changeset 797:37adac56017a

ImageAccessor abstraction
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 06 May 2014 12:47:26 +0200
parents e7b1ca0f1e04
children e1d27ee2114a
files Core/Enumerations.h Core/FileFormats/PngReader.cpp Core/FileFormats/PngReader.h Core/OrthancException.cpp OrthancCppClient/Instance.cpp UnitTestsSources/Png.cpp
diffstat 6 files changed, 164 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/Core/Enumerations.h	Tue May 06 12:09:11 2014 +0200
+++ b/Core/Enumerations.h	Tue May 06 12:47:26 2014 +0200
@@ -68,7 +68,8 @@
     ErrorCode_IncompatibleDatabaseVersion,
     ErrorCode_FullStorage,
     ErrorCode_CorruptedFile,
-    ErrorCode_InexistentTag
+    ErrorCode_InexistentTag,
+    ErrorCode_ReadOnly
   };
 
   /**
--- a/Core/FileFormats/PngReader.cpp	Tue May 06 12:09:11 2014 +0200
+++ b/Core/FileFormats/PngReader.cpp	Tue May 06 12:47:26 2014 +0200
@@ -131,10 +131,6 @@
 
   PngReader::PngReader()
   {
-    width_ = 0;
-    height_ = 0;
-    pitch_ = 0;
-    format_ = PixelFormat_Grayscale8;
   }
 
   void PngReader::Read(PngRabi& rabi)
@@ -152,18 +148,18 @@
                  &bit_depth, &color_type, &interlace_type,
                  &compression_type, &filter_method);
 
-    width_ = width;
-    height_ = height;
+    PixelFormat format;
+    unsigned int pitch;
 
     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 8)
     {
-      format_ = PixelFormat_Grayscale8;
-      pitch_ = width_;
+      format = PixelFormat_Grayscale8;
+      pitch = width;
     }
     else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)
     {
-      format_ = PixelFormat_Grayscale16;
-      pitch_ = 2 * width_;
+      format = PixelFormat_Grayscale16;
+      pitch = 2 * width;
 
       if (Toolbox::DetectEndianness() == Endianness_Little)
       {
@@ -172,31 +168,34 @@
     }
     else if (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 8)
     {
-      format_ = PixelFormat_Grayscale8;
-      pitch_ = 3 * width_;
+      format = PixelFormat_RGB24;
+      pitch = 3 * width;
     }
     else
     {
       throw OrthancException(ErrorCode_NotImplemented);
     }
 
-    buffer_.resize(height_ * pitch_);
+    data_.resize(height * pitch);
 
-    if (height_ == 0 || width_ == 0)
+    if (height == 0 || width == 0)
     {
       // Empty image, we are done
+      AssignEmpty(format);
       return;
     }
-
+    
     png_read_update_info(rabi.png_, rabi.info_);
 
-    std::vector<png_bytep> rows(height_);
-    for (size_t i = 0; i < height_; i++)
+    std::vector<png_bytep> rows(height);
+    for (size_t i = 0; i < height; i++)
     {
-      rows[i] = &buffer_[0] + i * pitch_;
+      rows[i] = &data_[0] + i * pitch;
     }
 
     png_read_image(rabi.png_, &rows[0]);
+
+    AssignReadOnly(format, width, height, pitch, &data_[0]);
   }
 
   void PngReader::ReadFromFile(const char* filename)
@@ -225,6 +224,89 @@
   }
 
 
+  void* ImageAccessor::GetBuffer()
+  {
+    if (readOnly_)
+    {
+      throw OrthancException(ErrorCode_ReadOnly);
+    }
+
+    return buffer_;
+  }
+
+
+  const void* ImageAccessor::GetConstRow(unsigned int y) const
+  {
+    if (buffer_ != NULL)
+    {
+      return reinterpret_cast<const uint8_t*>(buffer_) + y * pitch_;
+    }
+    else
+    {
+      return NULL;
+    }
+  }
+
+
+  void* ImageAccessor::GetRow(unsigned int y) 
+  {
+    if (readOnly_)
+    {
+      throw OrthancException(ErrorCode_ReadOnly);
+    }
+
+    if (buffer_ != NULL)
+    {
+      return reinterpret_cast<uint8_t*>(buffer_) + y * pitch_;
+    }
+    else
+    {
+      return NULL;
+    }
+  }
+
+
+  void ImageAccessor::AssignEmpty(PixelFormat format)
+  {
+    readOnly_ = false;
+    format_ = format;
+    width_ = 0;
+    height_ = 0;
+    pitch_ = 0;
+    buffer_ = NULL;
+  }
+
+
+  void ImageAccessor::AssignReadOnly(PixelFormat format,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int pitch,
+                                     const void *buffer)
+  {
+    readOnly_ = true;
+    format_ = format;
+    width_ = width;
+    height_ = height;
+    pitch_ = pitch;
+    buffer_ = const_cast<void*>(buffer);
+  }
+
+
+  void ImageAccessor::AssignWritable(PixelFormat format,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int pitch,
+                                     void *buffer)
+  {
+    readOnly_ = false;
+    format_ = format;
+    width_ = width;
+    height_ = height;
+    pitch_ = pitch;
+    buffer_ = buffer;
+  }
+
+
 
   namespace
   {
@@ -298,8 +380,12 @@
   void PngReader::ReadFromMemory(const std::string& buffer)
   {
     if (buffer.size() != 0)
+    {
       ReadFromMemory(&buffer[0], buffer.size());
+    }
     else
+    {
       ReadFromMemory(NULL, 0);
+    }
   }
 }
--- a/Core/FileFormats/PngReader.h	Tue May 06 12:09:11 2014 +0200
+++ b/Core/FileFormats/PngReader.h	Tue May 06 12:47:26 2014 +0200
@@ -40,23 +40,26 @@
 
 namespace Orthanc
 {
-  class PngReader
+  class ImageAccessor
   {
   private:
-    struct PngRabi;
-
+    bool readOnly_;
     PixelFormat format_;
     unsigned int width_;
     unsigned int height_;
     unsigned int pitch_;
-    std::vector<uint8_t> buffer_;
-
-    void CheckHeader(const void* header);
-
-    void Read(PngRabi& rabi);
+    void *buffer_;
 
   public:
-    PngReader();
+    ImageAccessor()
+    {
+      AssignEmpty(PixelFormat_Grayscale8);
+    }
+
+    bool IsReadOnly() const
+    {
+      return readOnly_;
+    }
 
     PixelFormat GetFormat() const
     {
@@ -78,21 +81,46 @@
       return pitch_;
     }
 
-    const void* GetBuffer() const
+    const void* GetConstBuffer() const
     {
-      if (buffer_.size() > 0)
-        return &buffer_[0];
-      else
-        return NULL;
+      return buffer_;
     }
 
-    const void* GetBuffer(unsigned int y) const
-    {
-      if (buffer_.size() > 0)
-        return &buffer_[y * pitch_];
-      else
-        return NULL;
-    }
+    void* GetBuffer();
+
+    const void* GetConstRow(unsigned int y) const;
+
+    void* GetRow(unsigned int y);
+
+    void AssignEmpty(PixelFormat format);
+
+    void AssignReadOnly(PixelFormat format,
+                        unsigned int width,
+                        unsigned int height,
+                        unsigned int pitch,
+                        const void *buffer);
+
+    void AssignWritable(PixelFormat format,
+                        unsigned int width,
+                        unsigned int height,
+                        unsigned int pitch,
+                        void *buffer);
+  };
+
+
+  class PngReader : public ImageAccessor
+  {
+  private:
+    struct PngRabi;
+
+    std::vector<uint8_t> data_;
+
+    void CheckHeader(const void* header);
+
+    void Read(PngRabi& rabi);
+
+  public:
+    PngReader();
 
     void ReadFromFile(const char* filename);
 
--- a/Core/OrthancException.cpp	Tue May 06 12:09:11 2014 +0200
+++ b/Core/OrthancException.cpp	Tue May 06 12:47:26 2014 +0200
@@ -111,6 +111,9 @@
       case ErrorCode_InexistentTag:
         return "Inexistent tag";
 
+      case ErrorCode_ReadOnly:
+        return "Cannot modify a read-only data structure";
+
       case ErrorCode_Custom:
       default:
         return "???";
--- a/OrthancCppClient/Instance.cpp	Tue May 06 12:09:11 2014 +0200
+++ b/OrthancCppClient/Instance.cpp	Tue May 06 12:47:26 2014 +0200
@@ -178,13 +178,13 @@
   const void* Instance::GetBuffer()
   {
     DownloadImage();
-    return reader_->GetBuffer();
+    return reader_->GetConstBuffer();
   }
 
   const void* Instance::GetBuffer(unsigned int y)
   {
     DownloadImage();
-    return reader_->GetBuffer(y);
+    return reader_->GetConstRow(y);
   }
 
   void Instance::DiscardImage()
--- a/UnitTestsSources/Png.cpp	Tue May 06 12:09:11 2014 +0200
+++ b/UnitTestsSources/Png.cpp	Tue May 06 12:47:26 2014 +0200
@@ -119,8 +119,8 @@
     v = 0;
     for (int y = 0; y < height; y++)
     {
-      uint16_t *p = reinterpret_cast<uint16_t*>((uint8_t*) r.GetBuffer() + y * r.GetPitch());
-      ASSERT_EQ(p, r.GetBuffer(y));
+      const uint16_t *p = reinterpret_cast<const uint16_t*>((const uint8_t*) r.GetConstBuffer() + y * r.GetPitch());
+      ASSERT_EQ(p, r.GetConstRow(y));
       for (int x = 0; x < width; x++, p++, v++)
       {
         ASSERT_EQ(*p, v);
@@ -142,8 +142,8 @@
     v = 0;
     for (int y = 0; y < height; y++)
     {
-      uint16_t *p = reinterpret_cast<uint16_t*>((uint8_t*) r2.GetBuffer() + y * r2.GetPitch());
-      ASSERT_EQ(p, r2.GetBuffer(y));
+      const uint16_t *p = reinterpret_cast<const uint16_t*>((const uint8_t*) r2.GetConstBuffer() + y * r2.GetPitch());
+      ASSERT_EQ(p, r2.GetConstRow(y));
       for (int x = 0; x < width; x++, p++, v++)
       {
         ASSERT_EQ(*p, v);