comparison Core/Images/ImageProcessing.cpp @ 3548:e1ce68692069

ImageProcessing::ApplyWindowing
author Alain Mazy <alain@mazy.be>
date Thu, 24 Oct 2019 11:40:02 +0200
parents dabe17e23e23
children 0f5f9a5eed25
comparison
equal deleted inserted replaced
3547:dabe17e23e23 3548:e1ce68692069
472 memcpy(target.GetRow(y), source.GetConstRow(y), lineSize); 472 memcpy(target.GetRow(y), source.GetConstRow(y), lineSize);
473 } 473 }
474 } 474 }
475 475
476 476
477 void ImageProcessing::ApplyWindowing(ImageAccessor& target,
478 const ImageAccessor& source,
479 float windowCenter,
480 float windowWidth,
481 Orthanc::PhotometricInterpretation sourcePhotometricInterpretation)
482 {
483 if (source.GetFormat() != Orthanc::PixelFormat_Float32)
484 {
485 throw OrthancException(ErrorCode_NotImplemented);
486 }
487
488 if (sourcePhotometricInterpretation != Orthanc::PhotometricInterpretation_Monochrome1
489 && sourcePhotometricInterpretation != Orthanc::PhotometricInterpretation_Monochrome2)
490 {
491 throw OrthancException(ErrorCode_ParameterOutOfRange);
492 }
493
494 if (target.GetWidth() != source.GetWidth() ||
495 target.GetHeight() != source.GetHeight())
496 {
497 throw OrthancException(ErrorCode_IncompatibleImageSize);
498 }
499
500 unsigned int targetBytesPerPixels = target.GetBytesPerPixel();
501 unsigned int targetChannelsPerPixels = 0;
502 switch (target.GetFormat())
503 {
504 case Orthanc::PixelFormat_Grayscale8:
505 targetChannelsPerPixels = 1;
506 break;
507 case Orthanc::PixelFormat_RGBA32:
508 case Orthanc::PixelFormat_BGRA32:
509 case Orthanc::PixelFormat_RGB24:
510 targetChannelsPerPixels = 3;
511 break;
512 default:
513 throw OrthancException(ErrorCode_NotImplemented);
514 }
515
516 const float a = windowCenter - windowWidth / 2.0f;
517 const float slope = 256.0f / windowWidth;
518 bool isInverted = sourcePhotometricInterpretation == Orthanc::PhotometricInterpretation_Monochrome1;
519
520 const unsigned int width = source.GetWidth();
521 const unsigned int height = source.GetHeight();
522
523 assert(sizeof(float) == 4);
524
525 for (unsigned int y = 0; y < height; y++)
526 {
527 const float* p = reinterpret_cast<const float*>(source.GetConstRow(y));
528 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
529
530 for (unsigned int x = 0; x < width; x++)
531 {
532 float v = (*p - a) * slope;
533 if (v <= 0)
534 {
535 v = 0;
536 }
537 else if (v >= 255)
538 {
539 v = 255;
540 }
541
542 uint8_t vv = static_cast<uint8_t>(v);
543
544 if (isInverted)
545 {
546 vv = 255 - vv;
547 }
548
549 for (unsigned int c = 0; c < targetChannelsPerPixels; c++)
550 {
551 q[c] = vv;
552 }
553
554 p++;
555 q += targetBytesPerPixels;
556 }
557 }
558
559 }
560
561
477 void ImageProcessing::Convert(ImageAccessor& target, 562 void ImageProcessing::Convert(ImageAccessor& target,
478 const ImageAccessor& source) 563 const ImageAccessor& source)
479 { 564 {
480 if (target.GetWidth() != source.GetWidth() || 565 if (target.GetWidth() != source.GetWidth() ||
481 target.GetHeight() != source.GetHeight()) 566 target.GetHeight() != source.GetHeight())
966 } 1051 }
967 } 1052 }
968 } 1053 }
969 1054
970 void ImageProcessing::Set(ImageAccessor& image, 1055 void ImageProcessing::Set(ImageAccessor& image,
971 uint8_t red, 1056 uint8_t red,
972 uint8_t green, 1057 uint8_t green,
973 uint8_t blue, 1058 uint8_t blue,
974 ImageAccessor& alpha) 1059 ImageAccessor& alpha)
975 { 1060 {
976 uint8_t p[4]; 1061 uint8_t p[4];
977 1062
978 if (alpha.GetWidth() != image.GetWidth() || alpha.GetHeight() != image.GetHeight()) 1063 if (alpha.GetWidth() != image.GetWidth() || alpha.GetHeight() != image.GetHeight())
979 { 1064 {
1848 source.GetHeight() == target.GetHeight()) 1933 source.GetHeight() == target.GetHeight())
1849 { 1934 {
1850 Copy(target, source); 1935 Copy(target, source);
1851 return; 1936 return;
1852 } 1937 }
1853 1938
1854 switch (source.GetFormat()) 1939 switch (source.GetFormat())
1855 { 1940 {
1856 case PixelFormat_Grayscale8: 1941 case PixelFormat_Grayscale8:
1857 ResizeInternal<PixelFormat_Grayscale8>(target, source); 1942 ResizeInternal<PixelFormat_Grayscale8>(target, source);
1943 break;
1944
1945 case PixelFormat_Float32:
1946 ResizeInternal<PixelFormat_Float32>(target, source);
1858 break; 1947 break;
1859 1948
1860 case PixelFormat_RGB24: 1949 case PixelFormat_RGB24:
1861 ResizeInternal<PixelFormat_RGB24>(target, source); 1950 ResizeInternal<PixelFormat_RGB24>(target, source);
1862 break; 1951 break;