changeset 1916:5bcf721bde4f

IImageWriter
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 09 Feb 2016 15:26:37 +0100
parents 7454019be8f3
children 7db4b909bec3
files Core/Images/IImageWriter.h Core/Images/ImageAccessor.cpp Core/Images/JpegWriter.cpp Core/Images/JpegWriter.h Core/Images/PngWriter.cpp Core/Images/PngWriter.h Plugins/Engine/OrthancPlugins.cpp UnitTestsSources/ImageTests.cpp
diffstat 8 files changed, 173 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/Images/IImageWriter.h	Tue Feb 09 15:26:37 2016 +0100
@@ -0,0 +1,83 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "ImageAccessor.h"
+#include "../Toolbox.h"
+
+#include <boost/noncopyable.hpp>
+
+namespace Orthanc
+{
+  class IImageWriter : public boost::noncopyable
+  {
+  protected:
+    virtual void WriteToMemoryInternal(std::string& compressed,
+                                       unsigned int width,
+                                       unsigned int height,
+                                       unsigned int pitch,
+                                       PixelFormat format,
+                                       const void* buffer) = 0;
+
+    virtual void WriteToFileInternal(const std::string& path,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int pitch,
+                                     PixelFormat format,
+                                     const void* buffer)
+    {
+      std::string compressed;
+      WriteToMemoryInternal(compressed, width, height, pitch, format, buffer);
+      Toolbox::WriteFile(compressed, path);
+    }
+
+  public:
+    virtual ~IImageWriter()
+    {
+    }
+
+    virtual void WriteToMemory(std::string& compressed,
+                               const ImageAccessor& accessor)
+    {
+      WriteToMemoryInternal(compressed, accessor.GetWidth(), accessor.GetHeight(),
+                            accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
+    }
+
+    virtual void WriteToFile(const std::string& path,
+                             const ImageAccessor& accessor)
+    {
+      WriteToFileInternal(path, accessor.GetWidth(), accessor.GetHeight(),
+                          accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
+    }
+  };
+}
--- a/Core/Images/ImageAccessor.cpp	Tue Feb 09 14:50:29 2016 +0100
+++ b/Core/Images/ImageAccessor.cpp	Tue Feb 09 15:26:37 2016 +0100
@@ -176,7 +176,10 @@
     pitch_ = pitch;
     buffer_ = const_cast<void*>(buffer);
 
-    assert(GetBytesPerPixel() * width_ <= pitch_);
+    if (GetBytesPerPixel() * width_ > pitch_)
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
   }
 
 
@@ -193,7 +196,10 @@
     pitch_ = pitch;
     buffer_ = buffer;
 
-    assert(GetBytesPerPixel() * width_ <= pitch_);
+    if (GetBytesPerPixel() * width_ > pitch_)
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
   }
 
 
--- a/Core/Images/JpegWriter.cpp	Tue Feb 09 14:50:29 2016 +0100
+++ b/Core/Images/JpegWriter.cpp	Tue Feb 09 15:26:37 2016 +0100
@@ -111,14 +111,15 @@
   }
 
 
-  void JpegWriter::WriteToFile(const char* filename,
-                               unsigned int width,
-                               unsigned int height,
-                               unsigned int pitch,
-                               PixelFormat format,
-                               const void* buffer)
+  void JpegWriter::WriteToFileInternal(const std::string& filename,
+                                       unsigned int width,
+                                       unsigned int height,
+                                       unsigned int pitch,
+                                       PixelFormat format,
+                                       const void* buffer)
   {
-    FILE* fp = fopen(filename, "wb");
+    // TODO This will not work on Windows system if the path contains non-ASCII characters
+    FILE* fp = fopen(filename.c_str(), "wb");
     if (fp == NULL)
     {
       throw OrthancException(ErrorCode_FullStorage);
@@ -156,12 +157,12 @@
   }
 
 
-  void JpegWriter::WriteToMemory(std::string& jpeg,
-                                 unsigned int width,
-                                 unsigned int height,
-                                 unsigned int pitch,
-                                 PixelFormat format,
-                                 const void* buffer)
+  void JpegWriter::WriteToMemoryInternal(std::string& jpeg,
+                                         unsigned int width,
+                                         unsigned int height,
+                                         unsigned int pitch,
+                                         PixelFormat format,
+                                         const void* buffer)
   {
     std::vector<uint8_t*> lines;
     GetLines(lines, height, pitch, format, buffer);
--- a/Core/Images/JpegWriter.h	Tue Feb 09 14:50:29 2016 +0100
+++ b/Core/Images/JpegWriter.h	Tue Feb 09 15:26:37 2016 +0100
@@ -32,16 +32,27 @@
 
 #pragma once
 
-#include "ImageAccessor.h"
-
-#include <string>
-#include <stdint.h>
-#include <boost/noncopyable.hpp>
+#include "IImageWriter.h"
 
 namespace Orthanc
 {
-  class JpegWriter : public boost::noncopyable
+  class JpegWriter : public IImageWriter
   {
+  protected:
+    virtual void WriteToFileInternal(const std::string& filename,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int pitch,
+                                     PixelFormat format,
+                                     const void* buffer);
+
+    virtual void WriteToMemoryInternal(std::string& jpeg,
+                                       unsigned int width,
+                                       unsigned int height,
+                                       unsigned int pitch,
+                                       PixelFormat format,
+                                       const void* buffer);
+
   private:
     uint8_t  quality_;
 
@@ -56,33 +67,5 @@
     {
       return quality_;
     }
-
-    void WriteToFile(const char* filename,
-                     unsigned int width,
-                     unsigned int height,
-                     unsigned int pitch,
-                     PixelFormat format,
-                     const void* buffer);
-
-    void WriteToMemory(std::string& jpeg,
-                       unsigned int width,
-                       unsigned int height,
-                       unsigned int pitch,
-                       PixelFormat format,
-                       const void* buffer);
-
-    void WriteToFile(const char* filename,
-                     const ImageAccessor& accessor)
-    {
-      WriteToFile(filename, accessor.GetWidth(), accessor.GetHeight(),
-                  accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
-
-    void WriteToMemory(std::string& jpeg,
-                       const ImageAccessor& accessor)
-    {
-      WriteToMemory(jpeg, accessor.GetWidth(), accessor.GetHeight(),
-                    accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
   };
 }
--- a/Core/Images/PngWriter.cpp	Tue Feb 09 14:50:29 2016 +0100
+++ b/Core/Images/PngWriter.cpp	Tue Feb 09 15:26:37 2016 +0100
@@ -202,16 +202,17 @@
   }
 
 
-  void PngWriter::WriteToFile(const char* filename,
-                              unsigned int width,
-                              unsigned int height,
-                              unsigned int pitch,
-                              PixelFormat format,
-                              const void* buffer)
+  void PngWriter::WriteToFileInternal(const std::string& filename,
+                                      unsigned int width,
+                                      unsigned int height,
+                                      unsigned int pitch,
+                                      PixelFormat format,
+                                      const void* buffer)
   {
     Prepare(width, height, pitch, format, buffer);
 
-    FILE* fp = fopen(filename, "wb");
+    // TODO This will not work on Windows system if the path contains non-ASCII characters
+    FILE* fp = fopen(filename.c_str(), "wb");
     if (!fp)
     {
       throw OrthancException(ErrorCode_CannotWriteFile);
@@ -232,7 +233,6 @@
 
 
 
-
   static void MemoryCallback(png_structp png_ptr, 
                              png_bytep data, 
                              png_size_t size)
@@ -243,12 +243,12 @@
 
 
 
-  void PngWriter::WriteToMemory(std::string& png,
-                                unsigned int width,
-                                unsigned int height,
-                                unsigned int pitch,
-                                PixelFormat format,
-                                const void* buffer)
+  void PngWriter::WriteToMemoryInternal(std::string& png,
+                                        unsigned int width,
+                                        unsigned int height,
+                                        unsigned int pitch,
+                                        PixelFormat format,
+                                        const void* buffer)
   {
     ChunkedBuffer chunks;
 
--- a/Core/Images/PngWriter.h	Tue Feb 09 14:50:29 2016 +0100
+++ b/Core/Images/PngWriter.h	Tue Feb 09 15:26:37 2016 +0100
@@ -32,16 +32,29 @@
 
 #pragma once
 
-#include "ImageAccessor.h"
+#include "IImageWriter.h"
 
-#include <boost/noncopyable.hpp>
 #include <boost/shared_ptr.hpp>
-#include <string>
 
 namespace Orthanc
 {
-  class PngWriter : public boost::noncopyable
+  class PngWriter : public IImageWriter
   {
+  protected:
+    virtual void WriteToFileInternal(const std::string& filename,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int pitch,
+                                     PixelFormat format,
+                                     const void* buffer);
+
+    virtual void WriteToMemoryInternal(std::string& png,
+                                       unsigned int width,
+                                       unsigned int height,
+                                       unsigned int pitch,
+                                       PixelFormat format,
+                                       const void* buffer);
+
   private:
     struct PImpl;
     boost::shared_ptr<PImpl> pimpl_;
@@ -61,33 +74,5 @@
     PngWriter();
 
     ~PngWriter();
-
-    void WriteToFile(const char* filename,
-                     unsigned int width,
-                     unsigned int height,
-                     unsigned int pitch,
-                     PixelFormat format,
-                     const void* buffer);
-
-    void WriteToMemory(std::string& png,
-                       unsigned int width,
-                       unsigned int height,
-                       unsigned int pitch,
-                       PixelFormat format,
-                       const void* buffer);
-
-    void WriteToFile(const char* filename,
-                     const ImageAccessor& accessor)
-    {
-      WriteToFile(filename, accessor.GetWidth(), accessor.GetHeight(),
-                  accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
-
-    void WriteToMemory(std::string& png,
-                       const ImageAccessor& accessor)
-    {
-      WriteToMemory(png, accessor.GetWidth(), accessor.GetHeight(),
-                    accessor.GetPitch(), accessor.GetFormat(), accessor.GetConstBuffer());
-    }
   };
 }
--- a/Plugins/Engine/OrthancPlugins.cpp	Tue Feb 09 14:50:29 2016 +0100
+++ b/Plugins/Engine/OrthancPlugins.cpp	Tue Feb 09 15:26:37 2016 +0100
@@ -1328,12 +1328,15 @@
 
     std::string compressed;
 
+    ImageAccessor accessor;
+    accessor.AssignReadOnly(Plugins::Convert(p.pixelFormat), p.width, p.height, p.pitch, p.buffer);
+
     switch (p.imageFormat)
     {
       case OrthancPluginImageFormat_Png:
       {
         PngWriter writer;
-        writer.WriteToMemory(compressed, p.width, p.height, p.pitch, Plugins::Convert(p.pixelFormat), p.buffer);
+        writer.WriteToMemory(compressed, accessor);
         break;
       }
 
@@ -1341,7 +1344,7 @@
       {
         JpegWriter writer;
         writer.SetQuality(p.quality);
-        writer.WriteToMemory(compressed, p.width, p.height, p.pitch, Plugins::Convert(p.pixelFormat), p.buffer);
+        writer.WriteToMemory(compressed, accessor);
         break;
       }
 
--- a/UnitTestsSources/ImageTests.cpp	Tue Feb 09 14:50:29 2016 +0100
+++ b/UnitTestsSources/ImageTests.cpp	Tue Feb 09 15:26:37 2016 +0100
@@ -66,7 +66,10 @@
     }
   }
 
-  w.WriteToFile("UnitTestsResults/ColorPattern.png", width, height, pitch, Orthanc::PixelFormat_RGB24, &image[0]);
+  Orthanc::ImageAccessor accessor;
+  accessor.AssignReadOnly(Orthanc::PixelFormat_RGB24, width, height, pitch, &image[0]);
+
+  w.WriteToFile("UnitTestsResults/ColorPattern.png", accessor);
 
   std::string f, md5;
   Orthanc::Toolbox::ReadFile(f, "UnitTestsResults/ColorPattern.png");
@@ -91,7 +94,10 @@
     }
   }
 
-  w.WriteToFile("UnitTestsResults/Gray8Pattern.png", width, height, pitch, Orthanc::PixelFormat_Grayscale8, &image[0]);
+  Orthanc::ImageAccessor accessor;
+  accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale8, width, height, pitch, &image[0]);
+
+  w.WriteToFile("UnitTestsResults/Gray8Pattern.png", accessor);
 
   std::string f, md5;
   Orthanc::Toolbox::ReadFile(f, "UnitTestsResults/Gray8Pattern.png");
@@ -118,7 +124,9 @@
     }
   }
 
-  w.WriteToFile("UnitTestsResults/Gray16Pattern.png", width, height, pitch, Orthanc::PixelFormat_Grayscale16, &image[0]);
+  Orthanc::ImageAccessor accessor;
+  accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]);
+  w.WriteToFile("UnitTestsResults/Gray16Pattern.png", accessor);
 
   std::string f, md5;
   Orthanc::Toolbox::ReadFile(f, "UnitTestsResults/Gray16Pattern.png");
@@ -145,8 +153,11 @@
     }
   }
 
+  Orthanc::ImageAccessor accessor;
+  accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]);
+
   std::string s;
-  w.WriteToMemory(s, width, height, pitch, Orthanc::PixelFormat_Grayscale16, &image[0]);
+  w.WriteToMemory(s, accessor);
 
   {
     Orthanc::PngReader r;