changeset 31131:7349994f30f8

Tiff: fixed the first test to use a single-pixel image * Tiff.m: modified the test to use an image with one pixel instead of an empty image. * __tiff__.cc: fixed bugs in PlanarConfiguration tag and in type checking for writeEncodedStrip.
author magedrifaat <magedrifaat@gmail.com>
date Mon, 25 Jul 2022 04:15:18 +0200
parents 8475bdb70457
children c66f7c227e50
files libinterp/dldfcn/__tiff__.cc scripts/io/Tiff.m
diffstat 2 files changed, 42 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__tiff__.cc	Sun Jul 24 22:24:10 2022 +0200
+++ b/libinterp/dldfcn/__tiff__.cc	Mon Jul 25 04:15:18 2022 +0200
@@ -46,9 +46,11 @@
                                    &bits_per_sample))
         error ("Failed to read the BitsPerSample tag");
       
-      if (! TIFFGetFieldDefaulted (tif, TIFFTAG_PLANARCONFIG,
-                                   &planar_configuration))
-        error ("Failed to read the PlanarConfiguration tag");
+      if (! TIFFGetField (tif, TIFFTAG_PLANARCONFIG,
+                          &planar_configuration))
+        // LibTIFF has a bug where it incorrectly returns 0 as a default
+        // value for PlanarConfiguration although the default value is 1
+        planar_configuration = 1;
       
       is_tiled = TIFFIsTiled(tif);
     }
@@ -651,7 +653,16 @@
     int type_size = TIFFDataWidth (TIFFFieldDataType (fip));
     
     void *data = _TIFFmalloc (type_size);
-    validate_tiff_get_field (TIFFGetFieldDefaulted (tif, tag_id, data), data);
+    if (tag_id == TIFFTAG_PLANARCONFIG)
+      {
+        // Workaround for a bug in LibTIFF where it incorrectly returns
+        // zero as the default value for PlanaConfiguration
+        if (! TIFFGetField(tif, tag_id, data))
+          *reinterpret_cast<uint16_t *> (data) = 1;
+      }
+    else
+      validate_tiff_get_field (TIFFGetFieldDefaulted (tif, tag_id, data), data);
+    
     octave_value tag_data_ov = interpret_tag_data (data, 1,
                                                    TIFFFieldDataType (fip));
     _TIFFfree (data);
@@ -1216,14 +1227,17 @@
     switch (image_data.bits_per_sample)
       {
       case 1:
-        if (type_name == "bool matrix")
+        // Substrings are taken to support both the type and its matrix type
+        // i.e. "bool" and "bool matrix" to handle single element matrices
+        if (type_name.substr (0, 4) == "bool")
           write_strip<boolNDArray> (tif, strip_no, args(2), &image_data);
         else
           error ("Expected logical matrix for BiLevel image");
         break;
       case 4:
       case 8:
-        if (type_name == "uint8 matrix" || type_name == "int8 matrix")
+        if (type_name.substr (0, 5) == "uint8"
+            || type_name.substr (0, 4) == "int8")
           write_strip<uint8NDArray> (tif, strip_no, args(2), &image_data);
         else
           error ("Only uint8 and int8 data are allowed for images with bit depth of 8");
@@ -1232,31 +1246,36 @@
         // Type conversion from signed to unsigned is handled in the function
         // TODO(maged): what is the behavior if the input matrix has
         // negative numbers?
-        if (type_name == "uint16 matrix" || type_name == "int16 matrix")
+        if (type_name.substr (0, 6) == "uint16"
+            || type_name.substr (0, 5) == "int16")
           write_strip<uint16NDArray> (tif, strip_no, args(2), &image_data);
         else
           error ("Only uint16 and int16 data are allowed for images with bit depth of 16");
         break;
       case 32:
-        if (sample_format == 3)  
-          if (type_name == "float matrix" || type_name == "matrix")
+        if (sample_format == 3)
+          if (type_name.substr (0, 5) == "float" || type_name == "double"
+              || type_name == "matrix")
             write_strip<FloatNDArray> (tif, strip_no, args(2), &image_data);
           else
             error ("Only single and double data are allowed for floating-point images");
         else
-          if (type_name == "uint32 matrix" || type_name == "int32 matrix")
+          if (type_name.substr (0, 6) == "uint32"
+              || type_name.substr (0, 5) == "int32")
             write_strip<uint32NDArray> (tif, strip_no, args(2), &image_data);
           else
             error ("Only uint32 and int32 data are allowed for images with bit depth of 32");
         break;
       case 64:
-        if (sample_format == 3)          
-          if (type_name == "float matrix" || type_name == "matrix")
+        if (sample_format == 3)
+          if (type_name.substr (0, 5) == "float" || type_name == "double"
+              || type_name == "matrix")
             write_strip<NDArray> (tif, strip_no, args(2), &image_data);
           else
             error ("Only single and double data are allowed for floating-point images");
         else  
-          if (type_name == "uint64 matrix" || type_name == "int64 matrix")
+          if (type_name.substr (0, 6) == "uint64"
+              || type_name.substr (0, 5) == "int64")
             write_strip<uint64NDArray> (tif, strip_no, args(2), &image_data);
           else
             error ("Only uint64 and int64 data are allowed for images with bit depth of 64");
--- a/scripts/io/Tiff.m	Sun Jul 24 22:24:10 2022 +0200
+++ b/scripts/io/Tiff.m	Mon Jul 25 04:15:18 2022 +0200
@@ -1,6 +1,5 @@
 classdef Tiff
     properties (Constant = true)
-        % TODO(maged): Add the remaining fields
         TagID = struct(
             "SubFileType", 254,
             "ImageWidth", 256,
@@ -112,13 +111,21 @@
     endmethods
 endclassdef
 
-## test empty image
+## test one-pixel image
 %!testif HAVE_TIFF
 %! filename = [tempname() ".tif"];
 %! unwind_protect
 %!   a = Tiff (filename, "w");
+%!   setTag(a, "ImageWidth", 1);
+%!   setTag(a, "ImageLength", 1);
+%!   setTag(a, "BitsPerSample", 8);
+%!   data = uint8([255]);
+%!   writeEncodedStrip(a, 1, data);
 %!   a.close ();
-%!   a = Tiff (filename, "rh");
+%!   a = Tiff (filename, "r");
+%!   data2 = a.read();
+%!   assert (all (size(data) == [1, 1]));
+%!   assert (data(1) == 255);
 %!   a.close ();
 %! unwind_protect_cleanup
 %!   unlink (filename);