diff libinterp/dldfcn/__magick_read__.cc @ 18610:30aa4e85f8d5 stable

Fix writing and reading of multipage images. * __magick_read__.cc (encode_uint_image): reset the coordinates for each Magick::Image object so that writing of multipage images (matrices with non-singleton 4th dimension) work properly. Stride over the extra channels at the end of each page, to fix writing of multipage RGB and CMYK images. (read_images): correct stride over each frame for RGB and CMYK images. * imwrite.m: add tests to write and read multipage grayscale and RGB images. Reduce size of test images to speed up comparison.
author Carnë Draug <carandraug@octave.org>
date Tue, 04 Mar 2014 16:52:00 +0000
parents bc1809fe55e4
children e0cc67d5a462
line wrap: on
line diff
--- a/libinterp/dldfcn/__magick_read__.cc
+++ b/libinterp/dldfcn/__magick_read__.cc
@@ -416,6 +416,7 @@
         }
     }
 
+  const octave_idx_type colour_stride = nRows * nCols;
   switch (type)
     {
     case Magick::BilevelType:           // Monochrome bi-level image
@@ -480,6 +481,7 @@
         img = T (dim_vector (nRows, nCols, 3, nFrames));
         P *img_fvec = img.fortran_vec ();
 
+        const octave_idx_type frame_stride  = colour_stride * 3;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             const Magick::PixelPacket *pix
@@ -487,10 +489,9 @@
                                                        col_cache, row_cache);
 
             octave_idx_type idx = 0;
-            img_fvec += nRows * nCols * frame;
             P *rbuf   = img_fvec;
-            P *gbuf   = img_fvec + nRows * nCols;
-            P *bbuf   = img_fvec + nRows * nCols * 2;
+            P *gbuf   = img_fvec + colour_stride;
+            P *bbuf   = img_fvec + colour_stride * 2;
 
             for (octave_idx_type col = 0; col < nCols; col++)
               {
@@ -504,6 +505,7 @@
                   }
                 pix -= col_shift;
               }
+            img_fvec += frame_stride;
           }
         break;
       }
@@ -516,6 +518,8 @@
         P *img_fvec = img.fortran_vec ();
         P *a_fvec   = alpha.fortran_vec ();
 
+        const octave_idx_type frame_stride  = colour_stride * 3;
+
         // Unlike the index for the other channels, this one won't need
         // to be reset on each frame since it's a separate matrix.
         octave_idx_type a_idx = 0;
@@ -526,10 +530,9 @@
                                                        col_cache, row_cache);
 
             octave_idx_type idx = 0;
-            img_fvec += nRows * nCols * frame;
             P *rbuf   = img_fvec;
-            P *gbuf   = img_fvec + nRows * nCols;
-            P *bbuf   = img_fvec + nRows * nCols * 2;
+            P *gbuf   = img_fvec + colour_stride;
+            P *bbuf   = img_fvec + colour_stride * 2;
 
             for (octave_idx_type col = 0; col < nCols; col++)
               {
@@ -544,6 +547,7 @@
                   }
                 pix -= col_shift;
               }
+            img_fvec += frame_stride;
           }
         retval(2) = alpha;
         break;
@@ -554,6 +558,7 @@
         img   = T (dim_vector (nRows, nCols, 4, nFrames));
         P *img_fvec = img.fortran_vec ();
 
+        const octave_idx_type frame_stride  = colour_stride * 4;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             const Magick::PixelPacket *pix
@@ -561,11 +566,10 @@
                                                        col_cache, row_cache);
 
             octave_idx_type idx = 0;
-            img_fvec += nRows * nCols * frame;
             P *cbuf   = img_fvec;
-            P *mbuf   = img_fvec + nRows * nCols;
-            P *ybuf   = img_fvec + nRows * nCols * 2;
-            P *kbuf   = img_fvec + nRows * nCols * 3;
+            P *mbuf   = img_fvec + colour_stride;
+            P *ybuf   = img_fvec + colour_stride * 2;
+            P *kbuf   = img_fvec + colour_stride * 3;
 
             for (octave_idx_type col = 0; col < nCols; col++)
               {
@@ -580,6 +584,7 @@
                   }
                 pix -= col_shift;
               }
+            img_fvec += frame_stride;
           }
         break;
       }
@@ -592,6 +597,8 @@
         P *img_fvec = img.fortran_vec ();
         P *a_fvec   = alpha.fortran_vec ();
 
+        const octave_idx_type frame_stride  = colour_stride * 4;
+
         // Unlike the index for the other channels, this one won't need
         // to be reset on each frame since it's a separate matrix.
         octave_idx_type a_idx = 0;
@@ -606,11 +613,10 @@
               = imvec[frameidx(frame)].getConstIndexes ();
 
             octave_idx_type idx = 0;
-            img_fvec += nRows * nCols * frame;
             P *cbuf   = img_fvec;
-            P *mbuf   = img_fvec + nRows * nCols;
-            P *ybuf   = img_fvec + nRows * nCols * 2;
-            P *kbuf   = img_fvec + nRows * nCols * 3;
+            P *mbuf   = img_fvec + colour_stride;
+            P *ybuf   = img_fvec + colour_stride * 2;
+            P *kbuf   = img_fvec + colour_stride * 3;
 
             for (octave_idx_type col = 0; col < nCols; col++)
               {
@@ -626,6 +632,7 @@
                   }
                 pix -= col_shift;
               }
+            img_fvec += frame_stride;
           }
         retval(2) = alpha;
         break;
@@ -1062,7 +1069,6 @@
     {
     case Magick::GrayscaleType:
       {
-        octave_idx_type GM_idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
@@ -1070,6 +1076,7 @@
                                                       Magick::DirectClass);
 
             Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
+            octave_idx_type GM_idx = 0;
             for (octave_idx_type col = 0; col < nCols; col++)
               {
                 for (octave_idx_type row = 0; row < nRows; row++)
@@ -1091,7 +1098,6 @@
 
     case Magick::GrayscaleMatteType:
       {
-        octave_idx_type GM_idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
@@ -1099,6 +1105,7 @@
                                                       Magick::DirectClass);
 
             Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
+            octave_idx_type GM_idx = 0;
             for (octave_idx_type col = 0; col < nCols; col++)
               {
                 for (octave_idx_type row = 0; row < nRows; row++)
@@ -1125,7 +1132,6 @@
         // The fortran_vec offset for the green and blue channels
         const octave_idx_type G_offset = nCols * nRows;
         const octave_idx_type B_offset = nCols * nRows * 2;
-        octave_idx_type GM_idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
@@ -1133,6 +1139,7 @@
                                                       Magick::DirectClass);
 
             Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
+            octave_idx_type GM_idx = 0;
             for (octave_idx_type col = 0; col < nCols; col++)
               {
                 for (octave_idx_type row = 0; row < nRows; row++)
@@ -1149,6 +1156,7 @@
             // Save changes to underlying image.
             m_img.syncPixels ();
             imvec.push_back (m_img);
+            img_fvec += B_offset;
           }
         break;
       }
@@ -1158,7 +1166,6 @@
         // The fortran_vec offset for the green and blue channels
         const octave_idx_type G_offset = nCols * nRows;
         const octave_idx_type B_offset = nCols * nRows * 2;
-        octave_idx_type GM_idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
@@ -1166,6 +1173,7 @@
                                                       Magick::DirectClass);
 
             Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
+            octave_idx_type GM_idx = 0;
             for (octave_idx_type col = 0; col < nCols; col++)
               {
                 for (octave_idx_type row = 0; row < nRows; row++)
@@ -1184,6 +1192,7 @@
             // Save changes to underlying image.
             m_img.syncPixels ();
             imvec.push_back (m_img);
+            img_fvec += B_offset;
           }
         break;
       }
@@ -1194,7 +1203,6 @@
         const octave_idx_type M_offset = nCols * nRows;
         const octave_idx_type Y_offset = nCols * nRows * 2;
         const octave_idx_type K_offset = nCols * nRows * 3;
-        octave_idx_type GM_idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
@@ -1202,6 +1210,7 @@
                                                       Magick::DirectClass);
 
             Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
+            octave_idx_type GM_idx = 0;
             for (octave_idx_type col = 0; col < nCols; col++)
               {
                 for (octave_idx_type row = 0; row < nRows; row++)
@@ -1219,6 +1228,7 @@
             // Save changes to underlying image.
             m_img.syncPixels ();
             imvec.push_back (m_img);
+            img_fvec += K_offset;
           }
         break;
       }
@@ -1229,7 +1239,6 @@
         const octave_idx_type M_offset = nCols * nRows;
         const octave_idx_type Y_offset = nCols * nRows * 2;
         const octave_idx_type K_offset = nCols * nRows * 3;
-        octave_idx_type GM_idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
           {
             Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
@@ -1238,6 +1247,7 @@
 
             Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
             Magick::IndexPacket *ind = m_img.getIndexes ();
+            octave_idx_type GM_idx = 0;
             for (octave_idx_type col = 0; col < nCols; col++)
               {
                 for (octave_idx_type row = 0; row < nRows; row++)
@@ -1257,6 +1267,7 @@
             // Save changes to underlying image.
             m_img.syncPixels ();
             imvec.push_back (m_img);
+            img_fvec += K_offset;
           }
         break;
       }