changeset 4443:fd958175c5b9

ImageProcessing::ConvertJpegYCbCrToRgb()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 12 Jan 2021 13:07:15 +0100
parents f77ee6e6cf47
children 11ea0a05115b
files OrthancFramework/Sources/Images/ImageProcessing.cpp OrthancFramework/Sources/Images/ImageProcessing.h
diffstat 2 files changed, 59 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/Images/ImageProcessing.cpp	Mon Jan 11 14:32:44 2021 +0100
+++ b/OrthancFramework/Sources/Images/ImageProcessing.cpp	Tue Jan 12 13:07:15 2021 +0100
@@ -2570,4 +2570,60 @@
 
     return target.release();
   }
+
+
+  void ImageProcessing::ConvertJpegYCbCrToRgb(ImageAccessor& image)
+  {
+    // http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2
+    // https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion
+    
+    // TODO - Check out the outcome of Mathieu's discussion about
+    // truncation of YCbCr-to-RGB conversion:
+    // https://groups.google.com/forum/#!msg/comp.protocols.dicom/JHuGeyWbTz8/ARoTWrJzAQAJ
+
+    const unsigned int width = image.GetWidth();
+    const unsigned int height = image.GetHeight();
+    const unsigned int pitch = image.GetPitch();
+    uint8_t* buffer = reinterpret_cast<uint8_t*>(image.GetBuffer());
+        
+    if (image.GetFormat() != PixelFormat_RGB24 ||
+        pitch < 3 * width)
+    {
+      throw OrthancException(ErrorCode_IncompatibleImageFormat);
+    }
+
+    for (unsigned int y = 0; y < height; y++)
+    {
+      uint8_t* p = buffer + y * pitch;
+          
+      for (unsigned int x = 0; x < width; x++, p += 3)
+      {
+        const float Y  = p[0];
+        const float Cb = p[1];
+        const float Cr = p[2];
+
+        const float result[3] = {
+          Y                             + 1.402f    * (Cr - 128.0f),
+          Y - 0.344136f * (Cb - 128.0f) - 0.714136f * (Cr - 128.0f),
+          Y + 1.772f    * (Cb - 128.0f)
+        };
+
+        for (uint8_t i = 0; i < 3 ; i++)
+        {
+          if (result[i] < 0)
+          {
+            p[i] = 0;
+          }
+          else if (result[i] > 255)
+          {
+            p[i] = 255;
+          }
+          else
+          {
+            p[i] = static_cast<uint8_t>(result[i]);
+          }
+        }    
+      }
+    }
+  }
 }
--- a/OrthancFramework/Sources/Images/ImageProcessing.h	Mon Jan 11 14:32:44 2021 +0100
+++ b/OrthancFramework/Sources/Images/ImageProcessing.h	Tue Jan 12 13:07:15 2021 +0100
@@ -197,5 +197,8 @@
     static ImageAccessor* FitSizeKeepAspectRatio(const ImageAccessor& source,
                                                  unsigned int width,
                                                  unsigned int height);
+
+    // https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion
+    static void ConvertJpegYCbCrToRgb(ImageAccessor& image /* inplace */);
   };
 }