changeset 31115:5b3465a9c340

Tiff read: support for reading image arranged in planes (RRRGGGBBB) * __tiff__.cc (read_stripped_image): Added support for reading stripped images with PlanarConfiguration=Separate (RRRGGGBBB) as opposed to (RGBRGBRGB).
author magedrifaat <magedrifaat@gmail.com>
date Sat, 16 Jul 2022 19:05:09 +0200
parents 9dead1249449
children 9b3685afb4e7
files libinterp/dldfcn/__tiff__.cc
diffstat 1 files changed, 70 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__tiff__.cc	Sat Jul 16 17:29:14 2022 +0200
+++ b/libinterp/dldfcn/__tiff__.cc	Sat Jul 16 19:05:09 2022 +0200
@@ -16,7 +16,7 @@
 #  include <tiffio.h>
 #endif
 
-// TODO(maged): Tidy up the formatting to be consistant with octave
+// TODO(maged): Fix warnings
 
 namespace octve
 {
@@ -51,77 +51,93 @@
 
     uint32_t row_index = 0;
     uint32_t row_size_in_bits = image_data->width
-                                * image_data->samples_per_pixel
                                 * image_data->bits_per_sample;
+    if (image_data->planar_configuration == PLANARCONFIG_CONTIG)
+      row_size_in_bits *= image_data->samples_per_pixel;
     // According to the Tiff format specification, the row size is
     // padded at least up to the next byte, so we add padding to
     // complete the byte
     row_size_in_bits += (8 - row_size_in_bits % 8) % 8;
     for (uint32_t strip = 0; strip < strip_count; strip++)
       {
+        // Can't rely on StripByteCounts because in compressed images
+        // the byte count reflect the actual number of bytes stored
+        // in the file not the size of the uncompressed strip
         uint32_t strip_bytes = TIFFReadEncodedStrip (tif, strip, buf, -1);
         if (strip_bytes == -1)
           error ("Failed to read strip data");
         
-        if (image_data->planar_configuration == PLANARCONFIG_CONTIG)
+        uint32_t rows_in_strip = strip_bytes * 8 / row_size_in_bits;
+        uint32_t plane_size = image_data->width * image_data->height;
+        for (uint32_t row_subindex = 0;
+              row_subindex < rows_in_strip;
+              row_subindex++)
           {
-            uint32_t rows_in_strip = strip_bytes * 8 / row_size_in_bits;
-            for (uint32_t row_subindex = 0;
-                  row_subindex < rows_in_strip;
-                  row_subindex++)
+            for (uint32_t column = 0;
+                  column < image_data->width;
+                  column++)
               {
-                for (uint32_t column = 0;
-                      column < image_data->width;
-                      column++)
+                uint32_t row_offset = row_size_in_bits / 8
+                                      * row_subindex;
+                // TODO(maged): support arbitrary BitsPerSample?
+                if (image_data->bits_per_sample >= 8
+                    && image_data->bits_per_sample % 8 == 0)
                   {
-                    uint32_t row_offset = row_size_in_bits / 8
-                                          * row_subindex;
-                    // TODO(maged): support arbitrary BitsPerSample?
-                    if (image_data->bits_per_sample >= 8
-                        && image_data->bits_per_sample % 8 == 0)
+                    // TODO(maged): clean up the math for both cases
+                    if (image_data->planar_configuration == PLANARCONFIG_CONTIG)
+                      for (uint16_t sample = 0;
+                            sample < image_data->samples_per_pixel; sample++)
+                        // The memory organization of fvec is inverted from
+                        // what would be expected for a normal C-like array.
+                        // It is treated as samples * columns * rows as
+                        // opposed to rows * columns * samples.
+                        img_fvec[sample * plane_size
+                                + column * image_data->height
+                                + row_index + row_subindex]
+                          = ((P *)buf)[row_subindex * image_data->width
+                                      * image_data->samples_per_pixel
+                                      + column * image_data->samples_per_pixel
+                                      + sample];
+                    else
                       {
-                        // TODO(maged): copy entire strip at once?
-                        for (uint16_t sample = 0;
-                             sample < image_data->samples_per_pixel; sample++)
-                          // The memory organization of fvec is inverted from
-                          // what would be expected for a normal C-like array.
-                          // It is treated as samples * columns * rows as
-                          // opposed to rows * columns * samples.
-                          img_fvec[sample * image_data->width * image_data->height
-                                   + column * image_data->height
-                                   + row_index + row_subindex]
-                            = ((P *)buf)[row_subindex * image_data->width * image_data->samples_per_pixel
-                                         + column * image_data->samples_per_pixel + sample];
+                        uint16_t channel_no = strip
+                                              * image_data->samples_per_pixel
+                                              / strip_count;
+                        uint16_t corrected_row = (row_index + row_subindex)
+                                                 % image_data->height;
+                        img_fvec[channel_no * plane_size
+                                 + column * image_data->height
+                                 + corrected_row]
+                          = ((P *)buf)[row_subindex * image_data->width
+                                       + column];
                       }
-                    else if (image_data->bits_per_sample == 4
-                              && image_data->samples_per_pixel == 1)
-                      {
-                        // TODO(maged): Check FillOrder for completeness
-                        uint8_t nibble
-                          = ((uint8_t *)buf)[row_offset + column / 2];
-                        // Extract the needed nibble from the byte
-                        nibble = (column % 2 == 0? nibble >> 4: nibble) & 0x0F;
-                        img_fvec[(row_index + row_subindex)
-                                 + column * image_data->height] = nibble;
-                      }
-                    else if (image_data->bits_per_sample == 1
-                              && image_data->samples_per_pixel == 1)
-                      {
-                        uint8_t byte
-                          = ((uint8_t *)buf)[row_offset + column / 8];
-                        // Extract the needed bit from the byte
-                        uint8_t bit = (byte >> (7 - column % 8)) & 0x01;
-                        img_fvec[(row_index + row_subindex)
-                                 + column * image_data->height] = bit;
-                      }
-                    else
-                      error ("Unsupported bit depth");
+                  }
+                else if (image_data->bits_per_sample == 4
+                          && image_data->samples_per_pixel == 1)
+                  {
+                    // TODO(maged): Check FillOrder for completeness
+                    uint8_t nibble
+                      = ((uint8_t *)buf)[row_offset + column / 2];
+                    // Extract the needed nibble from the byte
+                    nibble = (column % 2 == 0? nibble >> 4: nibble) & 0x0F;
+                    img_fvec[(row_index + row_subindex)
+                              + column * image_data->height] = nibble;
                   }
+                else if (image_data->bits_per_sample == 1
+                          && image_data->samples_per_pixel == 1)
+                  {
+                    uint8_t byte
+                      = ((uint8_t *)buf)[row_offset + column / 8];
+                    // Extract the needed bit from the byte
+                    uint8_t bit = (byte >> (7 - column % 8)) & 0x01;
+                    img_fvec[(row_index + row_subindex)
+                              + column * image_data->height] = bit;
+                  }
+                else
+                  error ("Unsupported bit depth");
               }
-            row_index += rows_in_strip;
           }
-        else
-          error ("Images with multiple planes are not implemented yet");
+        row_index += rows_in_strip;
       }
     _TIFFfree (buf);
 
@@ -550,6 +566,7 @@
       case TIFFTAG_DOTRANGE:
       case TIFFTAG_YCBCRSUBSAMPLING:
         {
+          // TODO(maged): fix bug where only first one is returned
           uint16_t tag_part1, tag_part2;
           validate_tiff_get_field (TIFFGetField (tif, tag_id,
                                                  &tag_part1, &tag_part2));