diff Framework/Jpeg2000Reader.cpp @ 217:20bc074ec19a

Viewer can display DICOM pyramids whose tile sizes vary across levels
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 12 Jan 2021 14:24:18 +0100
parents 1e864138f0da
children 4eefa34657f0
line wrap: on
line diff
--- a/Framework/Jpeg2000Reader.cpp	Tue Jan 12 10:21:36 2021 +0100
+++ b/Framework/Jpeg2000Reader.cpp	Tue Jan 12 14:24:18 2021 +0100
@@ -25,6 +25,7 @@
 #include "ImageToolbox.h"
 
 #include <Compatibility.h>  // For std::unique_ptr
+#include <Images/ImageProcessing.h>
 #include <OrthancException.h>
 #include <SystemToolbox.h>
 
@@ -40,8 +41,9 @@
 typedef opj_dinfo_t opj_codec_t;
 typedef opj_cio_t opj_stream_t;
 #elif ORTHANC_OPENJPEG_MAJOR_VERSION == 2
+// OK, no need for compatibility macros
 #else
-#error Unsupported version of OpenJpeg
+#  error Unsupported version of OpenJpeg
 #endif
 
 
@@ -295,27 +297,80 @@
     {
     private:
       opj_image_t* image_;
+      
+      Orthanc::ImageAccessor* ExtractChannel(unsigned int channel)
+      {
+        const unsigned int width = image_->comps[channel].w;
+        const unsigned int height = image_->comps[channel].h;
+        
+        std::unique_ptr<Orthanc::ImageAccessor> target(
+          new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false));
 
+        const int32_t* q = image_->comps[channel].data;
+        assert(q != NULL);
+
+        for (unsigned int y = 0; y < height; y++)
+        {
+          uint8_t *p = reinterpret_cast<uint8_t*>(target->GetRow(y));
+
+          for (unsigned int x = 0; x < width; x++, p++, q++)
+          {
+            *p = *q;
+          }
+        }        
+
+        return target.release();
+      }
+      
       void CopyChannel(Orthanc::ImageAccessor& target,
                        unsigned int channel,
                        unsigned int targetIncrement)
       {
-        int32_t* q = image_->comps[channel].data;
-        assert(q != NULL);
-
         const unsigned int width = target.GetWidth();
         const unsigned int height = target.GetHeight();
 
-        for (unsigned int y = 0; y < height; y++)
+        if (0 &&   // TODO
+            width == image_->comps[channel].w &&
+            height == image_->comps[channel].h)
         {
-          uint8_t *p = reinterpret_cast<uint8_t*>(target.GetRow(y)) + channel;
+          const int32_t* q = image_->comps[channel].data;
+          assert(q != NULL);
+
+          for (unsigned int y = 0; y < height; y++)
+          {
+            uint8_t *p = reinterpret_cast<uint8_t*>(target.GetRow(y)) + channel;
 
-          for (unsigned int x = 0; x < width; x++, p += targetIncrement)
+            for (unsigned int x = 0; x < width; x++, p += targetIncrement)
+            {
+              *p = *q;
+              q++;
+            }
+          }
+        }
+        else
+        {
+          // This component is subsampled
+          std::unique_ptr<Orthanc::ImageAccessor> source(ExtractChannel(channel));
+          Orthanc::Image resized(Orthanc::PixelFormat_Grayscale8, width, height, false);
+          Orthanc::ImageProcessing::Resize(resized, *source);
+
+          assert(resized.GetWidth() == target.GetWidth() &&
+                 resized.GetHeight() == target.GetHeight() &&
+                 resized.GetFormat() == Orthanc::PixelFormat_Grayscale8 &&
+                 source->GetFormat() == Orthanc::PixelFormat_Grayscale8);            
+          
+          for (unsigned int y = 0; y < height; y++)
           {
-            *p = *q;
-            q++;
-          }
-        }        
+            const uint8_t *q = reinterpret_cast<const uint8_t*>(resized.GetConstRow(y));
+            uint8_t *p = reinterpret_cast<uint8_t*>(target.GetRow(y)) + channel;
+
+            for (unsigned int x = 0; x < width; x++, p += targetIncrement)
+            {
+              *p = *q;
+              q++;
+            }
+          }          
+        }
       }
 
     public:
@@ -375,12 +430,10 @@
 
         for (unsigned int c = 0; c < static_cast<unsigned int>(image_->numcomps); c++)
         {
-          if (image_->comps[c].dx != 1 ||
-              image_->comps[c].dy != 1 ||
-              image_->comps[c].x0 != 0 ||
+          if (image_->comps[c].x0 != 0 ||
               image_->comps[c].y0 != 0 ||
-              image_->comps[c].w != image_->x1 ||
-              image_->comps[c].h != image_->y1 ||
+              image_->comps[c].dx * image_->comps[c].w != image_->x1 ||
+              image_->comps[c].dy * image_->comps[c].h != image_->y1 ||
               image_->comps[c].prec != 8 ||
               image_->comps[c].sgnd != 0)
           {
@@ -429,7 +482,6 @@
 
         return image.release();
       }
-
     };
   }
 
@@ -442,11 +494,11 @@
     OpenJpegImage image(decoder, input);
     
     image_.reset(image.ProvideImage());
-    AssignReadOnly(image_->GetFormat(), 
+    AssignWritable(image_->GetFormat(), 
                    image_->GetWidth(),
                    image_->GetHeight(), 
                    image_->GetPitch(), 
-                   image_->GetConstBuffer());
+                   image_->GetBuffer());
   }