Mercurial > hg > orthanc-stone
diff 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 |
line wrap: on
line diff
--- a/Framework/Radiography/RadiographyMaskLayer.cpp Tue Feb 12 12:22:13 2019 +0100 +++ b/Framework/Radiography/RadiographyMaskLayer.cpp Wed Feb 13 12:04:02 2019 +0100 @@ -29,6 +29,18 @@ namespace OrthancStone { + const unsigned char IN_MASK_VALUE = 0x00; + const unsigned char OUT_MASK_VALUE = 0xFF; + + const AffineTransform2D& RadiographyMaskLayer::GetTransform() const + { + return dicomLayer_.GetTransform(); + } + + const AffineTransform2D& RadiographyMaskLayer::GetTransformInverse() const + { + return dicomLayer_.GetTransformInverse(); + } void ComputeMaskExtent(unsigned int& left, unsigned int& right, unsigned int& top, unsigned int& bottom, const std::vector<MaskPoint>& corners) { @@ -66,18 +78,6 @@ DrawMask(); -// for (unsigned int i = 0; i < 100; i++) -// { -// for (unsigned int j = 0; j < 50; j++) -// { -// if ((i + j) % 2 == 1) -// { -// Orthanc::ImageAccessor region; -// mask_->GetRegion(region, i* 20, j * 20, 20, 20); -// Orthanc::ImageProcessing::Set(region, 255); -// } -// } -// } invalidated_ = false; } @@ -112,7 +112,7 @@ for (unsigned int x = 0; x < width; x++, p++, q++) { - if (*p == 0) + if (*p == OUT_MASK_VALUE) *q = foreground_; // else keep the underlying pixel value } @@ -214,6 +214,36 @@ return count&1; // Same as (count%2 == 1) } + void RadiographyMaskLayer::DrawLine(const MaskPoint& start, const MaskPoint& end) const + { + int dx = (int)(end.x) - (int)(start.x); + int dy = (int)(end.y) - (int)(start.y); + + if (std::abs(dx) > std::abs(dy)) + { // the line is closer to horizontal + + int incx = dx / std::abs(dx); + double incy = (double)(dy)/(double)(dx); + double y = (double)(start.y); + for (int x = (int)(start.x); x != (int)(end.x); x += incx, y += incy) + { + unsigned char* p = reinterpret_cast<unsigned char*>(mask_->GetRow((int)(y + 0.5))) + x; + *p = IN_MASK_VALUE; + } + } + else + { // the line is closer to vertical + int incy = dy / std::abs(dy); + double incx = (double)(dx)/(double)(dy); + double x = (double)(start.x); + for (int y = (int)(start.y); y != (int)(end.y); y += incy, x += incx) + { + unsigned char* p = reinterpret_cast<unsigned char*>(mask_->GetRow(y)) + (int)(x + 0.5); + *p = IN_MASK_VALUE; + } + } + } + void RadiographyMaskLayer::DrawMask() const { @@ -222,26 +252,114 @@ unsigned int top; unsigned int bottom; - ComputeMaskExtent(left, right, top, bottom, corners_); +// ComputeMaskExtent(left, right, top, bottom, corners_); - Orthanc::ImageProcessing::Set(*mask_, 0); + left = 0; + right = 2500; + top = 0; + bottom = 2500; + // first fill the complete image + Orthanc::ImageProcessing::Set(*mask_, OUT_MASK_VALUE); - MaskPoint p(left, top); - for (p.y = top; p.y <= bottom; p.y++) + { - unsigned char* q = reinterpret_cast<unsigned char*>(mask_->GetRow(p.y)); - for (p.x = left; p.x <= right; p.x++, q++) + // from http://alienryderflex.com/polygon_fill/ + std::auto_ptr<int> raiiNodeX(new int(corners_.size())); + + std::vector<int> nodeX; + nodeX.resize(corners_.size()); + int nodes, pixelX, pixelY, i, j, swap ; + + // Loop through the rows of the image. + for (pixelY = (int)top; pixelY < (int)bottom; pixelY++) { - if (isInside(corners_, p)) + // Build a list of nodes. + nodes = 0; + j = (int)corners_.size() - 1; + + for (i = 0; i < (int)corners_.size(); i++) + { + if ((int)corners_[i].y < pixelY && (int)corners_[j].y >= pixelY + || (int)corners_[j].y < pixelY && (int)corners_[i].y >= pixelY) + { + 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)); + } + j=i; + } + + // Sort the nodes, via a simple “Bubble” sort. + i=0; + while (i<nodes-1) { - *q = 255; + if (nodeX[i]>nodeX[i+1]) + { + swap=nodeX[i]; nodeX[i]=nodeX[i+1]; nodeX[i+1]=swap; if (i) i--; + } + else + { + i++; + } + } + + unsigned char* row = reinterpret_cast<unsigned char*>(mask_->GetRow(pixelY)); + // Fill the pixels between node pairs. + for (i=0; i<nodes; i+=2) + { + if (nodeX[i ]>=(int)right) + break; + if (nodeX[i+1]> (int)left) + { + if (nodeX[i ]< (int)left ) + nodeX[i ]=(int)left ; + if (nodeX[i+1]> (int)right) + nodeX[i+1]=(int)right; + for (pixelX=nodeX[i]; pixelX<nodeX[i+1]; pixelX++) + { + *(row + pixelX) = IN_MASK_VALUE; + } + } } } } -// Orthanc::ImageAccessor region; -// mask_->GetRegion(region, 100, 100, 1000, 1000); -// Orthanc::ImageProcessing::Set(region, 255); +// // draw lines +// for (size_t i = 1; i < corners_.size(); i++) +// { +// DrawLine(corners_[i-1], corners_[i]); +// } +// DrawLine(corners_[corners_.size()-1], corners_[0]); + +// // fill between lines +// MaskPoint p(left, top); +// for (p.y = top; p.y <= bottom; p.y++) +// { +// unsigned char* q = reinterpret_cast<unsigned char*>(mask_->GetRow(p.y)) + left; +// unsigned char previousPixelValue1 = OUT_MASK_VALUE; +// unsigned char previousPixelValue2 = OUT_MASK_VALUE; +// for (p.x = left; p.x <= right; p.x++, q++) +// { +// if (*p == OUT_MASK_VALUE && previousPixelValue1 == IN_MASK_VALUE && previousPixelValue2 == OUT_MASK_VALUE) // we just passed over a single one pixel line => start filling +// { + +// *q = IN_MASK_VALUE; +// } +// } +// } + + +// MaskPoint p(left, top); +// for (p.y = top; p.y <= bottom; p.y++) +// { +// unsigned char* q = reinterpret_cast<unsigned char*>(mask_->GetRow(p.y)) + left; +// for (p.x = left; p.x <= right; p.x++, q++) +// { +// if (isInside(corners_, p)) +// { +// *q = IN_MASK_VALUE; +// } +// } +// } + } }