Mercurial > hg > orthanc-stone
comparison Framework/Radiography/RadiographyMaskLayer.cpp @ 1196:a5f2a6b04a31
RadiographyScene: windowing is now only applied to the Dicom layer
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Wed, 27 Nov 2019 17:51:33 +0100 |
parents | 077f28e3ea3d |
children | ab958fd99b07 |
comparison
equal
deleted
inserted
replaced
1191:c6a36ecd641d | 1196:a5f2a6b04a31 |
---|---|
24 | 24 |
25 #include "RadiographyScene.h" | 25 #include "RadiographyScene.h" |
26 #include "Core/Images/Image.h" | 26 #include "Core/Images/Image.h" |
27 #include "Core/Images/ImageProcessing.h" | 27 #include "Core/Images/ImageProcessing.h" |
28 #include <Core/OrthancException.h> | 28 #include <Core/OrthancException.h> |
29 #include "../Toolbox/ImageGeometry.h" | |
29 | 30 |
30 namespace OrthancStone | 31 namespace OrthancStone |
31 { | 32 { |
32 const unsigned char IN_MASK_VALUE = 0x00; | 33 const unsigned char IN_MASK_VALUE = 0x77; |
33 const unsigned char OUT_MASK_VALUE = 0xFF; | 34 const unsigned char OUT_MASK_VALUE = 0xFF; |
34 | 35 |
35 const AffineTransform2D& RadiographyMaskLayer::GetTransform() const | 36 const AffineTransform2D& RadiographyMaskLayer::GetTransform() const |
36 { | 37 { |
37 return dicomLayer_.GetTransform(); | 38 return dicomLayer_.GetTransform(); |
74 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); | 75 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this)); |
75 } | 76 } |
76 | 77 |
77 void RadiographyMaskLayer::Render(Orthanc::ImageAccessor& buffer, | 78 void RadiographyMaskLayer::Render(Orthanc::ImageAccessor& buffer, |
78 const AffineTransform2D& viewTransform, | 79 const AffineTransform2D& viewTransform, |
79 ImageInterpolation interpolation) const | 80 ImageInterpolation interpolation, |
81 float windowCenter, | |
82 float windowWidth, | |
83 bool applyWindowing) const | |
80 { | 84 { |
81 if (dicomLayer_.GetWidth() == 0) // nothing to do if the DICOM layer is not displayed (or not loaded) | 85 if (dicomLayer_.GetWidth() == 0) // nothing to do if the DICOM layer is not displayed (or not loaded) |
82 return; | 86 return; |
83 | 87 |
84 if (invalidated_) | 88 if (invalidated_) |
106 Orthanc::ImageAccessor cropped; | 110 Orthanc::ImageAccessor cropped; |
107 mask_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); | 111 mask_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); |
108 | 112 |
109 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); | 113 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); |
110 | 114 |
111 t.Apply(tmp, cropped, interpolation, true /* clear */); | 115 t.Apply(tmp, cropped, ImageInterpolation_Nearest, true /* clear */); |
116 | |
117 unsigned int x1, y1, x2, y2; | |
118 OrthancStone::GetProjectiveTransformExtent(x1, y1, x2, y2, | |
119 t.GetHomogeneousMatrix(), | |
120 cropped.GetWidth(), | |
121 cropped.GetHeight(), | |
122 buffer.GetWidth(), | |
123 buffer.GetHeight()); | |
124 | |
125 // we have observed vertical lines at the image border (probably due to bilinear filtering of the DICOM image when it is not aligned with the buffer pixels) | |
126 // -> draw the mask one line further on each side | |
127 if (x1 >= 1) | |
128 { | |
129 x1 = x1 - 1; | |
130 } | |
131 if (x2 < buffer.GetWidth() - 2) | |
132 { | |
133 x2 = x2 + 1; | |
134 } | |
112 | 135 |
113 // Blit | 136 // Blit |
114 const unsigned int width = buffer.GetWidth(); | 137 for (unsigned int y = y1; y <= y2; y++) |
115 const unsigned int height = buffer.GetHeight(); | 138 { |
139 float *q = reinterpret_cast<float*>(buffer.GetRow(y)) + x1; | |
140 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)) + x1; | |
116 | 141 |
117 for (unsigned int y = 0; y < height; y++) | 142 for (unsigned int x = x1; x <= x2; x++, p++, q++) |
118 { | |
119 float *q = reinterpret_cast<float*>(buffer.GetRow(y)); | |
120 const uint8_t *p = reinterpret_cast<uint8_t*>(tmp.GetRow(y)); | |
121 | |
122 for (unsigned int x = 0; x < width; x++, p++, q++) | |
123 { | 143 { |
124 if (*p == OUT_MASK_VALUE) | 144 if (*p != IN_MASK_VALUE) |
125 *q = foreground_; | 145 *q = foreground_; |
126 // else keep the underlying pixel value | 146 // else keep the underlying pixel value |
127 } | 147 } |
128 } | 148 } |
129 | 149 |