changeset 31155:a30b144bc10b

Tiff write: added support for writing tiled images * __tiff__.cc(write_tiled_image): implemented the logic to write tiled images for all cases except logical images.
author magedrifaat <magedrifaat@gmail.com>
date Thu, 04 Aug 2022 03:12:42 +0200
parents 828b7cc9aa36
children 1e633a093faa
files libinterp/dldfcn/__tiff__.cc
diffstat 1 files changed, 79 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__tiff__.cc	Thu Aug 04 00:02:27 2022 +0200
+++ b/libinterp/dldfcn/__tiff__.cc	Thu Aug 04 03:12:42 2022 +0200
@@ -1316,6 +1316,85 @@
   {
     // TODO(maged): remove this? ASSUMES pixel data dimensions are already validated
 
+    typedef typename T::element_type P;
+
+    uint32_t tile_width, tile_height;
+    if (! TIFFGetField (tif, TIFFTAG_TILEWIDTH, &tile_width))
+      error ("Failed to get the tile width");
+    if (! TIFFGetField (tif, TIFFTAG_TILELENGTH, &tile_height))
+      error ("Failed to get the tile length");
+
+    if (tile_height == 0 || tile_height % 16 != 0
+        || tile_width == 0 || tile_width % 16 != 0)
+      error ("Tile dimesion tags are invalid");
+    
+    uint32_t tiles_across = (image_data->width + tile_width - 1)
+                            / tile_width;
+    uint32_t tiles_down = (image_data->height + tile_height - 1)
+                          / tile_height;
+    
+    // Resize the image data to add tile padding
+    dim_vector padded_dims (tiles_down * tile_height,
+                            tiles_across * tile_width,
+                            image_data->samples_per_pixel);
+    pixel_data.resize (padded_dims);
+
+    // Reshape the image to separate tiles into their own dimension
+    // so we can permute them to the right order
+    dim_vector tiled_dims (tile_height, tiles_down, tile_width, tiles_across,
+                           image_data->samples_per_pixel);
+    pixel_data = pixel_data.reshape (tiled_dims);
+
+    // Permute the dimesnions to get the memory alignment to match LibTIFF
+    Array<octave_idx_type> perm (dim_vector (5, 1));
+    if (image_data->planar_configuration == PLANARCONFIG_SEPARATE)
+      {
+        // For separate planes, the data coming from libtiff will have all
+        // tiles of the first sample then all tiles of the second sample
+        // and so on. Tiles of each sample will be ordered from left to right
+        // and from top to bottom. And data inside each tile is organised as
+        // rows and each row contains columns.
+        // So the order for LibTIFF is:
+        //   samples x tiles_down x tiles_across x tile_height x tile_width
+        // But memory orientation of Octave arrays is reversed so we set it to
+        //   tile_width x tile_height x tiles_across x tiles_down x samples
+        perm(0) = 2;
+        perm(1) = 0;
+        perm(2) = 3;
+        perm(3) = 1;
+        perm(4) = 4;
+      }
+    else
+      {
+        // For chunky planes, the data coming from libtiff will be ordered
+        // from left to right and from top to bottom. And data inside each
+        // tile is organised as rows and each row contains columns and each
+        // column contains samples.
+        // So the order for LibTIFF is:
+        //   tiles_down x tiles_across x tile_height x tile_width x samples
+        // But memory orientation of Octave arrays is reversed so we set it to
+        //   samples x tile_width x tile_height x tiles_across x tiles_down
+        perm(0) = 4;
+        perm(1) = 2;
+        perm(2) = 0;
+        perm(3) = 3;
+        perm(4) = 1;
+      }
+    pixel_data = pixel_data.permute (perm);
+
+    uint8_t *pixel_fvec
+      = reinterpret_cast<uint8_t *> (pixel_data.fortran_vec ());
+    uint32_t tile_count = TIFFNumberOfTiles (tif);
+    uint64_t tile_size = tile_width * tile_height * sizeof (P);
+    if (image_data->planar_configuration == PLANARCONFIG_CONTIG)
+      tile_size *= image_data->samples_per_pixel;
+    for (uint32_t tile = 0; tile <tile_count; tile++)
+      {
+        if (! TIFFWriteEncodedTile (tif, tile, pixel_fvec, tile_size))
+          error ("Failed to write tile data");
+        pixel_fvec += tile_size;
+      }
+
   }
 
   template <typename T>