comparison RenderingPlugin/Sources/Plugin.cpp @ 1943:a601b8abc1cb

rendering plugin: subpixel accuracy in rt-struct
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 02 Jun 2022 10:52:47 +0200
parents bd527bbc34df
children 3daecfa5791c
comparison
equal deleted inserted replaced
1942:09de7321d3b9 1943:a601b8abc1cb
218 bool flipX_; 218 bool flipX_;
219 bool flipY_; 219 bool flipY_;
220 bool hasResize_; 220 bool hasResize_;
221 unsigned int targetWidth_; 221 unsigned int targetWidth_;
222 unsigned int targetHeight_; 222 unsigned int targetHeight_;
223 bool hasInterpolation_;
224 OrthancStone::ImageInterpolation interpolation_;
223 225
224 void ApplyInternal(Orthanc::ImageAccessor& target, 226 void ApplyInternal(Orthanc::ImageAccessor& target,
225 const Orthanc::ImageAccessor& source) 227 const Orthanc::ImageAccessor& source)
226 { 228 {
227 if (source.GetWidth() == 0 || 229 if (source.GetWidth() == 0 ||
237 else 239 else
238 { 240 {
239 OrthancStone::AffineTransform2D transform = ComputeTransform(source.GetWidth(), source.GetHeight()); 241 OrthancStone::AffineTransform2D transform = ComputeTransform(source.GetWidth(), source.GetHeight());
240 242
241 OrthancStone::ImageInterpolation interpolation; 243 OrthancStone::ImageInterpolation interpolation;
242 244
243 if (source.GetFormat() == Orthanc::PixelFormat_RGB24) 245 if (hasInterpolation_)
244 { 246 {
245 LOG(WARNING) << "Bilinear interpolation for color images is not implemented yet"; 247 interpolation = interpolation_;
248 }
249 else if (source.GetFormat() == Orthanc::PixelFormat_RGB24)
250 {
251 // Bilinear interpolation for color images is not implemented yet
246 interpolation = OrthancStone::ImageInterpolation_Nearest; 252 interpolation = OrthancStone::ImageInterpolation_Nearest;
247 } 253 }
248 else 254 else
249 { 255 {
250 interpolation = OrthancStone::ImageInterpolation_Bilinear; 256 interpolation = OrthancStone::ImageInterpolation_Bilinear;
289 flipX_ = false; 295 flipX_ = false;
290 flipY_ = false; 296 flipY_ = false;
291 hasResize_ = false; 297 hasResize_ = false;
292 targetWidth_ = 0; 298 targetWidth_ = 0;
293 targetHeight_ = 0; 299 targetHeight_ = 0;
300 hasInterpolation_ = false;
294 } 301 }
295 302
296 303
297 OrthancStone::AffineTransform2D ComputeTransform(unsigned int sourceWidth, 304 OrthancStone::AffineTransform2D ComputeTransform(unsigned int sourceWidth,
298 unsigned int sourceHeight) const 305 unsigned int sourceHeight) const
377 targetWidth_ = ParseUnsignedInteger(key, tokens[0]); 384 targetWidth_ = ParseUnsignedInteger(key, tokens[0]);
378 targetHeight_ = ParseUnsignedInteger(key, tokens[1]); 385 targetHeight_ = ParseUnsignedInteger(key, tokens[1]);
379 hasResize_ = true; 386 hasResize_ = true;
380 return true; 387 return true;
381 } 388 }
389 }
390 else if (key == "interpolation")
391 {
392 if (value == "nearest")
393 {
394 interpolation_ = OrthancStone::ImageInterpolation_Nearest;
395 }
396 else if (value == "bilinear")
397 {
398 interpolation_ = OrthancStone::ImageInterpolation_Bilinear;
399 }
400 else
401 {
402 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
403 "Unknown interpolation (must be \"nearest\" or \"bilinear\"): " + value);
404 }
405
406 hasInterpolation_ = true;
407 return true;
382 } 408 }
383 else 409 else
384 { 410 {
385 return false; 411 return false;
386 } 412 }
677 703
678 virtual void Fill(int y, 704 virtual void Fill(int y,
679 int x1, 705 int x1,
680 int x2) ORTHANC_OVERRIDE 706 int x2) ORTHANC_OVERRIDE
681 { 707 {
682 assert(x1 > 0 && 708 assert(x1 <= x2);
683 x1 <= x2 && 709
684 x2 < static_cast<int>(image_.GetWidth()) && 710 if (y >= 0 &&
685 y > 0 && 711 y < static_cast<int>(image_.GetHeight()))
686 y < static_cast<int>(image_.GetHeight())); 712 {
687 713 x1 = std::max(x1, 0);
688 uint8_t* p = reinterpret_cast<uint8_t*>(image_.GetRow(y)) + x1; 714 x2 = std::min(x2, static_cast<int>(image_.GetWidth()) - 1);
689 715
690 for (int i = x1; i <= x2; i++, p++) 716 uint8_t* p = reinterpret_cast<uint8_t*>(image_.GetRow(y)) + x1;
691 { 717
692 *p = (*p ^ 0xff); 718 for (int i = x1; i <= x2; i++, p++)
719 {
720 *p = (*p ^ 0xff);
721 }
693 } 722 }
694 } 723 }
695 }; 724 };
696 725
697 DataAugmentationParameters dataAugmentation; 726 DataAugmentationParameters dataAugmentation;
780 std::vector<Orthanc::ImageProcessing::ImagePoint> points; 809 std::vector<Orthanc::ImageProcessing::ImagePoint> points;
781 points.reserve(it->size()); 810 points.reserve(it->size());
782 811
783 for (size_t i = 0; i < it->size(); i++) 812 for (size_t i = 0; i < it->size(); i++)
784 { 813 {
814 // The (0.5, 0.5) offset is due to the fact that DICOM
815 // coordinates are expressed wrt. the CENTER of the voxels
816
785 double x, y; 817 double x, y;
786 parameters->GetGeometry().ProjectPoint(x, y, (*it) [i]); 818 parameters->GetGeometry().ProjectPoint(x, y, (*it) [i]);
787 x /= parameters->GetPixelSpacingX(); 819 x = x / parameters->GetPixelSpacingX() + 0.5;
788 y /= parameters->GetPixelSpacingY(); 820 y = y / parameters->GetPixelSpacingY() + 0.5;
789 821
790 transform.Apply(x, y); 822 transform.Apply(x, y);
791 823
792 points.push_back(Orthanc::ImageProcessing::ImagePoint(x, y)); 824 points.push_back(Orthanc::ImageProcessing::ImagePoint(x, y));
793 } 825 }