comparison Framework/Radiography/RadiographyMaskLayer.cpp @ 476:a95090305dd4 am-touch-events

Introduced ControlPoint instead of Corner in the trackers and layers + drawing mask from the ControlPoints
author am@osimis.io
date Wed, 13 Feb 2019 12:04:02 +0100
parents 3c28542229a3
children baf8c8d68bbc
comparison
equal deleted inserted replaced
475:3c28542229a3 476:a95090305dd4
27 #include "Core/Images/ImageProcessing.h" 27 #include "Core/Images/ImageProcessing.h"
28 #include <Core/OrthancException.h> 28 #include <Core/OrthancException.h>
29 29
30 namespace OrthancStone 30 namespace OrthancStone
31 { 31 {
32 const unsigned char IN_MASK_VALUE = 0x00;
33 const unsigned char OUT_MASK_VALUE = 0xFF;
34
35 const AffineTransform2D& RadiographyMaskLayer::GetTransform() const
36 {
37 return dicomLayer_.GetTransform();
38 }
39
40 const AffineTransform2D& RadiographyMaskLayer::GetTransformInverse() const
41 {
42 return dicomLayer_.GetTransformInverse();
43 }
32 44
33 void ComputeMaskExtent(unsigned int& left, unsigned int& right, unsigned int& top, unsigned int& bottom, const std::vector<MaskPoint>& corners) 45 void ComputeMaskExtent(unsigned int& left, unsigned int& right, unsigned int& top, unsigned int& bottom, const std::vector<MaskPoint>& corners)
34 { 46 {
35 left = std::numeric_limits<unsigned int>::max(); 47 left = std::numeric_limits<unsigned int>::max();
36 right = std::numeric_limits<unsigned int>::min(); 48 right = std::numeric_limits<unsigned int>::min();
64 { 76 {
65 mask_.reset(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, dicomLayer_.GetWidth(), dicomLayer_.GetHeight(), false)); 77 mask_.reset(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, dicomLayer_.GetWidth(), dicomLayer_.GetHeight(), false));
66 78
67 DrawMask(); 79 DrawMask();
68 80
69 // for (unsigned int i = 0; i < 100; i++)
70 // {
71 // for (unsigned int j = 0; j < 50; j++)
72 // {
73 // if ((i + j) % 2 == 1)
74 // {
75 // Orthanc::ImageAccessor region;
76 // mask_->GetRegion(region, i* 20, j * 20, 20, 20);
77 // Orthanc::ImageProcessing::Set(region, 255);
78 // }
79 // }
80 // }
81 invalidated_ = false; 81 invalidated_ = false;
82 } 82 }
83 83
84 {// rendering 84 {// rendering
85 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32) 85 if (buffer.GetFormat() != Orthanc::PixelFormat_Float32)
110 float *q = reinterpret_cast<float*>(buffer.GetRow(y)); 110 float *q = reinterpret_cast<float*>(buffer.GetRow(y));
111 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)); 111 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y));
112 112
113 for (unsigned int x = 0; x < width; x++, p++, q++) 113 for (unsigned int x = 0; x < width; x++, p++, q++)
114 { 114 {
115 if (*p == 0) 115 if (*p == OUT_MASK_VALUE)
116 *q = foreground_; 116 *q = foreground_;
117 // else keep the underlying pixel value 117 // else keep the underlying pixel value
118 } 118 }
119 } 119 }
120 120
212 212
213 // Return true if count is odd, false otherwise 213 // Return true if count is odd, false otherwise
214 return count&1; // Same as (count%2 == 1) 214 return count&1; // Same as (count%2 == 1)
215 } 215 }
216 216
217 void RadiographyMaskLayer::DrawLine(const MaskPoint& start, const MaskPoint& end) const
218 {
219 int dx = (int)(end.x) - (int)(start.x);
220 int dy = (int)(end.y) - (int)(start.y);
221
222 if (std::abs(dx) > std::abs(dy))
223 { // the line is closer to horizontal
224
225 int incx = dx / std::abs(dx);
226 double incy = (double)(dy)/(double)(dx);
227 double y = (double)(start.y);
228 for (int x = (int)(start.x); x != (int)(end.x); x += incx, y += incy)
229 {
230 unsigned char* p = reinterpret_cast<unsigned char*>(mask_->GetRow((int)(y + 0.5))) + x;
231 *p = IN_MASK_VALUE;
232 }
233 }
234 else
235 { // the line is closer to vertical
236 int incy = dy / std::abs(dy);
237 double incx = (double)(dx)/(double)(dy);
238 double x = (double)(start.x);
239 for (int y = (int)(start.y); y != (int)(end.y); y += incy, x += incx)
240 {
241 unsigned char* p = reinterpret_cast<unsigned char*>(mask_->GetRow(y)) + (int)(x + 0.5);
242 *p = IN_MASK_VALUE;
243 }
244 }
245 }
246
217 247
218 void RadiographyMaskLayer::DrawMask() const 248 void RadiographyMaskLayer::DrawMask() const
219 { 249 {
220 unsigned int left; 250 unsigned int left;
221 unsigned int right; 251 unsigned int right;
222 unsigned int top; 252 unsigned int top;
223 unsigned int bottom; 253 unsigned int bottom;
224 254
225 ComputeMaskExtent(left, right, top, bottom, corners_); 255 // ComputeMaskExtent(left, right, top, bottom, corners_);
226 256
227 Orthanc::ImageProcessing::Set(*mask_, 0); 257 left = 0;
228 258 right = 2500;
229 MaskPoint p(left, top); 259 top = 0;
230 for (p.y = top; p.y <= bottom; p.y++) 260 bottom = 2500;
261 // first fill the complete image
262 Orthanc::ImageProcessing::Set(*mask_, OUT_MASK_VALUE);
263
264
231 { 265 {
232 unsigned char* q = reinterpret_cast<unsigned char*>(mask_->GetRow(p.y)); 266 // from http://alienryderflex.com/polygon_fill/
233 for (p.x = left; p.x <= right; p.x++, q++) 267 std::auto_ptr<int> raiiNodeX(new int(corners_.size()));
234 { 268
235 if (isInside(corners_, p)) 269 std::vector<int> nodeX;
270 nodeX.resize(corners_.size());
271 int nodes, pixelX, pixelY, i, j, swap ;
272
273 // Loop through the rows of the image.
274 for (pixelY = (int)top; pixelY < (int)bottom; pixelY++)
275 {
276 // Build a list of nodes.
277 nodes = 0;
278 j = (int)corners_.size() - 1;
279
280 for (i = 0; i < (int)corners_.size(); i++)
236 { 281 {
237 *q = 255; 282 if ((int)corners_[i].y < pixelY && (int)corners_[j].y >= pixelY
283 || (int)corners_[j].y < pixelY && (int)corners_[i].y >= pixelY)
284 {
285 nodeX[nodes++]= (int)((double)corners_[i].x + ((double)pixelY - (double)corners_[i].y)/((double)corners_[j].y - (double)corners_[i].y) *((double)corners_[j].x - (double)corners_[i].x));
286 }
287 j=i;
238 } 288 }
239 } 289
240 } 290 // Sort the nodes, via a simple “Bubble” sort.
241 291 i=0;
242 // Orthanc::ImageAccessor region; 292 while (i<nodes-1)
243 // mask_->GetRegion(region, 100, 100, 1000, 1000); 293 {
244 // Orthanc::ImageProcessing::Set(region, 255); 294 if (nodeX[i]>nodeX[i+1])
295 {
296 swap=nodeX[i]; nodeX[i]=nodeX[i+1]; nodeX[i+1]=swap; if (i) i--;
297 }
298 else
299 {
300 i++;
301 }
302 }
303
304 unsigned char* row = reinterpret_cast<unsigned char*>(mask_->GetRow(pixelY));
305 // Fill the pixels between node pairs.
306 for (i=0; i<nodes; i+=2)
307 {
308 if (nodeX[i ]>=(int)right)
309 break;
310 if (nodeX[i+1]> (int)left)
311 {
312 if (nodeX[i ]< (int)left )
313 nodeX[i ]=(int)left ;
314 if (nodeX[i+1]> (int)right)
315 nodeX[i+1]=(int)right;
316 for (pixelX=nodeX[i]; pixelX<nodeX[i+1]; pixelX++)
317 {
318 *(row + pixelX) = IN_MASK_VALUE;
319 }
320 }
321 }
322 }
323 }
324
325 // // draw lines
326 // for (size_t i = 1; i < corners_.size(); i++)
327 // {
328 // DrawLine(corners_[i-1], corners_[i]);
329 // }
330 // DrawLine(corners_[corners_.size()-1], corners_[0]);
331
332 // // fill between lines
333 // MaskPoint p(left, top);
334 // for (p.y = top; p.y <= bottom; p.y++)
335 // {
336 // unsigned char* q = reinterpret_cast<unsigned char*>(mask_->GetRow(p.y)) + left;
337 // unsigned char previousPixelValue1 = OUT_MASK_VALUE;
338 // unsigned char previousPixelValue2 = OUT_MASK_VALUE;
339 // for (p.x = left; p.x <= right; p.x++, q++)
340 // {
341 // if (*p == OUT_MASK_VALUE && previousPixelValue1 == IN_MASK_VALUE && previousPixelValue2 == OUT_MASK_VALUE) // we just passed over a single one pixel line => start filling
342 // {
343
344 // *q = IN_MASK_VALUE;
345 // }
346 // }
347 // }
348
349
350 // MaskPoint p(left, top);
351 // for (p.y = top; p.y <= bottom; p.y++)
352 // {
353 // unsigned char* q = reinterpret_cast<unsigned char*>(mask_->GetRow(p.y)) + left;
354 // for (p.x = left; p.x <= right; p.x++, q++)
355 // {
356 // if (isInside(corners_, p))
357 // {
358 // *q = IN_MASK_VALUE;
359 // }
360 // }
361 // }
362
245 } 363 }
246 364
247 } 365 }