Mercurial > hg > orthanc-stone
comparison Framework/Layers/FrameRenderer.cpp @ 97:d18dcc963930 wasm
separation of the renderers vs. viewport slice
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 30 May 2017 14:09:11 +0200 |
parents | 7b14c12a3be5 |
children | 53025eecbc95 |
comparison
equal
deleted
inserted
replaced
96:f8bce1bebe01 | 97:d18dcc963930 |
---|---|
26 | 26 |
27 #include "../../Resources/Orthanc/Core/OrthancException.h" | 27 #include "../../Resources/Orthanc/Core/OrthancException.h" |
28 | 28 |
29 namespace OrthancStone | 29 namespace OrthancStone |
30 { | 30 { |
31 static bool ComputePixelTransform(cairo_matrix_t& target, | |
32 const SliceGeometry& viewportSlice, | |
33 const SliceGeometry& frameSlice, | |
34 double pixelSpacingX, | |
35 double pixelSpacingY) | |
36 { | |
37 bool isOpposite; | |
38 if (!GeometryToolbox::IsParallelOrOpposite(isOpposite, | |
39 viewportSlice.GetNormal(), | |
40 frameSlice.GetNormal())) | |
41 { | |
42 return false; | |
43 } | |
44 else | |
45 { | |
46 double x0, y0, x1, y1, x2, y2; | |
47 viewportSlice.ProjectPoint(x0, y0, frameSlice.GetOrigin() | |
48 - 0.5 * pixelSpacingX * frameSlice.GetAxisX() | |
49 - 0.5 * pixelSpacingY * frameSlice.GetAxisY()); | |
50 viewportSlice.ProjectPoint(x1, y1, frameSlice.GetOrigin() | |
51 + 0.5 * pixelSpacingX * frameSlice.GetAxisX() | |
52 - 0.5 * pixelSpacingY * frameSlice.GetAxisY()); | |
53 viewportSlice.ProjectPoint(x2, y2, frameSlice.GetOrigin() | |
54 - 0.5 * pixelSpacingX * frameSlice.GetAxisX() | |
55 + 0.5 * pixelSpacingY * frameSlice.GetAxisY()); | |
56 | |
57 /** | |
58 * Now we solve the system of linear equations Ax + b = x', given: | |
59 * A [0 ; 0] + b = [x0 ; y0] | |
60 * A [1 ; 0] + b = [x1 ; y1] | |
61 * A [0 ; 1] + b = [x2 ; y2] | |
62 * <=> | |
63 * b = [x0 ; y0] | |
64 * A [1 ; 0] = [x1 ; y1] - b = [x1 - x0 ; y1 - y0] | |
65 * A [0 ; 1] = [x2 ; y2] - b = [x2 - x0 ; y2 - y0] | |
66 * <=> | |
67 * b = [x0 ; y0] | |
68 * [a11 ; a21] = [x1 - x0 ; y1 - y0] | |
69 * [a12 ; a22] = [x2 - x0 ; y2 - y0] | |
70 **/ | |
71 | |
72 cairo_matrix_init(&target, x1 - x0, y1 - y0, x2 - x0, y2 - y0, x0, y0); | |
73 | |
74 return true; | |
75 } | |
76 } | |
77 | |
78 | |
79 FrameRenderer::FrameRenderer(const SliceGeometry& frameSlice, | 31 FrameRenderer::FrameRenderer(const SliceGeometry& frameSlice, |
80 double pixelSpacingX, | 32 double pixelSpacingX, |
81 double pixelSpacingY, | 33 double pixelSpacingY, |
82 bool isFullQuality) : | 34 bool isFullQuality) : |
83 frameSlice_(frameSlice), | 35 frameSlice_(frameSlice), |
86 isFullQuality_(isFullQuality) | 38 isFullQuality_(isFullQuality) |
87 { | 39 { |
88 } | 40 } |
89 | 41 |
90 | 42 |
91 bool FrameRenderer::ComputeFrameExtent(double& x1, | |
92 double& y1, | |
93 double& x2, | |
94 double& y2, | |
95 const SliceGeometry& viewportSlice, | |
96 const SliceGeometry& frameSlice, | |
97 unsigned int frameWidth, | |
98 unsigned int frameHeight, | |
99 double pixelSpacingX, | |
100 double pixelSpacingY) | |
101 { | |
102 bool isOpposite; | |
103 if (!GeometryToolbox::IsParallelOrOpposite(isOpposite, viewportSlice.GetNormal(), frameSlice.GetNormal())) | |
104 { | |
105 return false; | |
106 } | |
107 else | |
108 { | |
109 cairo_matrix_t transform; | |
110 if (!ComputePixelTransform(transform, viewportSlice, frameSlice, pixelSpacingX, pixelSpacingY)) | |
111 { | |
112 return true; | |
113 } | |
114 | |
115 x1 = 0; | |
116 y1 = 0; | |
117 cairo_matrix_transform_point(&transform, &x1, &y1); | |
118 | |
119 x2 = frameWidth; | |
120 y2 = frameHeight; | |
121 cairo_matrix_transform_point(&transform, &x2, &y2); | |
122 | |
123 if (x1 > x2) | |
124 { | |
125 std::swap(x1, x2); | |
126 } | |
127 | |
128 if (y1 > y2) | |
129 { | |
130 std::swap(y1, y2); | |
131 } | |
132 | |
133 return true; | |
134 } | |
135 } | |
136 | |
137 | |
138 bool FrameRenderer::RenderLayer(CairoContext& context, | 43 bool FrameRenderer::RenderLayer(CairoContext& context, |
139 const ViewportGeometry& view, | 44 const ViewportGeometry& view) |
140 const SliceGeometry& viewportSlice) | |
141 { | 45 { |
142 if (!style_.visible_) | 46 if (!style_.visible_) |
143 { | 47 { |
144 return true; | 48 return true; |
145 } | 49 } |
146 | 50 |
147 if (display_.get() == NULL) | 51 if (display_.get() == NULL) |
148 { | 52 { |
149 if (!ComputePixelTransform(transform_, viewportSlice, frameSlice_, | |
150 pixelSpacingX_, pixelSpacingY_)) | |
151 { | |
152 return true; | |
153 } | |
154 | |
155 display_.reset(GenerateDisplay(style_)); | 53 display_.reset(GenerateDisplay(style_)); |
156 } | 54 } |
157 | 55 |
158 assert(display_.get() != NULL); | 56 assert(display_.get() != NULL); |
159 | 57 |
160 cairo_t *cr = context.GetObject(); | 58 cairo_t *cr = context.GetObject(); |
161 | 59 |
162 cairo_save(cr); | 60 cairo_save(cr); |
163 | 61 |
164 cairo_transform(cr, &transform_); | 62 cairo_matrix_t transform; |
63 cairo_matrix_init_identity(&transform); | |
64 cairo_matrix_scale(&transform, pixelSpacingX_, pixelSpacingY_); | |
65 cairo_matrix_translate(&transform, -0.5, -0.5); | |
66 cairo_transform(cr, &transform); | |
67 | |
165 //cairo_set_operator(cr, CAIRO_OPERATOR_OVER); | 68 //cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
166 cairo_set_source_surface(cr, display_->GetObject(), 0, 0); | 69 cairo_set_source_surface(cr, display_->GetObject(), 0, 0); |
167 | 70 |
168 switch (style_.interpolation_) | 71 switch (style_.interpolation_) |
169 { | 72 { |
213 display_.reset(NULL); | 116 display_.reset(NULL); |
214 } | 117 } |
215 | 118 |
216 | 119 |
217 ILayerRenderer* FrameRenderer::CreateRenderer(Orthanc::ImageAccessor* frame, | 120 ILayerRenderer* FrameRenderer::CreateRenderer(Orthanc::ImageAccessor* frame, |
218 const SliceGeometry& frameSlice, | |
219 const OrthancPlugins::IDicomDataset& dicom, | |
220 double pixelSpacingX, | |
221 double pixelSpacingY, | |
222 bool isFullQuality) | |
223 { | |
224 std::auto_ptr<Orthanc::ImageAccessor> protect(frame); | |
225 | |
226 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) | |
227 { | |
228 return new ColorFrameRenderer(protect.release(), frameSlice, | |
229 pixelSpacingX, pixelSpacingY, isFullQuality); | |
230 } | |
231 else | |
232 { | |
233 DicomFrameConverter converter; | |
234 converter.ReadParameters(dicom); | |
235 return new GrayscaleFrameRenderer(protect.release(), converter, frameSlice, | |
236 pixelSpacingX, pixelSpacingY, isFullQuality); | |
237 } | |
238 } | |
239 | |
240 | |
241 ILayerRenderer* FrameRenderer::CreateRenderer(Orthanc::ImageAccessor* frame, | |
242 const Slice& frameSlice, | 121 const Slice& frameSlice, |
243 bool isFullQuality) | 122 bool isFullQuality) |
244 { | 123 { |
245 std::auto_ptr<Orthanc::ImageAccessor> protect(frame); | 124 std::auto_ptr<Orthanc::ImageAccessor> protect(frame); |
246 | 125 |
247 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) | 126 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) |
248 { | 127 { |
249 return new ColorFrameRenderer(protect.release(), frameSlice.GetGeometry(), | 128 return new ColorFrameRenderer(protect.release(), |
250 frameSlice.GetPixelSpacingX(), frameSlice.GetPixelSpacingY(), isFullQuality); | 129 frameSlice.GetGeometry(), |
130 frameSlice.GetPixelSpacingX(), | |
131 frameSlice.GetPixelSpacingY(), isFullQuality); | |
251 } | 132 } |
252 else | 133 else |
253 { | 134 { |
254 return new GrayscaleFrameRenderer(protect.release(), frameSlice.GetConverter(), frameSlice.GetGeometry(), | 135 return new GrayscaleFrameRenderer(protect.release(), |
255 frameSlice.GetPixelSpacingX(), frameSlice.GetPixelSpacingY(), isFullQuality); | 136 frameSlice.GetConverter(), |
137 frameSlice.GetGeometry(), | |
138 frameSlice.GetPixelSpacingX(), | |
139 frameSlice.GetPixelSpacingY(), isFullQuality); | |
256 } | 140 } |
257 } | 141 } |
258 } | 142 } |