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