Mercurial > hg > orthanc-stone
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 } |