Mercurial > hg > orthanc-stone
annotate Applications/Samples/SingleFrameEditorApplication.h @ 407:842a3c7cfdc0
renames
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 12 Nov 2018 11:44:20 +0100 |
parents | 99e31898910e |
children | 6834c236b36d |
rev | line source |
---|---|
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
1 /** |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2 * Stone of Orthanc |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
4 * Department, University Hospital of Liege, Belgium |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
6 * |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
7 * This program is free software: you can redistribute it and/or |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
8 * modify it under the terms of the GNU Affero General Public License |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
9 * as published by the Free Software Foundation, either version 3 of |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
10 * the License, or (at your option) any later version. |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
11 * |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
12 * This program is distributed in the hope that it will be useful, but |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
13 * WITHOUT ANY WARRANTY; without even the implied warranty of |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
15 * Affero General Public License for more details. |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
16 * |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
17 * You should have received a copy of the GNU Affero General Public License |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
19 **/ |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
20 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
21 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
22 #pragma once |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
23 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
24 #include "SampleApplicationBase.h" |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
25 |
339 | 26 #include "../../Framework/Toolbox/ImageGeometry.h" |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
27 #include "../../Framework/Toolbox/OrthancApiClient.h" |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
28 #include "../../Framework/Toolbox/DicomFrameConverter.h" |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
29 |
343 | 30 #include <Core/Images/FontRegistry.h> |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
31 #include <Core/Images/Image.h> |
339 | 32 #include <Core/Images/ImageProcessing.h> |
338 | 33 #include <Core/Images/PamReader.h> |
361
f559ac66ef55
first export of a dicom image
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
360
diff
changeset
|
34 #include <Core/Images/PamWriter.h> |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
35 #include <Core/Images/PngWriter.h> |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
36 #include <Core/Logging.h> |
403 | 37 #include <Core/OrthancException.h> |
361
f559ac66ef55
first export of a dicom image
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
360
diff
changeset
|
38 #include <Core/Toolbox.h> |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
39 #include <Plugins/Samples/Common/DicomDatasetReader.h> |
338 | 40 #include <Plugins/Samples/Common/FullOrthancDataset.h> |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
41 |
407 | 42 |
43 // Export using PAM is faster than using PNG, but requires Orthanc | |
44 // core >= 1.4.3 | |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
45 #define EXPORT_USING_PAM 1 |
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
46 |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
47 |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
48 #include <boost/math/constants/constants.hpp> |
376
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
49 #include <boost/math/special_functions/round.hpp> |
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
50 |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
51 |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
52 namespace OrthancStone |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
53 { |
407 | 54 class RadiologyScene : |
337 | 55 public IObserver, |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
56 public IObservable |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
57 { |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
58 public: |
407 | 59 typedef OriginMessage<MessageType_Widget_GeometryChanged, RadiologyScene> GeometryChangedMessage; |
60 typedef OriginMessage<MessageType_Widget_ContentChanged, RadiologyScene> ContentChangedMessage; | |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
61 |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
62 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
63 enum Corner |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
64 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
65 Corner_TopLeft, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
66 Corner_TopRight, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
67 Corner_BottomLeft, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
68 Corner_BottomRight |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
69 }; |
354 | 70 |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
71 |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
72 |
407 | 73 class Layer : public boost::noncopyable |
338 | 74 { |
407 | 75 friend class RadiologyScene; |
76 | |
338 | 77 private: |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
78 size_t index_; |
343 | 79 bool hasSize_; |
80 unsigned int width_; | |
81 unsigned int height_; | |
82 bool hasCrop_; | |
83 unsigned int cropX_; | |
84 unsigned int cropY_; | |
85 unsigned int cropWidth_; | |
86 unsigned int cropHeight_; | |
87 Matrix transform_; | |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
88 Matrix transformInverse_; |
343 | 89 double pixelSpacingX_; |
90 double pixelSpacingY_; | |
91 double panX_; | |
92 double panY_; | |
346 | 93 double angle_; |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
94 bool resizeable_; |
338 | 95 |
342 | 96 |
348 | 97 protected: |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
98 const Matrix& GetTransform() const |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
99 { |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
100 return transform_; |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
101 } |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
102 |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
103 |
348 | 104 private: |
346 | 105 static void ApplyTransform(double& x /* inout */, |
106 double& y /* inout */, | |
107 const Matrix& transform) | |
339 | 108 { |
109 Vector p; | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
110 LinearAlgebra::AssignVector(p, x, y, 1); |
339 | 111 |
346 | 112 Vector q = LinearAlgebra::Product(transform, p); |
339 | 113 |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
114 if (!LinearAlgebra::IsNear(q[2], 1.0)) |
339 | 115 { |
116 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
117 } | |
118 else | |
119 { | |
345 | 120 x = q[0]; |
121 y = q[1]; | |
339 | 122 } |
123 } | |
124 | |
345 | 125 |
346 | 126 void UpdateTransform() |
127 { | |
128 transform_ = CreateScalingMatrix(pixelSpacingX_, pixelSpacingY_); | |
129 | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
130 double centerX, centerY; |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
131 GetCenter(centerX, centerY); |
346 | 132 |
133 transform_ = LinearAlgebra::Product( | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
134 CreateOffsetMatrix(panX_ + centerX, panY_ + centerY), |
346 | 135 CreateRotationMatrix(angle_), |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
136 CreateOffsetMatrix(-centerX, -centerY), |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
137 transform_); |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
138 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
139 LinearAlgebra::InvertMatrix(transformInverse_, transform_); |
346 | 140 } |
141 | |
142 | |
345 | 143 void AddToExtent(Extent2D& extent, |
144 double x, | |
145 double y) const | |
146 { | |
346 | 147 ApplyTransform(x, y, transform_); |
345 | 148 extent.AddPoint(x, y); |
149 } | |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
150 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
151 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
152 void GetCornerInternal(double& x, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
153 double& y, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
154 Corner corner, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
155 unsigned int cropX, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
156 unsigned int cropY, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
157 unsigned int cropWidth, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
158 unsigned int cropHeight) const |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
159 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
160 double dx = static_cast<double>(cropX); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
161 double dy = static_cast<double>(cropY); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
162 double dwidth = static_cast<double>(cropWidth); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
163 double dheight = static_cast<double>(cropHeight); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
164 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
165 switch (corner) |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
166 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
167 case Corner_TopLeft: |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
168 x = dx; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
169 y = dy; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
170 break; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
171 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
172 case Corner_TopRight: |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
173 x = dx + dwidth; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
174 y = dy; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
175 break; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
176 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
177 case Corner_BottomLeft: |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
178 x = dx; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
179 y = dy + dheight; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
180 break; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
181 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
182 case Corner_BottomRight: |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
183 x = dx + dwidth; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
184 y = dy + dheight; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
185 break; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
186 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
187 default: |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
188 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
189 } |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
190 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
191 ApplyTransform(x, y, transform_); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
192 } |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
193 |
339 | 194 |
407 | 195 void SetIndex(size_t index) |
196 { | |
197 index_ = index; | |
198 } | |
199 | |
200 | |
201 bool Contains(double x, | |
202 double y) const | |
203 { | |
204 ApplyTransform(x, y, transformInverse_); | |
205 | |
206 unsigned int cropX, cropY, cropWidth, cropHeight; | |
207 GetCrop(cropX, cropY, cropWidth, cropHeight); | |
208 | |
209 return (x >= cropX && x <= cropX + cropWidth && | |
210 y >= cropY && y <= cropY + cropHeight); | |
211 } | |
212 | |
213 | |
214 void DrawBorders(CairoContext& context, | |
215 double zoom) | |
216 { | |
217 unsigned int cx, cy, width, height; | |
218 GetCrop(cx, cy, width, height); | |
219 | |
220 double dx = static_cast<double>(cx); | |
221 double dy = static_cast<double>(cy); | |
222 double dwidth = static_cast<double>(width); | |
223 double dheight = static_cast<double>(height); | |
224 | |
225 cairo_t* cr = context.GetObject(); | |
226 cairo_set_line_width(cr, 2.0 / zoom); | |
227 | |
228 double x, y; | |
229 x = dx; | |
230 y = dy; | |
231 ApplyTransform(x, y, transform_); | |
232 cairo_move_to(cr, x, y); | |
233 | |
234 x = dx + dwidth; | |
235 y = dy; | |
236 ApplyTransform(x, y, transform_); | |
237 cairo_line_to(cr, x, y); | |
238 | |
239 x = dx + dwidth; | |
240 y = dy + dheight; | |
241 ApplyTransform(x, y, transform_); | |
242 cairo_line_to(cr, x, y); | |
243 | |
244 x = dx; | |
245 y = dy + dheight; | |
246 ApplyTransform(x, y, transform_); | |
247 cairo_line_to(cr, x, y); | |
248 | |
249 x = dx; | |
250 y = dy; | |
251 ApplyTransform(x, y, transform_); | |
252 cairo_line_to(cr, x, y); | |
253 | |
254 cairo_stroke(cr); | |
255 } | |
256 | |
257 | |
258 static double Square(double x) | |
259 { | |
260 return x * x; | |
261 } | |
262 | |
263 | |
338 | 264 public: |
407 | 265 Layer() : |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
266 index_(0), |
343 | 267 hasSize_(false), |
339 | 268 width_(0), |
269 height_(0), | |
270 hasCrop_(false), | |
342 | 271 pixelSpacingX_(1), |
272 pixelSpacingY_(1), | |
273 panX_(0), | |
346 | 274 panY_(0), |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
275 angle_(0), |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
276 resizeable_(false) |
339 | 277 { |
342 | 278 UpdateTransform(); |
339 | 279 } |
280 | |
407 | 281 virtual ~Layer() |
343 | 282 { |
283 } | |
284 | |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
285 size_t GetIndex() const |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
286 { |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
287 return index_; |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
288 } |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
289 |
339 | 290 void ResetCrop() |
291 { | |
292 hasCrop_ = false; | |
293 } | |
294 | |
348 | 295 void SetCrop(unsigned int x, |
296 unsigned int y, | |
297 unsigned int width, | |
298 unsigned int height) | |
339 | 299 { |
348 | 300 if (!hasSize_) |
301 { | |
302 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
303 } | |
304 | |
305 if (x + width > width_ || | |
306 y + height > height_) | |
307 { | |
308 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
309 } | |
310 | |
339 | 311 hasCrop_ = true; |
312 cropX_ = x; | |
313 cropY_ = y; | |
314 cropWidth_ = width; | |
315 cropHeight_ = height; | |
348 | 316 |
317 UpdateTransform(); | |
339 | 318 } |
319 | |
320 void GetCrop(unsigned int& x, | |
321 unsigned int& y, | |
322 unsigned int& width, | |
323 unsigned int& height) const | |
338 | 324 { |
339 | 325 if (hasCrop_) |
326 { | |
327 x = cropX_; | |
328 y = cropY_; | |
329 width = cropWidth_; | |
330 height = cropHeight_; | |
331 } | |
332 else | |
333 { | |
334 x = 0; | |
335 y = 0; | |
336 width = width_; | |
337 height = height_; | |
338 } | |
339 } | |
340 | |
346 | 341 void SetAngle(double angle) |
342 { | |
343 angle_ = angle; | |
344 UpdateTransform(); | |
345 } | |
346 | |
347 double GetAngle() const | |
348 { | |
349 return angle_; | |
350 } | |
351 | |
343 | 352 void SetSize(unsigned int width, |
353 unsigned int height) | |
338 | 354 { |
343 | 355 if (hasSize_ && |
356 (width != width_ || | |
357 height != height_)) | |
339 | 358 { |
343 | 359 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
360 } |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
361 |
343 | 362 hasSize_ = true; |
363 width_ = width; | |
364 height_ = height; | |
346 | 365 |
366 UpdateTransform(); | |
338 | 367 } |
368 | |
343 | 369 |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
370 unsigned int GetWidth() const |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
371 { |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
372 return width_; |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
373 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
374 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
375 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
376 unsigned int GetHeight() const |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
377 { |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
378 return height_; |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
379 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
380 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
381 |
339 | 382 Extent2D GetExtent() const |
383 { | |
384 Extent2D extent; | |
385 | |
386 unsigned int x, y, width, height; | |
387 GetCrop(x, y, width, height); | |
388 | |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
389 double dx = static_cast<double>(x); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
390 double dy = static_cast<double>(y); |
339 | 391 double dwidth = static_cast<double>(width); |
392 double dheight = static_cast<double>(height); | |
342 | 393 |
339 | 394 AddToExtent(extent, dx, dy); |
395 AddToExtent(extent, dx + dwidth, dy); | |
396 AddToExtent(extent, dx, dy + dheight); | |
397 AddToExtent(extent, dx + dwidth, dy + dheight); | |
398 | |
399 return extent; | |
400 } | |
401 | |
402 | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
403 bool GetPixel(unsigned int& imageX, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
404 unsigned int& imageY, |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
405 double sceneX, |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
406 double sceneY) const |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
407 { |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
408 if (width_ == 0 || |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
409 height_ == 0) |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
410 { |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
411 return false; |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
412 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
413 else |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
414 { |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
415 ApplyTransform(sceneX, sceneY, transformInverse_); |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
416 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
417 int x = static_cast<int>(std::floor(sceneX)); |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
418 int y = static_cast<int>(std::floor(sceneY)); |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
419 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
420 if (x < 0) |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
421 { |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
422 imageX = 0; |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
423 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
424 else if (x >= static_cast<int>(width_)) |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
425 { |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
426 imageX = width_; |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
427 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
428 else |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
429 { |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
430 imageX = static_cast<unsigned int>(x); |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
431 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
432 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
433 if (y < 0) |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
434 { |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
435 imageY = 0; |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
436 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
437 else if (y >= static_cast<int>(height_)) |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
438 { |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
439 imageY = height_; |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
440 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
441 else |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
442 { |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
443 imageY = static_cast<unsigned int>(y); |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
444 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
445 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
446 return true; |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
447 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
448 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
449 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
450 |
342 | 451 void SetPan(double x, |
452 double y) | |
453 { | |
454 panX_ = x; | |
455 panY_ = y; | |
456 UpdateTransform(); | |
457 } | |
458 | |
459 | |
343 | 460 void SetPixelSpacing(double x, |
461 double y) | |
462 { | |
463 pixelSpacingX_ = x; | |
464 pixelSpacingY_ = y; | |
465 UpdateTransform(); | |
466 } | |
467 | |
345 | 468 double GetPixelSpacingX() const |
469 { | |
470 return pixelSpacingX_; | |
471 } | |
472 | |
473 double GetPixelSpacingY() const | |
474 { | |
475 return pixelSpacingY_; | |
476 } | |
343 | 477 |
342 | 478 double GetPanX() const |
479 { | |
480 return panX_; | |
481 } | |
482 | |
483 double GetPanY() const | |
484 { | |
485 return panY_; | |
486 } | |
343 | 487 |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
488 void GetCenter(double& centerX, |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
489 double& centerY) const |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
490 { |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
491 centerX = static_cast<double>(width_) / 2.0; |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
492 centerY = static_cast<double>(height_) / 2.0; |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
493 ApplyTransform(centerX, centerY, transform_); |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
494 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
495 |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
496 |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
497 void GetCorner(double& x /* out */, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
498 double& y /* out */, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
499 Corner corner) const |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
500 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
501 unsigned int cropX, cropY, cropWidth, cropHeight; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
502 GetCrop(cropX, cropY, cropWidth, cropHeight); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
503 GetCornerInternal(x, y, corner, cropX, cropY, cropWidth, cropHeight); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
504 } |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
505 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
506 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
507 bool LookupCorner(Corner& corner /* out */, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
508 double x, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
509 double y, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
510 double zoom, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
511 double viewportDistance) const |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
512 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
513 static const Corner CORNERS[] = { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
514 Corner_TopLeft, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
515 Corner_TopRight, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
516 Corner_BottomLeft, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
517 Corner_BottomRight |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
518 }; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
519 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
520 unsigned int cropX, cropY, cropWidth, cropHeight; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
521 GetCrop(cropX, cropY, cropWidth, cropHeight); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
522 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
523 double threshold = Square(viewportDistance / zoom); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
524 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
525 for (size_t i = 0; i < 4; i++) |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
526 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
527 double cx, cy; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
528 GetCornerInternal(cx, cy, CORNERS[i], cropX, cropY, cropWidth, cropHeight); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
529 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
530 double d = Square(cx - x) + Square(cy - y); |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
531 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
532 if (d <= threshold) |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
533 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
534 corner = CORNERS[i]; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
535 return true; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
536 } |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
537 } |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
538 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
539 return false; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
540 } |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
541 |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
542 bool IsResizeable() const |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
543 { |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
544 return resizeable_; |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
545 } |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
546 |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
547 void SetResizeable(bool resizeable) |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
548 { |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
549 resizeable_ = resizeable; |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
550 } |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
551 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
552 virtual bool GetDefaultWindowing(float& center, |
407 | 553 float& width) const = 0; |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
554 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
555 virtual void Render(Orthanc::ImageAccessor& buffer, |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
556 const Matrix& viewTransform, |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
557 ImageInterpolation interpolation) const = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
558 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
559 virtual bool GetRange(float& minValue, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
560 float& maxValue) const = 0; |
338 | 561 }; |
562 | |
563 | |
407 | 564 class LayerAccessor : public boost::noncopyable |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
565 { |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
566 private: |
407 | 567 RadiologyScene& scene_; |
568 size_t index_; | |
569 Layer* layer_; | |
343 | 570 |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
571 public: |
407 | 572 LayerAccessor(RadiologyScene& scene, |
573 size_t index) : | |
574 scene_(scene), | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
575 index_(index) |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
576 { |
407 | 577 Layers::iterator layer = scene.layers_.find(index); |
578 if (layer == scene.layers_.end()) | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
579 { |
407 | 580 layer_ = NULL; |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
581 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
582 else |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
583 { |
407 | 584 assert(layer->second != NULL); |
585 layer_ = layer->second; | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
586 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
587 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
588 |
407 | 589 LayerAccessor(RadiologyScene& scene, |
590 double x, | |
591 double y) : | |
592 scene_(scene), | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
593 index_(0) // Dummy initialization |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
594 { |
407 | 595 if (scene.LookupLayer(index_, x, y)) |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
596 { |
407 | 597 Layers::iterator layer = scene.layers_.find(index_); |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
598 |
407 | 599 if (layer == scene.layers_.end()) |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
600 { |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
601 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
602 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
603 else |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
604 { |
407 | 605 assert(layer->second != NULL); |
606 layer_ = layer->second; | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
607 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
608 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
609 else |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
610 { |
407 | 611 layer_ = NULL; |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
612 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
613 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
614 |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
615 void Invalidate() |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
616 { |
407 | 617 layer_ = NULL; |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
618 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
619 |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
620 bool IsValid() const |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
621 { |
407 | 622 return layer_ != NULL; |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
623 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
624 |
407 | 625 RadiologyScene& GetScene() const |
354 | 626 { |
627 if (IsValid()) | |
628 { | |
407 | 629 return scene_; |
354 | 630 } |
631 else | |
632 { | |
633 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
634 } | |
635 } | |
636 | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
637 size_t GetIndex() const |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
638 { |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
639 if (IsValid()) |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
640 { |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
641 return index_; |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
642 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
643 else |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
644 { |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
645 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
646 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
647 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
648 |
407 | 649 Layer& GetLayer() const |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
650 { |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
651 if (IsValid()) |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
652 { |
407 | 653 return *layer_; |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
654 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
655 else |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
656 { |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
657 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
658 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
659 } |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
660 }; |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
661 |
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
662 |
407 | 663 private: |
664 class AlphaLayer : public Layer | |
354 | 665 { |
666 private: | |
407 | 667 const RadiologyScene& scene_; |
354 | 668 std::auto_ptr<Orthanc::ImageAccessor> alpha_; // Grayscale8 |
669 bool useWindowing_; | |
670 float foreground_; | |
671 | |
672 public: | |
407 | 673 AlphaLayer(const RadiologyScene& scene) : |
674 scene_(scene), | |
354 | 675 useWindowing_(true), |
676 foreground_(0) | |
677 { | |
678 } | |
679 | |
680 | |
681 void SetForegroundValue(float foreground) | |
682 { | |
683 useWindowing_ = false; | |
684 foreground_ = foreground; | |
685 } | |
686 | |
687 | |
688 void SetAlpha(Orthanc::ImageAccessor* image) | |
689 { | |
690 std::auto_ptr<Orthanc::ImageAccessor> raii(image); | |
691 | |
692 if (image == NULL) | |
693 { | |
694 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
695 } | |
696 | |
697 if (image->GetFormat() != Orthanc::PixelFormat_Grayscale8) | |
698 { | |
699 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
700 } | |
701 | |
702 SetSize(image->GetWidth(), image->GetHeight()); | |
703 alpha_ = raii; | |
704 } | |
705 | |
706 | |
707 void LoadText(const Orthanc::Font& font, | |
708 const std::string& utf8) | |
709 { | |
710 SetAlpha(font.RenderAlpha(utf8)); | |
711 } | |
712 | |
713 | |
407 | 714 virtual bool GetDefaultWindowing(float& center, |
715 float& width) const | |
716 { | |
717 return false; | |
718 } | |
719 | |
720 | |
354 | 721 virtual void Render(Orthanc::ImageAccessor& buffer, |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
722 const Matrix& viewTransform, |
354 | 723 ImageInterpolation interpolation) const |
724 { | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
725 if (alpha_.get() == NULL) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
726 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
727 return; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
728 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
729 |
354 | 730 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) |
731 { | |
732 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
733 } | |
734 | |
735 unsigned int cropX, cropY, cropWidth, cropHeight; | |
736 GetCrop(cropX, cropY, cropWidth, cropHeight); | |
737 | |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
738 Matrix m = LinearAlgebra::Product(viewTransform, |
354 | 739 GetTransform(), |
740 CreateOffsetMatrix(cropX, cropY)); | |
741 | |
742 Orthanc::ImageAccessor cropped; | |
743 alpha_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); | |
744 | |
745 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); | |
746 ApplyProjectiveTransform(tmp, cropped, m, interpolation, true /* clear */); | |
747 | |
748 // Blit | |
749 const unsigned int width = buffer.GetWidth(); | |
750 const unsigned int height = buffer.GetHeight(); | |
751 | |
752 float value = foreground_; | |
753 | |
754 if (useWindowing_) | |
755 { | |
756 float center, width; | |
407 | 757 if (scene_.GetWindowing(center, width)) |
354 | 758 { |
759 value = center + width / 2.0f; | |
760 } | |
761 } | |
762 | |
763 for (unsigned int y = 0; y < height; y++) | |
764 { | |
765 float *q = reinterpret_cast<float*>(buffer.GetRow(y)); | |
766 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)); | |
767 | |
768 for (unsigned int x = 0; x < width; x++, p++, q++) | |
769 { | |
770 float a = static_cast<float>(*p) / 255.0f; | |
771 | |
772 *q = (a * value + (1.0f - a) * (*q)); | |
773 } | |
774 } | |
775 } | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
776 |
407 | 777 |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
778 virtual bool GetRange(float& minValue, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
779 float& maxValue) const |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
780 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
781 if (useWindowing_) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
782 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
783 return false; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
784 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
785 else |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
786 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
787 minValue = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
788 maxValue = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
789 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
790 if (foreground_ < 0) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
791 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
792 minValue = foreground_; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
793 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
794 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
795 if (foreground_ > 0) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
796 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
797 maxValue = foreground_; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
798 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
799 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
800 return true; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
801 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
802 } |
354 | 803 }; |
804 | |
805 | |
806 | |
347
cd65103c9172
RotateBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
346
diff
changeset
|
807 private: |
392 | 808 static Matrix CreateOffsetMatrix(double dx, |
809 double dy) | |
810 { | |
811 Matrix m = LinearAlgebra::IdentityMatrix(3); | |
812 m(0, 2) = dx; | |
813 m(1, 2) = dy; | |
814 return m; | |
815 } | |
816 | |
817 | |
818 static Matrix CreateScalingMatrix(double sx, | |
819 double sy) | |
820 { | |
821 Matrix m = LinearAlgebra::IdentityMatrix(3); | |
822 m(0, 0) = sx; | |
823 m(1, 1) = sy; | |
824 return m; | |
825 } | |
826 | |
827 | |
828 static Matrix CreateRotationMatrix(double angle) | |
829 { | |
830 Matrix m; | |
831 const double v[] = { cos(angle), -sin(angle), 0, | |
832 sin(angle), cos(angle), 0, | |
833 0, 0, 1 }; | |
834 LinearAlgebra::FillMatrix(m, 3, 3, v); | |
835 return m; | |
836 } | |
837 | |
838 | |
407 | 839 class DicomLayer : public Layer |
343 | 840 { |
841 private: | |
842 std::auto_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData | |
843 std::auto_ptr<DicomFrameConverter> converter_; | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
844 std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32 |
343 | 845 |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
846 static OrthancPlugins::DicomTag ConvertTag(const Orthanc::DicomTag& tag) |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
847 { |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
848 return OrthancPlugins::DicomTag(tag.GetGroup(), tag.GetElement()); |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
849 } |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
850 |
343 | 851 |
852 void ApplyConverter() | |
853 { | |
854 if (source_.get() != NULL && | |
855 converter_.get() != NULL) | |
856 { | |
857 converted_.reset(converter_->ConvertFrame(*source_)); | |
858 } | |
859 } | |
860 | |
861 public: | |
862 void SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset) | |
863 { | |
864 converter_.reset(new DicomFrameConverter); | |
865 converter_->ReadParameters(dataset); | |
866 ApplyConverter(); | |
867 | |
868 std::string tmp; | |
869 Vector pixelSpacing; | |
870 | |
871 if (dataset.GetStringValue(tmp, ConvertTag(Orthanc::DICOM_TAG_PIXEL_SPACING)) && | |
872 LinearAlgebra::ParseVector(pixelSpacing, tmp) && | |
873 pixelSpacing.size() == 2) | |
874 { | |
875 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); | |
876 } | |
877 | |
348 | 878 //SetPan(-0.5 * GetPixelSpacingX(), -0.5 * GetPixelSpacingY()); |
345 | 879 |
343 | 880 OrthancPlugins::DicomDatasetReader reader(dataset); |
881 | |
882 unsigned int width, height; | |
883 if (!reader.GetUnsignedIntegerValue(width, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) || | |
884 !reader.GetUnsignedIntegerValue(height, ConvertTag(Orthanc::DICOM_TAG_ROWS))) | |
885 { | |
886 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
887 } | |
888 else | |
889 { | |
890 SetSize(width, height); | |
891 } | |
892 } | |
893 | |
894 | |
895 void SetSourceImage(Orthanc::ImageAccessor* image) // Takes ownership | |
896 { | |
897 std::auto_ptr<Orthanc::ImageAccessor> raii(image); | |
898 | |
899 if (image == NULL) | |
900 { | |
901 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
902 } | |
903 | |
904 SetSize(image->GetWidth(), image->GetHeight()); | |
905 | |
906 source_ = raii; | |
907 ApplyConverter(); | |
908 } | |
909 | |
910 | |
911 virtual void Render(Orthanc::ImageAccessor& buffer, | |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
912 const Matrix& viewTransform, |
345 | 913 ImageInterpolation interpolation) const |
343 | 914 { |
915 if (converted_.get() != NULL) | |
916 { | |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
917 if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
918 { |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
919 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
920 } |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
921 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
922 unsigned int cropX, cropY, cropWidth, cropHeight; |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
923 GetCrop(cropX, cropY, cropWidth, cropHeight); |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
924 |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
925 Matrix m = LinearAlgebra::Product(viewTransform, |
351
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
926 GetTransform(), |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
927 CreateOffsetMatrix(cropX, cropY)); |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
928 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
929 Orthanc::ImageAccessor cropped; |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
930 converted_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
931 |
da25d2423314
CornerBitmapTracker to crop images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
350
diff
changeset
|
932 ApplyProjectiveTransform(buffer, cropped, m, interpolation, false); |
343 | 933 } |
934 } | |
935 | |
936 | |
937 virtual bool GetDefaultWindowing(float& center, | |
938 float& width) const | |
939 { | |
940 if (converter_.get() != NULL && | |
941 converter_->HasDefaultWindow()) | |
942 { | |
943 center = static_cast<float>(converter_->GetDefaultWindowCenter()); | |
944 width = static_cast<float>(converter_->GetDefaultWindowWidth()); | |
945 return true; | |
946 } | |
947 else | |
948 { | |
949 return false; | |
950 } | |
951 } | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
952 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
953 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
954 virtual bool GetRange(float& minValue, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
955 float& maxValue) const |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
956 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
957 if (converted_.get() != NULL) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
958 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
959 if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
960 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
961 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
962 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
963 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
964 Orthanc::ImageProcessing::GetMinMaxFloatValue(minValue, maxValue, *converted_); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
965 return true; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
966 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
967 else |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
968 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
969 return false; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
970 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
971 } |
343 | 972 }; |
973 | |
974 | |
975 | |
976 | |
407 | 977 typedef std::map<size_t, Layer*> Layers; |
338 | 978 |
341 | 979 OrthancApiClient& orthanc_; |
407 | 980 size_t countLayers_; |
341 | 981 bool hasWindowing_; |
982 float windowingCenter_; | |
983 float windowingWidth_; | |
407 | 984 Layers layers_; |
985 | |
986 | |
987 Layer& RegisterLayer(Layer* layer) | |
988 { | |
989 if (layer == NULL) | |
990 { | |
991 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
992 } | |
993 | |
994 std::auto_ptr<Layer> raii(layer); | |
995 | |
996 size_t index = countLayers_++; | |
997 raii->SetIndex(index); | |
998 layers_[index] = raii.release(); | |
999 | |
1000 EmitMessage(GeometryChangedMessage(*this)); | |
1001 EmitMessage(ContentChangedMessage(*this)); | |
1002 | |
1003 return *layer; | |
1004 } | |
1005 | |
338 | 1006 |
1007 public: | |
407 | 1008 RadiologyScene(MessageBroker& broker, |
1009 OrthancApiClient& orthanc) : | |
338 | 1010 IObserver(broker), |
1011 IObservable(broker), | |
1012 orthanc_(orthanc), | |
407 | 1013 countLayers_(0), |
338 | 1014 hasWindowing_(false), |
1015 windowingCenter_(0), // Dummy initialization | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1016 windowingWidth_(0) // Dummy initialization |
338 | 1017 { |
1018 } | |
1019 | |
345 | 1020 |
407 | 1021 virtual ~RadiologyScene() |
338 | 1022 { |
407 | 1023 for (Layers::iterator it = layers_.begin(); it != layers_.end(); it++) |
338 | 1024 { |
1025 assert(it->second != NULL); | |
1026 delete it->second; | |
1027 } | |
1028 } | |
339 | 1029 |
1030 | |
343 | 1031 bool GetWindowing(float& center, |
1032 float& width) const | |
339 | 1033 { |
1034 if (hasWindowing_) | |
1035 { | |
1036 center = windowingCenter_; | |
1037 width = windowingWidth_; | |
343 | 1038 return true; |
339 | 1039 } |
1040 else | |
1041 { | |
343 | 1042 return false; |
339 | 1043 } |
1044 } | |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1045 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1046 |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1047 void GetWindowingWithDefault(float& center, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1048 float& width) const |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1049 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1050 if (!GetWindowing(center, width)) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1051 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1052 center = 128; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1053 width = 256; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1054 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1055 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1056 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1057 |
350
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1058 void SetWindowing(float center, |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1059 float width) |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1060 |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1061 { |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1062 hasWindowing_ = true; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1063 windowingCenter_ = center; |
c57e049ed079
drawing corners for cropping
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
348
diff
changeset
|
1064 windowingWidth_ = width; |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1065 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1066 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1067 |
407 | 1068 Layer& LoadText(const Orthanc::Font& font, |
1069 const std::string& utf8) | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1070 { |
407 | 1071 std::auto_ptr<AlphaLayer> alpha(new AlphaLayer(*this)); |
352
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
1072 alpha->LoadText(font, utf8); |
d95e65ebe0b9
ResizeBitmapTracker
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
351
diff
changeset
|
1073 |
407 | 1074 return RegisterLayer(alpha.release()); |
348 | 1075 } |
1076 | |
1077 | |
407 | 1078 Layer& LoadTestBlock(unsigned int width, |
1079 unsigned int height) | |
348 | 1080 { |
1081 std::auto_ptr<Orthanc::Image> block(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false)); | |
1082 | |
1083 for (unsigned int padding = 0; | |
1084 (width > 2 * padding) && (height > 2 * padding); | |
1085 padding++) | |
1086 { | |
1087 uint8_t color; | |
1088 if (255 > 10 * padding) | |
1089 { | |
1090 color = 255 - 10 * padding; | |
1091 } | |
1092 else | |
1093 { | |
1094 color = 0; | |
1095 } | |
1096 | |
1097 Orthanc::ImageAccessor region; | |
1098 block->GetRegion(region, padding, padding, width - 2 * padding, height - 2 * padding); | |
1099 Orthanc::ImageProcessing::Set(region, color); | |
1100 } | |
1101 | |
407 | 1102 std::auto_ptr<AlphaLayer> alpha(new AlphaLayer(*this)); |
348 | 1103 alpha->SetAlpha(block.release()); |
343 | 1104 |
407 | 1105 return RegisterLayer(alpha.release()); |
343 | 1106 } |
1107 | |
1108 | |
407 | 1109 Layer& LoadDicomFrame(const std::string& instance, |
1110 unsigned int frame, | |
1111 bool httpCompression) | |
338 | 1112 { |
407 | 1113 Layer& layer = RegisterLayer(new DicomLayer); |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1114 |
338 | 1115 { |
1116 IWebService::Headers headers; | |
1117 std::string uri = "/instances/" + instance + "/tags"; | |
1118 orthanc_.GetBinaryAsync(uri, headers, | |
407 | 1119 new Callable<RadiologyScene, OrthancApiClient::BinaryResponseReadyMessage> |
1120 (*this, &RadiologyScene::OnTagsReceived), NULL, | |
1121 new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); | |
338 | 1122 } |
1123 | |
1124 { | |
1125 IWebService::Headers headers; | |
1126 headers["Accept"] = "image/x-portable-arbitrarymap"; | |
1127 | |
1128 if (httpCompression) | |
1129 { | |
1130 headers["Accept-Encoding"] = "gzip"; | |
1131 } | |
1132 | |
1133 std::string uri = "/instances/" + instance + "/frames/" + boost::lexical_cast<std::string>(frame) + "/image-uint16"; | |
1134 orthanc_.GetBinaryAsync(uri, headers, | |
407 | 1135 new Callable<RadiologyScene, OrthancApiClient::BinaryResponseReadyMessage> |
1136 (*this, &RadiologyScene::OnFrameReceived), NULL, | |
1137 new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); | |
338 | 1138 } |
1139 | |
407 | 1140 return layer; |
338 | 1141 } |
1142 | |
1143 | |
1144 void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) | |
1145 { | |
377 | 1146 size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&>(message.GetPayload()).GetValue(); |
1147 | |
1148 LOG(INFO) << "JSON received: " << message.GetUri().c_str() | |
407 | 1149 << " (" << message.GetAnswerSize() << " bytes) for layer " << index; |
338 | 1150 |
407 | 1151 Layers::iterator layer = layers_.find(index); |
1152 if (layer != layers_.end()) | |
338 | 1153 { |
407 | 1154 assert(layer->second != NULL); |
338 | 1155 |
377 | 1156 OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer(), message.GetAnswerSize()); |
407 | 1157 dynamic_cast<DicomLayer*>(layer->second)->SetDicomTags(dicom); |
338 | 1158 |
1159 float c, w; | |
1160 if (!hasWindowing_ && | |
407 | 1161 layer->second->GetDefaultWindowing(c, w)) |
338 | 1162 { |
1163 hasWindowing_ = true; | |
1164 windowingCenter_ = c; | |
1165 windowingWidth_ = w; | |
1166 } | |
1167 | |
1168 EmitMessage(GeometryChangedMessage(*this)); | |
1169 } | |
1170 } | |
1171 | |
1172 | |
1173 void OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) | |
1174 { | |
377 | 1175 size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&>(message.GetPayload()).GetValue(); |
338 | 1176 |
377 | 1177 LOG(INFO) << "DICOM frame received: " << message.GetUri().c_str() |
407 | 1178 << " (" << message.GetAnswerSize() << " bytes) for layer " << index; |
341 | 1179 |
407 | 1180 Layers::iterator layer = layers_.find(index); |
1181 if (layer != layers_.end()) | |
338 | 1182 { |
407 | 1183 assert(layer->second != NULL); |
338 | 1184 |
1185 std::string content; | |
377 | 1186 if (message.GetAnswerSize() > 0) |
338 | 1187 { |
377 | 1188 content.assign(reinterpret_cast<const char*>(message.GetAnswer()), message.GetAnswerSize()); |
338 | 1189 } |
1190 | |
1191 std::auto_ptr<Orthanc::PamReader> reader(new Orthanc::PamReader); | |
1192 reader->ReadFromMemory(content); | |
407 | 1193 dynamic_cast<DicomLayer*>(layer->second)->SetSourceImage(reader.release()); |
338 | 1194 |
1195 EmitMessage(ContentChangedMessage(*this)); | |
1196 } | |
1197 } | |
339 | 1198 |
1199 | |
1200 Extent2D GetSceneExtent() const | |
1201 { | |
1202 Extent2D extent; | |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
1203 |
407 | 1204 for (Layers::const_iterator it = layers_.begin(); |
1205 it != layers_.end(); ++it) | |
339 | 1206 { |
1207 assert(it->second != NULL); | |
1208 extent.Union(it->second->GetExtent()); | |
1209 } | |
1210 | |
1211 return extent; | |
1212 } | |
1213 | |
1214 | |
1215 void Render(Orthanc::ImageAccessor& buffer, | |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
1216 const Matrix& viewTransform, |
345 | 1217 ImageInterpolation interpolation) const |
339 | 1218 { |
1219 Orthanc::ImageProcessing::Set(buffer, 0); | |
1220 | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1221 // Render layers in the background-to-foreground order |
407 | 1222 for (size_t index = 0; index < countLayers_; index++) |
339 | 1223 { |
407 | 1224 Layers::const_iterator it = layers_.find(index); |
1225 if (it != layers_.end()) | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1226 { |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1227 assert(it->second != NULL); |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
1228 it->second->Render(buffer, viewTransform, interpolation); |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1229 } |
339 | 1230 } |
1231 } | |
342 | 1232 |
1233 | |
407 | 1234 bool LookupLayer(size_t& index /* out */, |
1235 double x, | |
1236 double y) const | |
342 | 1237 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1238 // Render layers in the foreground-to-background order |
407 | 1239 for (size_t i = countLayers_; i > 0; i--) |
342 | 1240 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1241 index = i - 1; |
407 | 1242 Layers::const_iterator it = layers_.find(index); |
1243 if (it != layers_.end()) | |
342 | 1244 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1245 assert(it->second != NULL); |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1246 if (it->second->Contains(x, y)) |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1247 { |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1248 return true; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
1249 } |
342 | 1250 } |
1251 } | |
1252 | |
1253 return false; | |
1254 } | |
1255 | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1256 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1257 void DrawBorder(CairoContext& context, |
407 | 1258 unsigned int layer, |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1259 double zoom) |
345 | 1260 { |
407 | 1261 Layers::const_iterator found = layers_.find(layer); |
345 | 1262 |
407 | 1263 if (found != layers_.end()) |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1264 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1265 context.SetSourceColor(255, 0, 0); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1266 found->second->DrawBorders(context, zoom); |
345 | 1267 } |
1268 } | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1269 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1270 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1271 void GetRange(float& minValue, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1272 float& maxValue) const |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1273 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1274 bool first = true; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1275 |
407 | 1276 for (Layers::const_iterator it = layers_.begin(); |
1277 it != layers_.end(); it++) | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1278 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1279 assert(it->second != NULL); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1280 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1281 float a, b; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1282 if (it->second->GetRange(a, b)) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1283 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1284 if (first) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1285 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1286 minValue = a; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1287 maxValue = b; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1288 first = false; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1289 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1290 else |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1291 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1292 minValue = std::min(a, minValue); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1293 maxValue = std::max(b, maxValue); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1294 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1295 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1296 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1297 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1298 if (first) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1299 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1300 minValue = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1301 maxValue = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1302 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
1303 } |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1304 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1305 |
407 | 1306 // Export using PAM is faster than using PNG, but requires Orthanc |
1307 // core >= 1.4.3 | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1308 void Export(const Orthanc::DicomMap& dicom, |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1309 double pixelSpacingX, |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1310 double pixelSpacingY, |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1311 bool invert, |
407 | 1312 ImageInterpolation interpolation, |
1313 bool usePam) | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1314 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1315 if (pixelSpacingX <= 0 || |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1316 pixelSpacingY <= 0) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1317 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1318 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1319 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1320 |
407 | 1321 LOG(INFO) << "Exporting DICOM"; |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1322 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1323 Extent2D extent = GetSceneExtent(); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1324 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1325 int w = std::ceil(extent.GetWidth() / pixelSpacingX); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1326 int h = std::ceil(extent.GetHeight() / pixelSpacingY); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1327 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1328 if (w < 0 || h < 0) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1329 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1330 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1331 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1332 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1333 Orthanc::Image layers(Orthanc::PixelFormat_Float32, |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1334 static_cast<unsigned int>(w), |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1335 static_cast<unsigned int>(h), false); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1336 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1337 Matrix view = LinearAlgebra::Product( |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1338 CreateScalingMatrix(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1339 CreateOffsetMatrix(-extent.GetX1(), -extent.GetY1())); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1340 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1341 Render(layers, view, interpolation); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1342 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1343 Orthanc::Image rendered(Orthanc::PixelFormat_Grayscale16, |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1344 layers.GetWidth(), layers.GetHeight(), false); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1345 Orthanc::ImageProcessing::Convert(rendered, layers); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1346 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1347 std::string base64; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1348 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1349 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1350 std::string content; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1351 |
407 | 1352 if (usePam) |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1353 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1354 Orthanc::PamWriter writer; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1355 writer.WriteToMemory(content, rendered); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1356 } |
407 | 1357 else |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1358 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1359 Orthanc::PngWriter writer; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1360 writer.WriteToMemory(content, rendered); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1361 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1362 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1363 Orthanc::Toolbox::EncodeBase64(base64, content); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1364 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1365 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1366 std::set<Orthanc::DicomTag> tags; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1367 dicom.GetTags(tags); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1368 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1369 Json::Value json = Json::objectValue; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1370 json["Tags"] = Json::objectValue; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1371 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1372 for (std::set<Orthanc::DicomTag>::const_iterator |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1373 tag = tags.begin(); tag != tags.end(); ++tag) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1374 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1375 const Orthanc::DicomValue& value = dicom.GetValue(*tag); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1376 if (!value.IsNull() && |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1377 !value.IsBinary()) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1378 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1379 json["Tags"][tag->Format()] = value.GetContent(); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1380 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1381 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1382 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1383 json["Tags"][Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION.Format()] = |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1384 (invert ? "MONOCHROME1" : "MONOCHROME2"); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1385 |
407 | 1386 // WARNING: The order of PixelSpacing is Y/X. We use "%0.8f" to |
1387 // avoid floating-point numbers to grow over 16 characters, | |
1388 // which would be invalid according to DICOM standard | |
1389 // ("dciodvfy" would complain). | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1390 char buf[32]; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1391 sprintf(buf, "%0.8f\\%0.8f", pixelSpacingY, pixelSpacingX); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1392 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1393 json["Tags"][Orthanc::DICOM_TAG_PIXEL_SPACING.Format()] = buf; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1394 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1395 float center, width; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1396 if (GetWindowing(center, width)) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1397 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1398 json["Tags"][Orthanc::DICOM_TAG_WINDOW_CENTER.Format()] = |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1399 boost::lexical_cast<std::string>(boost::math::iround(center)); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1400 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1401 json["Tags"][Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()] = |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1402 boost::lexical_cast<std::string>(boost::math::iround(width)); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1403 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1404 |
407 | 1405 // This is Data URI scheme: https://en.wikipedia.org/wiki/Data_URI_scheme |
1406 json["Content"] = ("data:" + | |
1407 std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + | |
1408 ";base64," + base64); | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1409 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1410 orthanc_.PostJsonAsyncExpectJson( |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1411 "/tools/create-dicom", json, |
407 | 1412 new Callable<RadiologyScene, OrthancApiClient::JsonResponseReadyMessage> |
1413 (*this, &RadiologyScene::OnDicomExported), | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1414 NULL, NULL); |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1415 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1416 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1417 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1418 void OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1419 { |
407 | 1420 LOG(INFO) << "DICOM export was successful:" |
1421 << message.GetJson().toStyledString(); | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
1422 } |
338 | 1423 }; |
1424 | |
341 | 1425 |
354 | 1426 class UndoRedoStack : public boost::noncopyable |
1427 { | |
1428 public: | |
1429 class ICommand : public boost::noncopyable | |
1430 { | |
1431 public: | |
1432 virtual ~ICommand() | |
1433 { | |
1434 } | |
1435 | |
1436 virtual void Undo() const = 0; | |
1437 | |
1438 virtual void Redo() const = 0; | |
1439 }; | |
1440 | |
1441 private: | |
1442 typedef std::list<ICommand*> Stack; | |
1443 | |
1444 Stack stack_; | |
1445 Stack::iterator current_; | |
1446 | |
1447 void Clear(Stack::iterator from) | |
1448 { | |
1449 for (Stack::iterator it = from; it != stack_.end(); ++it) | |
1450 { | |
1451 assert(*it != NULL); | |
1452 delete *it; | |
1453 } | |
1454 | |
1455 stack_.erase(from, stack_.end()); | |
1456 } | |
1457 | |
1458 public: | |
1459 UndoRedoStack() : | |
1460 current_(stack_.end()) | |
1461 { | |
1462 } | |
1463 | |
1464 ~UndoRedoStack() | |
1465 { | |
1466 Clear(stack_.begin()); | |
1467 } | |
1468 | |
1469 void Add(ICommand* command) | |
1470 { | |
1471 if (command == NULL) | |
1472 { | |
1473 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
1474 } | |
1475 | |
1476 Clear(current_); | |
1477 | |
1478 stack_.push_back(command); | |
1479 current_ = stack_.end(); | |
1480 } | |
1481 | |
1482 void Undo() | |
1483 { | |
1484 if (current_ != stack_.begin()) | |
1485 { | |
1486 --current_; | |
1487 | |
1488 assert(*current_ != NULL); | |
1489 (*current_)->Undo(); | |
1490 } | |
1491 } | |
1492 | |
1493 void Redo() | |
1494 { | |
1495 if (current_ != stack_.end()) | |
1496 { | |
1497 assert(*current_ != NULL); | |
1498 (*current_)->Redo(); | |
1499 | |
1500 ++current_; | |
1501 } | |
1502 } | |
1503 }; | |
1504 | |
1505 | |
407 | 1506 class RadiologyLayerCommand : public UndoRedoStack::ICommand |
354 | 1507 { |
1508 private: | |
407 | 1509 RadiologyScene& scene_; |
1510 size_t layer_; | |
354 | 1511 |
1512 protected: | |
407 | 1513 virtual void UndoInternal(RadiologyScene::Layer& layer) const = 0; |
1514 | |
1515 virtual void RedoInternal(RadiologyScene::Layer& layer) const = 0; | |
354 | 1516 |
1517 public: | |
407 | 1518 RadiologyLayerCommand(RadiologyScene& scene, |
1519 size_t layer) : | |
1520 scene_(scene), | |
1521 layer_(layer) | |
354 | 1522 { |
1523 } | |
1524 | |
407 | 1525 RadiologyLayerCommand(const RadiologyScene::LayerAccessor& accessor) : |
1526 scene_(accessor.GetScene()), | |
1527 layer_(accessor.GetIndex()) | |
354 | 1528 { |
1529 } | |
1530 | |
1531 virtual void Undo() const | |
1532 { | |
407 | 1533 RadiologyScene::LayerAccessor accessor(scene_, layer_); |
354 | 1534 |
1535 if (accessor.IsValid()) | |
1536 { | |
407 | 1537 UndoInternal(accessor.GetLayer()); |
354 | 1538 } |
1539 } | |
1540 | |
1541 virtual void Redo() const | |
1542 { | |
407 | 1543 RadiologyScene::LayerAccessor accessor(scene_, layer_); |
354 | 1544 |
1545 if (accessor.IsValid()) | |
1546 { | |
407 | 1547 RedoInternal(accessor.GetLayer()); |
354 | 1548 } |
1549 } | |
1550 }; | |
1551 | |
1552 | |
407 | 1553 class RadiologyLayerRotateTracker : public IWorldSceneMouseTracker |
354 | 1554 { |
1555 private: | |
407 | 1556 UndoRedoStack& undoRedoStack_; |
1557 RadiologyScene::LayerAccessor accessor_; | |
1558 double centerX_; | |
1559 double centerY_; | |
1560 double originalAngle_; | |
1561 double clickAngle_; | |
1562 bool roundAngles_; | |
354 | 1563 |
1564 bool ComputeAngle(double& angle /* out */, | |
1565 double sceneX, | |
1566 double sceneY) const | |
1567 { | |
1568 Vector u; | |
1569 LinearAlgebra::AssignVector(u, sceneX - centerX_, sceneY - centerY_); | |
1570 | |
1571 double nu = boost::numeric::ublas::norm_2(u); | |
1572 | |
1573 if (!LinearAlgebra::IsCloseToZero(nu)) | |
1574 { | |
1575 u /= nu; | |
1576 angle = atan2(u[1], u[0]); | |
1577 return true; | |
1578 } | |
1579 else | |
1580 { | |
1581 return false; | |
1582 } | |
1583 } | |
1584 | |
1585 | |
407 | 1586 class UndoRedoCommand : public RadiologyLayerCommand |
354 | 1587 { |
1588 private: | |
1589 double sourceAngle_; | |
1590 double targetAngle_; | |
1591 | |
1592 static int ToDegrees(double angle) | |
1593 { | |
376
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
1594 return boost::math::iround(angle * 180.0 / boost::math::constants::pi<double>()); |
354 | 1595 } |
1596 | |
1597 protected: | |
407 | 1598 virtual void UndoInternal(RadiologyScene::Layer& layer) const |
354 | 1599 { |
1600 LOG(INFO) << "Undo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; | |
407 | 1601 layer.SetAngle(sourceAngle_); |
354 | 1602 } |
1603 | |
407 | 1604 virtual void RedoInternal(RadiologyScene::Layer& layer) const |
354 | 1605 { |
1606 LOG(INFO) << "Redo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; | |
407 | 1607 layer.SetAngle(targetAngle_); |
354 | 1608 } |
1609 | |
1610 public: | |
407 | 1611 UndoRedoCommand(const RadiologyLayerRotateTracker& tracker) : |
1612 RadiologyLayerCommand(tracker.accessor_), | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1613 sourceAngle_(tracker.originalAngle_), |
407 | 1614 targetAngle_(tracker.accessor_.GetLayer().GetAngle()) |
354 | 1615 { |
1616 } | |
1617 }; | |
1618 | |
1619 | |
1620 public: | |
407 | 1621 RadiologyLayerRotateTracker(UndoRedoStack& undoRedoStack, |
1622 RadiologyScene& scene, | |
1623 const ViewportGeometry& view, | |
1624 size_t layer, | |
1625 double x, | |
1626 double y, | |
1627 bool roundAngles) : | |
354 | 1628 undoRedoStack_(undoRedoStack), |
407 | 1629 accessor_(scene, layer), |
354 | 1630 roundAngles_(roundAngles) |
1631 { | |
1632 if (accessor_.IsValid()) | |
1633 { | |
407 | 1634 accessor_.GetLayer().GetCenter(centerX_, centerY_); |
1635 originalAngle_ = accessor_.GetLayer().GetAngle(); | |
354 | 1636 |
1637 double sceneX, sceneY; | |
1638 view.MapDisplayToScene(sceneX, sceneY, x, y); | |
1639 | |
1640 if (!ComputeAngle(clickAngle_, x, y)) | |
1641 { | |
1642 accessor_.Invalidate(); | |
1643 } | |
1644 } | |
1645 } | |
1646 | |
1647 virtual bool HasRender() const | |
1648 { | |
1649 return false; | |
1650 } | |
1651 | |
1652 virtual void Render(CairoContext& context, | |
1653 double zoom) | |
1654 { | |
1655 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
1656 } | |
1657 | |
1658 virtual void MouseUp() | |
1659 { | |
1660 if (accessor_.IsValid()) | |
1661 { | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1662 undoRedoStack_.Add(new UndoRedoCommand(*this)); |
354 | 1663 } |
1664 } | |
1665 | |
1666 virtual void MouseMove(int displayX, | |
1667 int displayY, | |
1668 double sceneX, | |
1669 double sceneY) | |
1670 { | |
1671 static const double ROUND_ANGLE = 15.0 / 180.0 * boost::math::constants::pi<double>(); | |
1672 | |
1673 double angle; | |
1674 | |
1675 if (accessor_.IsValid() && | |
1676 ComputeAngle(angle, sceneX, sceneY)) | |
1677 { | |
1678 angle = angle - clickAngle_ + originalAngle_; | |
1679 | |
1680 if (roundAngles_) | |
1681 { | |
376
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
1682 angle = boost::math::round<double>((angle / ROUND_ANGLE) * ROUND_ANGLE); |
354 | 1683 } |
1684 | |
407 | 1685 accessor_.GetLayer().SetAngle(angle); |
354 | 1686 } |
1687 } | |
1688 }; | |
1689 | |
1690 | |
407 | 1691 class RadiologyLayerMoveTracker : public IWorldSceneMouseTracker |
354 | 1692 { |
1693 private: | |
407 | 1694 UndoRedoStack& undoRedoStack_; |
1695 RadiologyScene::LayerAccessor accessor_; | |
1696 double clickX_; | |
1697 double clickY_; | |
1698 double panX_; | |
1699 double panY_; | |
1700 bool oneAxis_; | |
1701 | |
1702 class UndoRedoCommand : public RadiologyLayerCommand | |
354 | 1703 { |
1704 private: | |
1705 double sourceX_; | |
1706 double sourceY_; | |
1707 double targetX_; | |
1708 double targetY_; | |
1709 | |
1710 protected: | |
407 | 1711 virtual void UndoInternal(RadiologyScene::Layer& layer) const |
354 | 1712 { |
407 | 1713 layer.SetPan(sourceX_, sourceY_); |
354 | 1714 } |
1715 | |
407 | 1716 virtual void RedoInternal(RadiologyScene::Layer& layer) const |
354 | 1717 { |
407 | 1718 layer.SetPan(targetX_, targetY_); |
354 | 1719 } |
1720 | |
1721 public: | |
407 | 1722 UndoRedoCommand(const RadiologyLayerMoveTracker& tracker) : |
1723 RadiologyLayerCommand(tracker.accessor_), | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1724 sourceX_(tracker.panX_), |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1725 sourceY_(tracker.panY_), |
407 | 1726 targetX_(tracker.accessor_.GetLayer().GetPanX()), |
1727 targetY_(tracker.accessor_.GetLayer().GetPanY()) | |
354 | 1728 { |
1729 } | |
1730 }; | |
1731 | |
1732 | |
1733 public: | |
407 | 1734 RadiologyLayerMoveTracker(UndoRedoStack& undoRedoStack, |
1735 RadiologyScene& scene, | |
1736 size_t layer, | |
1737 double x, | |
1738 double y, | |
1739 bool oneAxis) : | |
354 | 1740 undoRedoStack_(undoRedoStack), |
407 | 1741 accessor_(scene, layer), |
354 | 1742 clickX_(x), |
1743 clickY_(y), | |
1744 oneAxis_(oneAxis) | |
1745 { | |
1746 if (accessor_.IsValid()) | |
1747 { | |
407 | 1748 panX_ = accessor_.GetLayer().GetPanX(); |
1749 panY_ = accessor_.GetLayer().GetPanY(); | |
354 | 1750 } |
1751 } | |
1752 | |
1753 virtual bool HasRender() const | |
1754 { | |
1755 return false; | |
1756 } | |
1757 | |
1758 virtual void Render(CairoContext& context, | |
1759 double zoom) | |
1760 { | |
1761 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
1762 } | |
1763 | |
1764 virtual void MouseUp() | |
1765 { | |
1766 if (accessor_.IsValid()) | |
1767 { | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1768 undoRedoStack_.Add(new UndoRedoCommand(*this)); |
354 | 1769 } |
1770 } | |
1771 | |
1772 virtual void MouseMove(int displayX, | |
1773 int displayY, | |
1774 double sceneX, | |
1775 double sceneY) | |
1776 { | |
1777 if (accessor_.IsValid()) | |
1778 { | |
1779 double dx = sceneX - clickX_; | |
1780 double dy = sceneY - clickY_; | |
1781 | |
1782 if (oneAxis_) | |
1783 { | |
1784 if (fabs(dx) > fabs(dy)) | |
1785 { | |
407 | 1786 accessor_.GetLayer().SetPan(dx + panX_, panY_); |
354 | 1787 } |
1788 else | |
1789 { | |
407 | 1790 accessor_.GetLayer().SetPan(panX_, dy + panY_); |
354 | 1791 } |
1792 } | |
1793 else | |
1794 { | |
407 | 1795 accessor_.GetLayer().SetPan(dx + panX_, dy + panY_); |
354 | 1796 } |
1797 } | |
1798 } | |
1799 }; | |
1800 | |
1801 | |
407 | 1802 class RadiologyLayerCropTracker : public IWorldSceneMouseTracker |
354 | 1803 { |
1804 private: | |
407 | 1805 UndoRedoStack& undoRedoStack_; |
1806 RadiologyScene::LayerAccessor accessor_; | |
1807 RadiologyScene::Corner corner_; | |
1808 unsigned int cropX_; | |
1809 unsigned int cropY_; | |
1810 unsigned int cropWidth_; | |
1811 unsigned int cropHeight_; | |
1812 | |
1813 class UndoRedoCommand : public RadiologyLayerCommand | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1814 { |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1815 private: |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1816 unsigned int sourceCropX_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1817 unsigned int sourceCropY_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1818 unsigned int sourceCropWidth_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1819 unsigned int sourceCropHeight_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1820 unsigned int targetCropX_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1821 unsigned int targetCropY_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1822 unsigned int targetCropWidth_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1823 unsigned int targetCropHeight_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1824 |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1825 protected: |
407 | 1826 virtual void UndoInternal(RadiologyScene::Layer& layer) const |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1827 { |
407 | 1828 layer.SetCrop(sourceCropX_, sourceCropY_, sourceCropWidth_, sourceCropHeight_); |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1829 } |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1830 |
407 | 1831 virtual void RedoInternal(RadiologyScene::Layer& layer) const |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1832 { |
407 | 1833 layer.SetCrop(targetCropX_, targetCropY_, targetCropWidth_, targetCropHeight_); |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1834 } |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1835 |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1836 public: |
407 | 1837 UndoRedoCommand(const RadiologyLayerCropTracker& tracker) : |
1838 RadiologyLayerCommand(tracker.accessor_), | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1839 sourceCropX_(tracker.cropX_), |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1840 sourceCropY_(tracker.cropY_), |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1841 sourceCropWidth_(tracker.cropWidth_), |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1842 sourceCropHeight_(tracker.cropHeight_) |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1843 { |
407 | 1844 tracker.accessor_.GetLayer().GetCrop(targetCropX_, targetCropY_, |
1845 targetCropWidth_, targetCropHeight_); | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1846 } |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1847 }; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1848 |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1849 |
354 | 1850 public: |
407 | 1851 RadiologyLayerCropTracker(UndoRedoStack& undoRedoStack, |
1852 RadiologyScene& scene, | |
1853 const ViewportGeometry& view, | |
1854 size_t layer, | |
1855 double x, | |
1856 double y, | |
1857 RadiologyScene::Corner corner) : | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1858 undoRedoStack_(undoRedoStack), |
407 | 1859 accessor_(scene, layer), |
354 | 1860 corner_(corner) |
1861 { | |
1862 if (accessor_.IsValid()) | |
1863 { | |
407 | 1864 accessor_.GetLayer().GetCrop(cropX_, cropY_, cropWidth_, cropHeight_); |
354 | 1865 } |
1866 } | |
1867 | |
1868 virtual bool HasRender() const | |
1869 { | |
1870 return false; | |
1871 } | |
1872 | |
1873 virtual void Render(CairoContext& context, | |
1874 double zoom) | |
1875 { | |
1876 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
1877 } | |
1878 | |
1879 virtual void MouseUp() | |
1880 { | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1881 if (accessor_.IsValid()) |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1882 { |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1883 undoRedoStack_.Add(new UndoRedoCommand(*this)); |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1884 } |
354 | 1885 } |
1886 | |
1887 virtual void MouseMove(int displayX, | |
1888 int displayY, | |
1889 double sceneX, | |
1890 double sceneY) | |
1891 { | |
1892 if (accessor_.IsValid()) | |
1893 { | |
1894 unsigned int x, y; | |
1895 | |
407 | 1896 RadiologyScene::Layer& layer = accessor_.GetLayer(); |
1897 if (layer.GetPixel(x, y, sceneX, sceneY)) | |
354 | 1898 { |
1899 unsigned int targetX, targetWidth; | |
1900 | |
407 | 1901 if (corner_ == RadiologyScene::Corner_TopLeft || |
1902 corner_ == RadiologyScene::Corner_BottomLeft) | |
354 | 1903 { |
1904 targetX = std::min(x, cropX_ + cropWidth_); | |
1905 targetWidth = cropX_ + cropWidth_ - targetX; | |
1906 } | |
1907 else | |
1908 { | |
1909 targetX = cropX_; | |
1910 targetWidth = std::max(x, cropX_) - cropX_; | |
1911 } | |
1912 | |
1913 unsigned int targetY, targetHeight; | |
1914 | |
407 | 1915 if (corner_ == RadiologyScene::Corner_TopLeft || |
1916 corner_ == RadiologyScene::Corner_TopRight) | |
354 | 1917 { |
1918 targetY = std::min(y, cropY_ + cropHeight_); | |
1919 targetHeight = cropY_ + cropHeight_ - targetY; | |
1920 } | |
1921 else | |
1922 { | |
1923 targetY = cropY_; | |
1924 targetHeight = std::max(y, cropY_) - cropY_; | |
1925 } | |
1926 | |
407 | 1927 layer.SetCrop(targetX, targetY, targetWidth, targetHeight); |
354 | 1928 } |
1929 } | |
1930 } | |
1931 }; | |
1932 | |
1933 | |
407 | 1934 class RadiologyLayerResizeTracker : public IWorldSceneMouseTracker |
354 | 1935 { |
1936 private: | |
407 | 1937 UndoRedoStack& undoRedoStack_; |
1938 RadiologyScene::LayerAccessor accessor_; | |
1939 bool roundScaling_; | |
1940 double originalSpacingX_; | |
1941 double originalSpacingY_; | |
1942 double originalPanX_; | |
1943 double originalPanY_; | |
1944 RadiologyScene::Corner oppositeCorner_; | |
1945 double oppositeX_; | |
1946 double oppositeY_; | |
1947 double baseScaling_; | |
354 | 1948 |
1949 static double ComputeDistance(double x1, | |
1950 double y1, | |
1951 double x2, | |
1952 double y2) | |
1953 { | |
1954 double dx = x1 - x2; | |
1955 double dy = y1 - y2; | |
1956 return sqrt(dx * dx + dy * dy); | |
1957 } | |
1958 | |
407 | 1959 class UndoRedoCommand : public RadiologyLayerCommand |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1960 { |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1961 private: |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1962 double sourceSpacingX_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1963 double sourceSpacingY_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1964 double sourcePanX_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1965 double sourcePanY_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1966 double targetSpacingX_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1967 double targetSpacingY_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1968 double targetPanX_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1969 double targetPanY_; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1970 |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1971 protected: |
407 | 1972 virtual void UndoInternal(RadiologyScene::Layer& layer) const |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1973 { |
407 | 1974 layer.SetPixelSpacing(sourceSpacingX_, sourceSpacingY_); |
1975 layer.SetPan(sourcePanX_, sourcePanY_); | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1976 } |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1977 |
407 | 1978 virtual void RedoInternal(RadiologyScene::Layer& layer) const |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1979 { |
407 | 1980 layer.SetPixelSpacing(targetSpacingX_, targetSpacingY_); |
1981 layer.SetPan(targetPanX_, targetPanY_); | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1982 } |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1983 |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1984 public: |
407 | 1985 UndoRedoCommand(const RadiologyLayerResizeTracker& tracker) : |
1986 RadiologyLayerCommand(tracker.accessor_), | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1987 sourceSpacingX_(tracker.originalSpacingX_), |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1988 sourceSpacingY_(tracker.originalSpacingY_), |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1989 sourcePanX_(tracker.originalPanX_), |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1990 sourcePanY_(tracker.originalPanY_), |
407 | 1991 targetSpacingX_(tracker.accessor_.GetLayer().GetPixelSpacingX()), |
1992 targetSpacingY_(tracker.accessor_.GetLayer().GetPixelSpacingY()), | |
1993 targetPanX_(tracker.accessor_.GetLayer().GetPanX()), | |
1994 targetPanY_(tracker.accessor_.GetLayer().GetPanY()) | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1995 { |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1996 } |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1997 }; |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1998 |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
1999 |
354 | 2000 public: |
407 | 2001 RadiologyLayerResizeTracker(UndoRedoStack& undoRedoStack, |
2002 RadiologyScene& scene, | |
2003 size_t layer, | |
2004 double x, | |
2005 double y, | |
2006 RadiologyScene::Corner corner, | |
2007 bool roundScaling) : | |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
2008 undoRedoStack_(undoRedoStack), |
407 | 2009 accessor_(scene, layer), |
354 | 2010 roundScaling_(roundScaling) |
2011 { | |
2012 if (accessor_.IsValid() && | |
407 | 2013 accessor_.GetLayer().IsResizeable()) |
354 | 2014 { |
407 | 2015 originalSpacingX_ = accessor_.GetLayer().GetPixelSpacingX(); |
2016 originalSpacingY_ = accessor_.GetLayer().GetPixelSpacingY(); | |
2017 originalPanX_ = accessor_.GetLayer().GetPanX(); | |
2018 originalPanY_ = accessor_.GetLayer().GetPanY(); | |
354 | 2019 |
2020 switch (corner) | |
2021 { | |
407 | 2022 case RadiologyScene::Corner_TopLeft: |
2023 oppositeCorner_ = RadiologyScene::Corner_BottomRight; | |
354 | 2024 break; |
2025 | |
407 | 2026 case RadiologyScene::Corner_TopRight: |
2027 oppositeCorner_ = RadiologyScene::Corner_BottomLeft; | |
354 | 2028 break; |
2029 | |
407 | 2030 case RadiologyScene::Corner_BottomLeft: |
2031 oppositeCorner_ = RadiologyScene::Corner_TopRight; | |
354 | 2032 break; |
2033 | |
407 | 2034 case RadiologyScene::Corner_BottomRight: |
2035 oppositeCorner_ = RadiologyScene::Corner_TopLeft; | |
354 | 2036 break; |
2037 | |
2038 default: | |
2039 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
2040 } | |
2041 | |
407 | 2042 accessor_.GetLayer().GetCorner(oppositeX_, oppositeY_, oppositeCorner_); |
354 | 2043 |
2044 double d = ComputeDistance(x, y, oppositeX_, oppositeY_); | |
2045 if (d >= std::numeric_limits<float>::epsilon()) | |
2046 { | |
2047 baseScaling_ = 1.0 / d; | |
2048 } | |
2049 else | |
2050 { | |
2051 // Avoid division by zero in extreme cases | |
2052 accessor_.Invalidate(); | |
2053 } | |
2054 } | |
2055 } | |
2056 | |
2057 virtual bool HasRender() const | |
2058 { | |
2059 return false; | |
2060 } | |
2061 | |
2062 virtual void Render(CairoContext& context, | |
2063 double zoom) | |
2064 { | |
2065 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
2066 } | |
2067 | |
2068 virtual void MouseUp() | |
2069 { | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2070 if (accessor_.IsValid() && |
407 | 2071 accessor_.GetLayer().IsResizeable()) |
355
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
2072 { |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
2073 undoRedoStack_.Add(new UndoRedoCommand(*this)); |
d2468dd75b3f
undo redo for all tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
354
diff
changeset
|
2074 } |
354 | 2075 } |
2076 | |
2077 virtual void MouseMove(int displayX, | |
2078 int displayY, | |
2079 double sceneX, | |
2080 double sceneY) | |
2081 { | |
2082 static const double ROUND_SCALING = 0.1; | |
2083 | |
2084 if (accessor_.IsValid() && | |
407 | 2085 accessor_.GetLayer().IsResizeable()) |
354 | 2086 { |
2087 double scaling = ComputeDistance(oppositeX_, oppositeY_, sceneX, sceneY) * baseScaling_; | |
2088 | |
2089 if (roundScaling_) | |
2090 { | |
376
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
2091 scaling = boost::math::round<double>((scaling / ROUND_SCALING) * ROUND_SCALING); |
354 | 2092 } |
2093 | |
407 | 2094 RadiologyScene::Layer& layer = accessor_.GetLayer(); |
2095 layer.SetPixelSpacing(scaling * originalSpacingX_, | |
2096 scaling * originalSpacingY_); | |
354 | 2097 |
2098 // Keep the opposite corner at a fixed location | |
2099 double ox, oy; | |
407 | 2100 layer.GetCorner(ox, oy, oppositeCorner_); |
2101 layer.SetPan(layer.GetPanX() + oppositeX_ - ox, | |
2102 layer.GetPanY() + oppositeY_ - oy); | |
354 | 2103 } |
2104 } | |
2105 }; | |
2106 | |
2107 | |
407 | 2108 class RadiologyWindowingTracker : public IWorldSceneMouseTracker |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2109 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2110 public: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2111 enum Action |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2112 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2113 Action_IncreaseWidth, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2114 Action_DecreaseWidth, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2115 Action_IncreaseCenter, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2116 Action_DecreaseCenter |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2117 }; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2118 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2119 private: |
407 | 2120 UndoRedoStack& undoRedoStack_; |
2121 RadiologyScene& scene_; | |
2122 int clickX_; | |
2123 int clickY_; | |
2124 Action leftAction_; | |
2125 Action rightAction_; | |
2126 Action upAction_; | |
2127 Action downAction_; | |
2128 float strength_; | |
2129 float sourceCenter_; | |
2130 float sourceWidth_; | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2131 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2132 static void ComputeAxisEffect(int& deltaCenter, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2133 int& deltaWidth, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2134 int delta, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2135 Action actionNegative, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2136 Action actionPositive) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2137 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2138 if (delta < 0) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2139 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2140 switch (actionNegative) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2141 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2142 case Action_IncreaseWidth: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2143 deltaWidth = -delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2144 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2145 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2146 case Action_DecreaseWidth: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2147 deltaWidth = delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2148 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2149 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2150 case Action_IncreaseCenter: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2151 deltaCenter = -delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2152 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2153 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2154 case Action_DecreaseCenter: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2155 deltaCenter = delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2156 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2157 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2158 default: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2159 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2160 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2161 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2162 else if (delta > 0) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2163 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2164 switch (actionPositive) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2165 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2166 case Action_IncreaseWidth: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2167 deltaWidth = delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2168 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2169 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2170 case Action_DecreaseWidth: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2171 deltaWidth = -delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2172 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2173 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2174 case Action_IncreaseCenter: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2175 deltaCenter = delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2176 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2177 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2178 case Action_DecreaseCenter: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2179 deltaCenter = -delta; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2180 break; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2181 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2182 default: |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2183 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2184 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2185 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2186 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2187 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2188 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2189 class UndoRedoCommand : public UndoRedoStack::ICommand |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2190 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2191 private: |
407 | 2192 RadiologyScene& scene_; |
2193 float sourceCenter_; | |
2194 float sourceWidth_; | |
2195 float targetCenter_; | |
2196 float targetWidth_; | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2197 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2198 public: |
407 | 2199 UndoRedoCommand(const RadiologyWindowingTracker& tracker) : |
2200 scene_(tracker.scene_), | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2201 sourceCenter_(tracker.sourceCenter_), |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2202 sourceWidth_(tracker.sourceWidth_) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2203 { |
407 | 2204 scene_.GetWindowingWithDefault(targetCenter_, targetWidth_); |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2205 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2206 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2207 virtual void Undo() const |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2208 { |
407 | 2209 scene_.SetWindowing(sourceCenter_, sourceWidth_); |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2210 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2211 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2212 virtual void Redo() const |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2213 { |
407 | 2214 scene_.SetWindowing(targetCenter_, targetWidth_); |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2215 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2216 }; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2217 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2218 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2219 public: |
407 | 2220 RadiologyWindowingTracker(UndoRedoStack& undoRedoStack, |
2221 RadiologyScene& scene, | |
2222 int x, | |
2223 int y, | |
2224 Action leftAction, | |
2225 Action rightAction, | |
2226 Action upAction, | |
2227 Action downAction) : | |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2228 undoRedoStack_(undoRedoStack), |
407 | 2229 scene_(scene), |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2230 clickX_(x), |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2231 clickY_(y), |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2232 leftAction_(leftAction), |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2233 rightAction_(rightAction), |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2234 upAction_(upAction), |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2235 downAction_(downAction) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2236 { |
407 | 2237 scene_.GetWindowingWithDefault(sourceCenter_, sourceWidth_); |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2238 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2239 float minValue, maxValue; |
407 | 2240 scene.GetRange(minValue, maxValue); |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2241 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2242 assert(minValue <= maxValue); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2243 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2244 float tmp; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2245 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2246 float delta = (maxValue - minValue); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2247 if (delta <= 1) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2248 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2249 tmp = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2250 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2251 else |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2252 { |
376
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
2253 // NB: Visual Studio 2008 does not provide "log2f()", so we |
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
2254 // implement it by ourselves |
70256a53ff21
fix compatibility with Visual Studio 2008
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
369
diff
changeset
|
2255 tmp = logf(delta) / logf(2.0f); |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2256 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2257 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2258 strength_ = tmp - 7; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2259 if (strength_ < 1) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2260 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2261 strength_ = 1; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2262 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2263 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2264 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2265 virtual bool HasRender() const |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2266 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2267 return false; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2268 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2269 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2270 virtual void Render(CairoContext& context, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2271 double zoom) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2272 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2273 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2274 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2275 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2276 virtual void MouseUp() |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2277 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2278 undoRedoStack_.Add(new UndoRedoCommand(*this)); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2279 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2280 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2281 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2282 virtual void MouseMove(int displayX, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2283 int displayY, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2284 double sceneX, |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2285 double sceneY) |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2286 { |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2287 // https://bitbucket.org/osimis/osimis-webviewer-plugin/src/master/frontend/src/app/viewport/image-plugins/windowing-viewport-tool.class.js |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2288 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2289 static const float SCALE = 1.0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2290 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2291 int deltaCenter = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2292 int deltaWidth = 0; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2293 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2294 ComputeAxisEffect(deltaCenter, deltaWidth, displayX - clickX_, leftAction_, rightAction_); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2295 ComputeAxisEffect(deltaCenter, deltaWidth, displayY - clickY_, upAction_, downAction_); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2296 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2297 float newCenter = sourceCenter_ + (deltaCenter / SCALE * strength_); |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2298 float newWidth = sourceWidth_ + (deltaWidth / SCALE * strength_); |
407 | 2299 scene_.SetWindowing(newCenter, newWidth); |
356
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2300 } |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2301 }; |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2302 |
885f0a5eaa49
mouse tracker to set windowing
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
355
diff
changeset
|
2303 |
407 | 2304 class RadiologyWidget : |
338 | 2305 public WorldSceneWidget, |
2306 public IObserver | |
2307 { | |
2308 private: | |
407 | 2309 RadiologyScene& scene_; |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2310 std::auto_ptr<Orthanc::Image> floatBuffer_; |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2311 std::auto_ptr<CairoSurface> cairoBuffer_; |
358 | 2312 bool invert_; |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2313 ImageInterpolation interpolation_; |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2314 bool hasSelection_; |
407 | 2315 size_t selectedLayer_; |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2316 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2317 virtual bool RenderInternal(unsigned int width, |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2318 unsigned int height, |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2319 ImageInterpolation interpolation) |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2320 { |
339 | 2321 float windowCenter, windowWidth; |
407 | 2322 scene_.GetWindowingWithDefault(windowCenter, windowWidth); |
339 | 2323 |
2324 float x0 = windowCenter - windowWidth / 2.0f; | |
2325 float x1 = windowCenter + windowWidth / 2.0f; | |
2326 | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2327 if (windowWidth <= 0.001f) // Avoid division by zero at (*) |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2328 { |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2329 return false; |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2330 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2331 else |
339 | 2332 { |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2333 if (floatBuffer_.get() == NULL || |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2334 floatBuffer_->GetWidth() != width || |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2335 floatBuffer_->GetHeight() != height) |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2336 { |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2337 floatBuffer_.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, width, height, false)); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2338 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2339 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2340 if (cairoBuffer_.get() == NULL || |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2341 cairoBuffer_->GetWidth() != width || |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2342 cairoBuffer_->GetHeight() != height) |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2343 { |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2344 cairoBuffer_.reset(new CairoSurface(width, height)); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2345 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2346 |
407 | 2347 scene_.Render(*floatBuffer_, GetView().GetMatrix(), interpolation); |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2348 |
360 | 2349 // Conversion from Float32 to BGRA32 (cairo). Very similar to |
2350 // GrayscaleFrameRenderer => TODO MERGE? | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2351 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2352 Orthanc::ImageAccessor target; |
369
557c8ff1db5c
integration mainline->am-2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
365
diff
changeset
|
2353 cairoBuffer_->GetWriteableAccessor(target); |
360 | 2354 |
2355 float scaling = 255.0f / (x1 - x0); | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2356 |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2357 for (unsigned int y = 0; y < height; y++) |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2358 { |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2359 const float* p = reinterpret_cast<const float*>(floatBuffer_->GetConstRow(y)); |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2360 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
339 | 2361 |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2362 for (unsigned int x = 0; x < width; x++, p++, q += 4) |
339 | 2363 { |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2364 uint8_t v = 0; |
339 | 2365 if (*p >= x1) |
2366 { | |
2367 v = 255; | |
2368 } | |
2369 else if (*p <= x0) | |
2370 { | |
2371 v = 0; | |
2372 } | |
2373 else | |
2374 { | |
2375 // https://en.wikipedia.org/wiki/Linear_interpolation | |
360 | 2376 v = static_cast<uint8_t>(scaling * (*p - x0)); // (*) |
339 | 2377 } |
2378 | |
358 | 2379 if (invert_) |
2380 { | |
339 | 2381 v = 255 - v; |
358 | 2382 } |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2383 |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2384 q[0] = v; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2385 q[1] = v; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2386 q[2] = v; |
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2387 q[3] = 255; |
339 | 2388 } |
2389 } | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2390 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2391 return true; |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2392 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2393 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2394 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2395 protected: |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2396 virtual Extent2D GetSceneExtent() |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2397 { |
407 | 2398 return scene_.GetSceneExtent(); |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2399 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2400 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2401 virtual bool RenderScene(CairoContext& context, |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2402 const ViewportGeometry& view) |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2403 { |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2404 cairo_t* cr = context.GetObject(); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2405 |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2406 if (RenderInternal(context.GetWidth(), context.GetHeight(), interpolation_)) |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2407 { |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2408 // https://www.cairographics.org/FAQ/#paint_from_a_surface |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2409 cairo_save(cr); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2410 cairo_identity_matrix(cr); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2411 cairo_set_source_surface(cr, cairoBuffer_->GetObject(), 0, 0); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2412 cairo_paint(cr); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2413 cairo_restore(cr); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2414 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2415 else |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2416 { |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2417 // https://www.cairographics.org/FAQ/#clear_a_surface |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2418 context.SetSourceColor(0, 0, 0); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2419 cairo_paint(cr); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2420 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2421 |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2422 if (hasSelection_) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2423 { |
407 | 2424 scene_.DrawBorder(context, selectedLayer_, view.GetZoom()); |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2425 } |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2426 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2427 return true; |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2428 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2429 |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2430 public: |
407 | 2431 RadiologyWidget(MessageBroker& broker, |
2432 RadiologyScene& scene, | |
2433 const std::string& name) : | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2434 WorldSceneWidget(name), |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2435 IObserver(broker), |
407 | 2436 scene_(scene), |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2437 invert_(false), |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2438 interpolation_(ImageInterpolation_Nearest), |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2439 hasSelection_(false), |
407 | 2440 selectedLayer_(0) // Dummy initialization |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2441 { |
407 | 2442 scene.RegisterObserverCallback( |
2443 new Callable<RadiologyWidget, RadiologyScene::GeometryChangedMessage> | |
2444 (*this, &RadiologyWidget::OnGeometryChanged)); | |
2445 | |
2446 scene.RegisterObserverCallback( | |
2447 new Callable<RadiologyWidget, RadiologyScene::ContentChangedMessage> | |
2448 (*this, &RadiologyWidget::OnContentChanged)); | |
358 | 2449 } |
2450 | |
407 | 2451 RadiologyScene& GetScene() const |
358 | 2452 { |
407 | 2453 return scene_; |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2454 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2455 |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2456 void Unselect() |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2457 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2458 hasSelection_ = false; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2459 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2460 |
407 | 2461 void Select(size_t layer) |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2462 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2463 hasSelection_ = true; |
407 | 2464 selectedLayer_ = layer; |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2465 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2466 |
407 | 2467 bool LookupSelectedLayer(size_t& layer) |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2468 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2469 if (hasSelection_) |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2470 { |
407 | 2471 layer = selectedLayer_; |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2472 return true; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2473 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2474 else |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2475 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2476 return false; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2477 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2478 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2479 |
407 | 2480 void OnGeometryChanged(const RadiologyScene::GeometryChangedMessage& message) |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2481 { |
358 | 2482 LOG(INFO) << "Geometry has changed"; |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2483 FitContent(); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2484 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2485 |
407 | 2486 void OnContentChanged(const RadiologyScene::ContentChangedMessage& message) |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2487 { |
358 | 2488 LOG(INFO) << "Content has changed"; |
2489 NotifyContentChanged(); | |
2490 } | |
2491 | |
2492 void SetInvert(bool invert) | |
2493 { | |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2494 if (invert_ != invert) |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2495 { |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2496 invert_ = invert; |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2497 NotifyContentChanged(); |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2498 } |
358 | 2499 } |
2500 | |
2501 void SwitchInvert() | |
2502 { | |
2503 invert_ = !invert_; | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2504 NotifyContentChanged(); |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2505 } |
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2506 |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2507 bool IsInverted() const |
358 | 2508 { |
2509 return invert_; | |
2510 } | |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2511 |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2512 void SetInterpolation(ImageInterpolation interpolation) |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2513 { |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2514 if (interpolation_ != interpolation) |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2515 { |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2516 interpolation_ = interpolation; |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2517 NotifyContentChanged(); |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2518 } |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2519 } |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2520 |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2521 ImageInterpolation GetInterpolation() const |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2522 { |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2523 return interpolation_; |
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2524 } |
358 | 2525 }; |
2526 | |
2527 | |
407 | 2528 namespace Samples |
358 | 2529 { |
407 | 2530 class RadiologyEditorInteractor : |
2531 public IWorldSceneInteractor, | |
2532 public IObserver | |
358 | 2533 { |
407 | 2534 private: |
2535 enum Tool | |
2536 { | |
2537 Tool_Move, | |
2538 Tool_Rotate, | |
2539 Tool_Crop, | |
2540 Tool_Resize, | |
2541 Tool_Windowing | |
2542 }; | |
358 | 2543 |
2544 | |
407 | 2545 UndoRedoStack undoRedoStack_; |
2546 Tool tool_; | |
2547 | |
2548 | |
2549 static double GetHandleSize() | |
2550 { | |
2551 return 10.0; | |
2552 } | |
358 | 2553 |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2554 |
407 | 2555 public: |
2556 RadiologyEditorInteractor(MessageBroker& broker) : | |
2557 IObserver(broker), | |
2558 tool_(Tool_Move) | |
2559 { | |
2560 } | |
358 | 2561 |
407 | 2562 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& worldWidget, |
2563 const ViewportGeometry& view, | |
2564 MouseButton button, | |
2565 KeyboardModifiers modifiers, | |
2566 int viewportX, | |
2567 int viewportY, | |
2568 double x, | |
2569 double y, | |
2570 IStatusBar* statusBar) | |
357
ec4ad6c5eb99
avoid breaking class hierarchy
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
356
diff
changeset
|
2571 { |
407 | 2572 RadiologyWidget& widget = dynamic_cast<RadiologyWidget&>(worldWidget); |
2573 | |
2574 if (button == MouseButton_Left) | |
358 | 2575 { |
407 | 2576 size_t selected; |
2577 | |
2578 if (tool_ == Tool_Windowing) | |
358 | 2579 { |
407 | 2580 return new RadiologyWindowingTracker(undoRedoStack_, widget.GetScene(), |
2581 viewportX, viewportY, | |
2582 RadiologyWindowingTracker::Action_DecreaseWidth, | |
2583 RadiologyWindowingTracker::Action_IncreaseWidth, | |
2584 RadiologyWindowingTracker::Action_DecreaseCenter, | |
2585 RadiologyWindowingTracker::Action_IncreaseCenter); | |
358 | 2586 } |
407 | 2587 else if (!widget.LookupSelectedLayer(selected)) |
358 | 2588 { |
407 | 2589 // No layer is currently selected |
2590 size_t layer; | |
2591 if (widget.GetScene().LookupLayer(layer, x, y)) | |
358 | 2592 { |
407 | 2593 widget.Select(layer); |
358 | 2594 } |
407 | 2595 |
2596 return NULL; | |
358 | 2597 } |
407 | 2598 else if (tool_ == Tool_Crop || |
2599 tool_ == Tool_Resize) | |
358 | 2600 { |
407 | 2601 RadiologyScene::LayerAccessor accessor(widget.GetScene(), selected); |
2602 RadiologyScene::Corner corner; | |
2603 if (accessor.GetLayer().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize())) | |
358 | 2604 { |
407 | 2605 switch (tool_) |
2606 { | |
2607 case Tool_Crop: | |
2608 return new RadiologyLayerCropTracker(undoRedoStack_, widget.GetScene(), view, selected, x, y, corner); | |
2609 | |
2610 case Tool_Resize: | |
2611 return new RadiologyLayerResizeTracker(undoRedoStack_, widget.GetScene(), selected, x, y, corner, | |
2612 (modifiers & KeyboardModifiers_Shift)); | |
2613 | |
2614 default: | |
2615 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
2616 } | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2617 } |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2618 else |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2619 { |
407 | 2620 size_t layer; |
358 | 2621 |
407 | 2622 if (widget.GetScene().LookupLayer(layer, x, y)) |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2623 { |
407 | 2624 widget.Select(layer); |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2625 } |
407 | 2626 else |
2627 { | |
2628 widget.Unselect(); | |
2629 } | |
2630 | |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2631 return NULL; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2632 } |
358 | 2633 } |
2634 else | |
2635 { | |
407 | 2636 size_t layer; |
2637 | |
2638 if (widget.GetScene().LookupLayer(layer, x, y)) | |
2639 { | |
2640 if (layer == selected) | |
2641 { | |
2642 switch (tool_) | |
2643 { | |
2644 case Tool_Move: | |
2645 return new RadiologyLayerMoveTracker(undoRedoStack_, widget.GetScene(), layer, x, y, | |
2646 (modifiers & KeyboardModifiers_Shift)); | |
2647 | |
2648 case Tool_Rotate: | |
2649 return new RadiologyLayerRotateTracker(undoRedoStack_, widget.GetScene(), view, layer, x, y, | |
2650 (modifiers & KeyboardModifiers_Shift)); | |
2651 | |
2652 default: | |
2653 break; | |
2654 } | |
2655 | |
2656 return NULL; | |
2657 } | |
2658 else | |
2659 { | |
2660 widget.Select(layer); | |
2661 return NULL; | |
2662 } | |
2663 } | |
2664 else | |
2665 { | |
2666 widget.Unselect(); | |
2667 return NULL; | |
2668 } | |
2669 } | |
2670 } | |
2671 else | |
2672 { | |
2673 return NULL; | |
2674 } | |
2675 } | |
2676 | |
2677 virtual void MouseOver(CairoContext& context, | |
2678 WorldSceneWidget& worldWidget, | |
2679 const ViewportGeometry& view, | |
2680 double x, | |
2681 double y, | |
2682 IStatusBar* statusBar) | |
2683 { | |
2684 RadiologyWidget& widget = dynamic_cast<RadiologyWidget&>(worldWidget); | |
2685 | |
2686 #if 0 | |
2687 if (statusBar != NULL) | |
2688 { | |
2689 char buf[64]; | |
2690 sprintf(buf, "X = %.02f Y = %.02f (in cm)", x / 10.0, y / 10.0); | |
2691 statusBar->SetMessage(buf); | |
2692 } | |
2693 #endif | |
2694 | |
2695 size_t selected; | |
2696 | |
2697 if (widget.LookupSelectedLayer(selected) && | |
2698 (tool_ == Tool_Crop || | |
2699 tool_ == Tool_Resize)) | |
2700 { | |
2701 RadiologyScene::LayerAccessor accessor(widget.GetScene(), selected); | |
2702 | |
2703 RadiologyScene::Corner corner; | |
2704 if (accessor.GetLayer().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize())) | |
2705 { | |
2706 accessor.GetLayer().GetCorner(x, y, corner); | |
2707 | |
2708 double z = 1.0 / view.GetZoom(); | |
2709 | |
2710 context.SetSourceColor(255, 0, 0); | |
2711 cairo_t* cr = context.GetObject(); | |
2712 cairo_set_line_width(cr, 2.0 * z); | |
2713 cairo_move_to(cr, x - GetHandleSize() * z, y - GetHandleSize() * z); | |
2714 cairo_line_to(cr, x + GetHandleSize() * z, y - GetHandleSize() * z); | |
2715 cairo_line_to(cr, x + GetHandleSize() * z, y + GetHandleSize() * z); | |
2716 cairo_line_to(cr, x - GetHandleSize() * z, y + GetHandleSize() * z); | |
2717 cairo_line_to(cr, x - GetHandleSize() * z, y - GetHandleSize() * z); | |
2718 cairo_stroke(cr); | |
358 | 2719 } |
2720 } | |
339 | 2721 } |
407 | 2722 |
2723 virtual void MouseWheel(WorldSceneWidget& widget, | |
2724 MouseWheelDirection direction, | |
2725 KeyboardModifiers modifiers, | |
2726 IStatusBar* statusBar) | |
344
fdec8e6893cb
ordering of bitmap layers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
343
diff
changeset
|
2727 { |
358 | 2728 } |
407 | 2729 |
2730 virtual void KeyPressed(WorldSceneWidget& worldWidget, | |
2731 KeyboardKeys key, | |
2732 char keyChar, | |
2733 KeyboardModifiers modifiers, | |
2734 IStatusBar* statusBar) | |
345 | 2735 { |
407 | 2736 RadiologyWidget& widget = dynamic_cast<RadiologyWidget&>(worldWidget); |
2737 | |
2738 switch (keyChar) | |
358 | 2739 { |
407 | 2740 case 'a': |
2741 widget.FitContent(); | |
2742 break; | |
2743 | |
2744 case 'c': | |
2745 tool_ = Tool_Crop; | |
2746 break; | |
2747 | |
2748 case 'e': | |
2749 { | |
2750 Orthanc::DicomMap tags; | |
2751 | |
2752 // Minimal set of tags to generate a valid CR image | |
2753 tags.SetValue(Orthanc::DICOM_TAG_ACCESSION_NUMBER, "NOPE", false); | |
2754 tags.SetValue(Orthanc::DICOM_TAG_BODY_PART_EXAMINED, "PELVIS", false); | |
2755 tags.SetValue(Orthanc::DICOM_TAG_INSTANCE_NUMBER, "1", false); | |
2756 //tags.SetValue(Orthanc::DICOM_TAG_LATERALITY, "", false); | |
2757 tags.SetValue(Orthanc::DICOM_TAG_MANUFACTURER, "OSIMIS", false); | |
2758 tags.SetValue(Orthanc::DICOM_TAG_MODALITY, "CR", false); | |
2759 tags.SetValue(Orthanc::DICOM_TAG_PATIENT_BIRTH_DATE, "20000101", false); | |
2760 tags.SetValue(Orthanc::DICOM_TAG_PATIENT_ID, "hello", false); | |
2761 tags.SetValue(Orthanc::DICOM_TAG_PATIENT_NAME, "HELLO^WORLD", false); | |
2762 tags.SetValue(Orthanc::DICOM_TAG_PATIENT_ORIENTATION, "", false); | |
2763 tags.SetValue(Orthanc::DICOM_TAG_PATIENT_SEX, "M", false); | |
2764 tags.SetValue(Orthanc::DICOM_TAG_REFERRING_PHYSICIAN_NAME, "HOUSE^MD", false); | |
2765 tags.SetValue(Orthanc::DICOM_TAG_SERIES_NUMBER, "1", false); | |
2766 tags.SetValue(Orthanc::DICOM_TAG_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.1", false); | |
2767 tags.SetValue(Orthanc::DICOM_TAG_STUDY_ID, "STUDY", false); | |
2768 tags.SetValue(Orthanc::DICOM_TAG_VIEW_POSITION, "", false); | |
2769 | |
2770 widget.GetScene().Export(tags, 0.1, 0.1, widget.IsInverted(), | |
2771 widget.GetInterpolation(), EXPORT_USING_PAM); | |
2772 break; | |
2773 } | |
2774 | |
2775 case 'i': | |
2776 widget.SwitchInvert(); | |
2777 break; | |
2778 | |
2779 case 'm': | |
2780 tool_ = Tool_Move; | |
2781 break; | |
2782 | |
2783 case 'n': | |
2784 { | |
2785 switch (widget.GetInterpolation()) | |
2786 { | |
2787 case ImageInterpolation_Nearest: | |
2788 LOG(INFO) << "Switching to bilinear interpolation"; | |
2789 widget.SetInterpolation(ImageInterpolation_Bilinear); | |
2790 break; | |
2791 | |
2792 case ImageInterpolation_Bilinear: | |
2793 LOG(INFO) << "Switching to nearest neighbor interpolation"; | |
2794 widget.SetInterpolation(ImageInterpolation_Nearest); | |
2795 break; | |
2796 | |
2797 default: | |
2798 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
2799 } | |
358 | 2800 |
407 | 2801 break; |
2802 } | |
2803 | |
2804 case 'r': | |
2805 tool_ = Tool_Rotate; | |
2806 break; | |
2807 | |
2808 case 's': | |
2809 tool_ = Tool_Resize; | |
2810 break; | |
2811 | |
2812 case 'w': | |
2813 tool_ = Tool_Windowing; | |
2814 break; | |
2815 | |
2816 case 'y': | |
2817 if (modifiers & KeyboardModifiers_Control) | |
2818 { | |
2819 undoRedoStack_.Redo(); | |
2820 widget.NotifyContentChanged(); | |
2821 } | |
2822 break; | |
2823 | |
2824 case 'z': | |
2825 if (modifiers & KeyboardModifiers_Control) | |
2826 { | |
2827 undoRedoStack_.Undo(); | |
2828 widget.NotifyContentChanged(); | |
2829 } | |
2830 break; | |
2831 | |
2832 default: | |
2833 break; | |
358 | 2834 } |
345 | 2835 } |
407 | 2836 }; |
336
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
2837 |
c7fdc8bac581
creating GrayscaleBitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
334
diff
changeset
|
2838 |
358 | 2839 |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2840 class SingleFrameEditorApplication : |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2841 public SampleSingleCanvasApplicationBase, |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2842 public IObserver |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2843 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2844 private: |
334
c34784e5f299
compatibility fixes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
330
diff
changeset
|
2845 std::auto_ptr<OrthancApiClient> orthancApiClient_; |
407 | 2846 std::auto_ptr<RadiologyScene> scene_; |
2847 RadiologyEditorInteractor interactor_; | |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2848 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2849 public: |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2850 SingleFrameEditorApplication(MessageBroker& broker) : |
362
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
2851 IObserver(broker), |
12cec26d08ce
export of a valid DICOM CR
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
361
diff
changeset
|
2852 interactor_(broker) |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2853 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2854 } |
384
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2855 |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2856 virtual ~SingleFrameEditorApplication() |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2857 { |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2858 LOG(WARNING) << "Destroying the application"; |
d20d75f20c5d
better following of the MVC design pattern
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
377
diff
changeset
|
2859 } |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2860 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2861 virtual void DeclareStartupOptions(boost::program_options::options_description& options) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2862 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2863 boost::program_options::options_description generic("Sample options"); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2864 generic.add_options() |
340
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2865 ("instance", boost::program_options::value<std::string>(), |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2866 "Orthanc ID of the instance") |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2867 ("frame", boost::program_options::value<unsigned int>()->default_value(0), |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2868 "Number of the frame, for multi-frame DICOM instances") |
f5d5814a41a0
rendering BitmapStack
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
339
diff
changeset
|
2869 ; |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2870 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2871 options.add(generic); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2872 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2873 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2874 virtual void Initialize(StoneApplicationContext* context, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2875 IStatusBar& statusBar, |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2876 const boost::program_options::variables_map& parameters) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2877 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2878 using namespace OrthancStone; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2879 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2880 context_ = context; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2881 |
358 | 2882 statusBar.SetMessage("Use the key \"a\" to reinitialize the layout"); |
2883 statusBar.SetMessage("Use the key \"c\" to crop"); | |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2884 statusBar.SetMessage("Use the key \"e\" to export DICOM to the Orthanc server"); |
358 | 2885 statusBar.SetMessage("Use the key \"f\" to switch full screen"); |
2886 statusBar.SetMessage("Use the key \"i\" to invert contrast"); | |
2887 statusBar.SetMessage("Use the key \"m\" to move objects"); | |
359
100df90bf0ea
preparing to implement Export
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
358
diff
changeset
|
2888 statusBar.SetMessage("Use the key \"n\" to switch between nearest neighbor and bilinear interpolation"); |
358 | 2889 statusBar.SetMessage("Use the key \"r\" to rotate objects"); |
407 | 2890 statusBar.SetMessage("Use the key \"s\" to resize objects (not applicable to DICOM layers)"); |
358 | 2891 statusBar.SetMessage("Use the key \"w\" to change windowing"); |
2892 | |
2893 statusBar.SetMessage("Use the key \"ctrl-z\" to undo action"); | |
2894 statusBar.SetMessage("Use the key \"ctrl-y\" to redo action"); | |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2895 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2896 if (parameters.count("instance") != 1) |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2897 { |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2898 LOG(ERROR) << "The instance ID is missing"; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2899 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2900 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2901 |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2902 std::string instance = parameters["instance"].as<std::string>(); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2903 int frame = parameters["frame"].as<unsigned int>(); |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2904 |
393
e7a494bdd956
removed Messages/MessageType.h
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
392
diff
changeset
|
2905 orthancApiClient_.reset(new OrthancApiClient(GetBroker(), context_->GetWebService())); |
337 | 2906 |
343 | 2907 Orthanc::FontRegistry fonts; |
2908 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); | |
2909 | |
407 | 2910 scene_.reset(new RadiologyScene(GetBroker(), *orthancApiClient_)); |
2911 scene_->LoadDicomFrame(instance, frame, false); //.SetPan(200, 0); | |
2912 //scene_->LoadDicomFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false); | |
354 | 2913 |
2914 { | |
407 | 2915 RadiologyScene::Layer& layer = scene_->LoadText(fonts.GetFont(0), "Hello\nworld"); |
2916 //dynamic_cast<RadiologyScene::Layer&>(layer).SetForegroundValue(256); | |
2917 dynamic_cast<RadiologyScene::Layer&>(layer).SetResizeable(true); | |
354 | 2918 } |
2919 | |
2920 { | |
407 | 2921 RadiologyScene::Layer& layer = scene_->LoadTestBlock(100, 50); |
2922 //dynamic_cast<RadiologyScene::Layer&>(layer).SetForegroundValue(256); | |
2923 dynamic_cast<RadiologyScene::Layer&>(layer).SetResizeable(true); | |
2924 dynamic_cast<RadiologyScene::Layer&>(layer).SetPan(0, 200); | |
354 | 2925 } |
2926 | |
337 | 2927 |
407 | 2928 mainWidget_ = new RadiologyWidget(GetBroker(), *scene_, "main-widget"); |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2929 mainWidget_->SetTransmitMouseOver(true); |
358 | 2930 mainWidget_->SetInteractor(interactor_); |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2931 |
407 | 2932 //scene_->SetWindowing(128, 256); |
325
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2933 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2934 }; |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2935 } |
37ab9d83dc9b
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
am@osimis.io
parents:
diff
changeset
|
2936 } |