changeset 859:610a9a1ed855 jpeg

ImageProcessing::Convert
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 06 Jun 2014 18:12:31 +0200
parents ebc41566f742
children 80c7e53a69b5
files Core/ImageFormats/ImageProcessing.cpp OrthancServer/FromDcmtkBridge.cpp OrthancServer/Internals/DicomImageDecoder.cpp OrthancServer/Internals/DicomImageDecoder.h
diffstat 4 files changed, 161 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/Core/ImageFormats/ImageProcessing.cpp	Fri Jun 06 15:25:31 2014 +0200
+++ b/Core/ImageFormats/ImageProcessing.cpp	Fri Jun 06 18:12:31 2014 +0200
@@ -37,9 +37,45 @@
 
 #include <cassert>
 #include <string.h>
+#include <limits>
+#include <stdint.h>
+
+#include <stdio.h>
 
 namespace Orthanc
 {
+  template <typename TargetType, typename SourceType>
+  static void ConvertInternal(ImageAccessor& target,
+                              const ImageAccessor& source)
+  {
+    const TargetType minValue = std::numeric_limits<TargetType>::min();
+    const TargetType maxValue = std::numeric_limits<TargetType>::max();
+
+    for (unsigned int y = 0; y < source.GetHeight(); y++)
+    {
+      TargetType* t = reinterpret_cast<TargetType*>(target.GetRow(y));
+      const SourceType* s = reinterpret_cast<const SourceType*>(source.GetConstRow(y));
+
+      for (unsigned int x = 0; x < source.GetWidth(); x++, t++, s++)
+      {
+        if (static_cast<int32_t>(*s) < static_cast<int32_t>(minValue))
+        {
+          *t = minValue;
+        }
+        else if (static_cast<int32_t>(*s) > static_cast<int32_t>(maxValue))
+        {
+          *t = maxValue;
+        }
+        else
+        {
+          *t = static_cast<TargetType>(*s);
+        }
+      }
+    }
+  }
+
+
+
   void ImageProcessing::Copy(ImageAccessor& target,
                              const ImageAccessor& source)
   {
@@ -80,6 +116,50 @@
       return;
     }
 
+    if (target.GetFormat() == PixelFormat_Grayscale16 &&
+        source.GetFormat() == PixelFormat_Grayscale8)
+    {
+      ConvertInternal<uint16_t, uint8_t>(target, source);
+      return;
+    }
+
+    if (target.GetFormat() == PixelFormat_SignedGrayscale16 &&
+        source.GetFormat() == PixelFormat_Grayscale8)
+    {
+      ConvertInternal<int16_t, uint8_t>(target, source);
+      return;
+    }
+
+    if (target.GetFormat() == PixelFormat_Grayscale8 &&
+        source.GetFormat() == PixelFormat_Grayscale16)
+    {
+      printf("ICI\n");
+      ConvertInternal<uint8_t, uint16_t>(target, source);
+      return;
+    }
+
+    if (target.GetFormat() == PixelFormat_SignedGrayscale16 &&
+        source.GetFormat() == PixelFormat_Grayscale16)
+    {
+      ConvertInternal<int16_t, uint16_t>(target, source);
+      return;
+    }
+
+    if (target.GetFormat() == PixelFormat_Grayscale8 &&
+        source.GetFormat() == PixelFormat_SignedGrayscale16)
+    {
+      printf("ICI2\n");
+      ConvertInternal<uint8_t, int16_t>(target, source);
+      return;
+    }
+
+    if (target.GetFormat() == PixelFormat_Grayscale16 &&
+        source.GetFormat() == PixelFormat_SignedGrayscale16)
+    {
+      ConvertInternal<uint16_t, int16_t>(target, source);
+      return;
+    }
+
     throw OrthancException(ErrorCode_NotImplemented);
   }
 
--- a/OrthancServer/FromDcmtkBridge.cpp	Fri Jun 06 15:25:31 2014 +0200
+++ b/OrthancServer/FromDcmtkBridge.cpp	Fri Jun 06 18:12:31 2014 +0200
@@ -526,6 +526,20 @@
                                         unsigned int frame,
                                         ImageExtractionMode mode)
   {
+    // TODO CONTINUE THIS
+    if (mode == ImageExtractionMode_UInt8)
+    {
+      ImageBuffer tmp;
+      if (DicomImageDecoder::Decode(tmp, dataset, frame, PixelFormat_Grayscale8, DicomImageDecoder::Mode_Truncate))
+      {
+        printf("%d %d %d\n", tmp.GetWidth(), tmp.GetHeight(), tmp.GetFormat());
+        ImageAccessor accessor(tmp.GetAccessor());
+        PngWriter writer;
+        writer.WriteToMemory(result, accessor);
+        return;
+      }
+    }
+
     // See also: http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data
 
     std::auto_ptr<DicomIntegerPixelAccessor> accessor;
--- a/OrthancServer/Internals/DicomImageDecoder.cpp	Fri Jun 06 15:25:31 2014 +0200
+++ b/OrthancServer/Internals/DicomImageDecoder.cpp	Fri Jun 06 18:12:31 2014 +0200
@@ -447,14 +447,14 @@
       }
       catch (OrthancException&)
       {
-        // Unsupported conversion
+        // Unsupported conversion, use the slow version
       }
     }
 
 
     /**
-     * Loop over the DICOM buffer, storing its value into the target
-     * image.
+     * Slow version : loop over the DICOM buffer, storing its value
+     * into the target image.
      **/
 
     if (!fastVersionSuccess)
@@ -536,6 +536,7 @@
 
 
 
+
   bool DicomImageDecoder::Decode(ImageBuffer& target,
                                  DcmDataset& dataset,
                                  unsigned int frame)
@@ -585,4 +586,45 @@
 
     return false;
   }
+
+
+  bool DicomImageDecoder::Decode(ImageBuffer& target,
+                                 DcmDataset& dataset,
+                                 unsigned int frame,
+                                 PixelFormat format,
+                                 Mode mode)
+  {
+    // TODO OPTIMIZE THIS !!!
+
+    ImageBuffer tmp;
+    if (!Decode(tmp, dataset, frame))
+    {
+      return false;
+    }
+
+    target.SetFormat(format);
+    target.SetWidth(tmp.GetWidth());
+    target.SetHeight(tmp.GetHeight());
+
+    switch (mode)
+    {
+      case Mode_Truncate:
+      {
+        ImageAccessor a(target.GetAccessor());
+        ImageAccessor b(tmp.GetAccessor());
+        printf("IN\n");
+        ImageProcessing::Convert(a, b);
+        printf("OUT\n");
+        return true;
+      }
+
+      default:
+        throw OrthancException(ErrorCode_NotImplemented);
+    }
+
+    return false;
+  }
+
+
+
 }
--- a/OrthancServer/Internals/DicomImageDecoder.h	Fri Jun 06 15:25:31 2014 +0200
+++ b/OrthancServer/Internals/DicomImageDecoder.h	Fri Jun 06 18:12:31 2014 +0200
@@ -40,8 +40,14 @@
 {
   class DicomImageDecoder
   {
-  public:   // TODO SWITCH TO PRIVATE
-    //private:
+  public:
+    enum Mode
+    {
+      Mode_Truncate,
+      Mode_Stretch
+    };
+
+  private:
     class ImageSource;
 
     static void DecodeUncompressedImageInternal(ImageBuffer& target,
@@ -53,6 +59,7 @@
     static void SetupImageBuffer(ImageBuffer& target,
                                  DcmDataset& dataset);
 
+  public:   // TODO SWITCH TO PRIVATE
     static bool DecodePsmctRle1(std::string& output,
                                 DcmDataset& dataset);
 
@@ -65,6 +72,12 @@
                                         DcmDataset& dataset,
                                         unsigned int frame);
 
+    static void DecodeUncompressedImage(ImageBuffer& target,
+                                        DcmDataset& dataset,
+                                        unsigned int frame,
+                                        PixelFormat format,
+                                        Mode mode);
+
 #if ORTHANC_JPEG_LOSSLESS_ENABLED == 1
     static void DecodeJpegLossless(ImageBuffer& target,
                                    DcmDataset& dataset,
@@ -74,5 +87,12 @@
     static bool Decode(ImageBuffer& target,
                        DcmDataset& dataset,
                        unsigned int frame);
+
+    static bool Decode(ImageBuffer& target,
+                       DcmDataset& dataset,
+                       unsigned int frame,
+                       PixelFormat format,
+                       Mode mode);
+
   };
 }