changeset 31165:48d46f7a640b

Tiff setTag: handled scalar tags with the correct data type.
author magedrifaat <magedrifaat@gmail.com>
date Fri, 12 Aug 2022 00:04:37 +0200
parents 3155aa74c62e
children b8b6cc05c8ea
files libinterp/corefcn/__tiff__.cc
diffstat 1 files changed, 185 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/__tiff__.cc	Wed Aug 10 23:55:33 2022 +0200
+++ b/libinterp/corefcn/__tiff__.cc	Fri Aug 12 00:04:37 2022 +0200
@@ -854,6 +854,8 @@
             }
           case TIFF_RATIONAL:
             {
+              // TODO(maged): This is incorrect, LibTIFF already handles
+              // rationals and converts them to floats
               NDArray arr (arr_dims);
               for (uint32_t i = 0; i < count; i+=2)
                 {
@@ -1178,10 +1180,193 @@
   }
 
   void
+  set_scalar_field_data (TIFF *tif, const TIFFField *fip, octave_value tag_ov)
+  {
+    uint32_t tag_id = TIFFFieldTag (fip);
+    
+    // Since scalar tags are the last to be handled, any tag that
+    // require a count to be passed is an unsupported tag.
+    if (TIFFFieldPassCount (fip))
+      error ("Unsupported tag");
+    
+    TIFFDataType tag_datatype = TIFFFieldDataType (fip);
+    switch (tag_datatype)
+      {
+      case TIFF_BYTE:
+      case TIFF_UNDEFINED:
+        // TODO(maged): check if matlab errors for long data type/range
+        TIFFSetField (tif, tag_id, tag_ov.uint8_scalar_value ());
+        break;
+      case TIFF_SHORT:
+        TIFFSetField (tif, tag_id, tag_ov.uint16_scalar_value ());
+        break;
+      case TIFF_LONG:
+        TIFFSetField (tif, tag_id, tag_ov.uint32_scalar_value ());
+        break;
+      case TIFF_LONG8:
+        TIFFSetField (tif, tag_id, tag_ov.uint64_scalar_value ());
+        break;
+      case TIFF_RATIONAL:
+        TIFFSetField (tif, tag_id, tag_ov.float_scalar_value ());
+        break;
+      case TIFF_SBYTE:
+        TIFFSetField (tif, tag_id, tag_ov.int8_scalar_value ());
+        break;
+      case TIFF_SSHORT:
+        TIFFSetField (tif, tag_id, tag_ov.int16_scalar_value ());
+        break;
+      case TIFF_SLONG:
+        TIFFSetField (tif, tag_id, tag_ov.int32_scalar_value ());
+        break;
+      case TIFF_SLONG8:
+        TIFFSetField (tif, tag_id, tag_ov.int64_scalar_value ());
+        break;
+      case TIFF_FLOAT:
+        TIFFSetField (tif, tag_id, tag_ov.float_scalar_value ());
+        break;
+      case TIFF_DOUBLE:
+        TIFFSetField (tif, tag_id, tag_ov.double_value ());
+        break;
+      case TIFF_SRATIONAL:
+        TIFFSetField (tif, tag_id, tag_ov.float_scalar_value ());
+        break;
+      case TIFF_IFD:
+      case TIFF_IFD8:
+        error ("Unimplemented IFFD data type");
+        break;
+      default:
+        error ("Unsupported tag data type");
+      }
+  }
+
+  void
+  set_array_field_data (TIFF *tif, const TIFFField *fip,
+                        octave_value tag_ov, uint32_t count)
+  {
+  }
+
+  void
   set_field_data (TIFF *tif, const TIFFField *fip, octave_value tag_ov)
   { 
     // TODO(maged): complete the implementation of this function
     uint32_t tag_id = TIFFFieldTag (fip);
+
+    // TODO(maged): find/create images to test the special tags
+    switch (tag_id)
+      {
+      case TIFFTAG_STRIPBYTECOUNTS:
+      case TIFFTAG_STRIPOFFSETS:
+        set_array_field_data (tif, fip, tag_ov, TIFFNumberOfStrips (tif));
+        break;
+      case TIFFTAG_TILEBYTECOUNTS:
+      case TIFFTAG_TILEOFFSETS:
+        set_array_field_data (tif, fip, tag_ov, TIFFNumberOfTiles (tif));
+        break;
+      case TIFFTAG_YCBCRCOEFFICIENTS:
+        set_array_field_data (tif, fip, tag_ov, 3);
+        break;
+      case TIFFTAG_REFERENCEBLACKWHITE:
+        set_array_field_data (tif, fip, tag_ov, 6);
+        break;
+      case TIFFTAG_GRAYRESPONSECURVE:
+        {
+          uint16_t bits_per_sample;
+          if (! TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE,
+                                            &bits_per_sample))
+            error ("Failed to obtain the bit depth");
+          
+          set_array_field_data (tif, fip, tag_ov, 1<<bits_per_sample);
+          break;
+        }
+      case TIFFTAG_COLORMAP:
+        {
+          uint16_t bits_per_sample;
+          if (! TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE,
+                                       &bits_per_sample))
+            error ("Failed to obtain the bit depth");
+          
+          // According to the format specification, this field should
+          // be 8 or 16 only.
+          if (bits_per_sample > 16)
+            error ("Too high bit depth for a palette image");
+
+          uint32_t count = 1 << bits_per_sample;
+          // uint16_t *red, *green, *blue;
+          // validate_tiff_get_field (TIFFGetField (tif, TIFFTAG_COLORMAP,
+          //                                        &red, &green, &blue));
+          break;
+        }
+      case TIFFTAG_TRANSFERFUNCTION:
+        {
+          uint16_t samples_per_pixel;
+          if (! TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL,
+                                       &samples_per_pixel))
+            error ("Failed to obtain the number of samples per pixel");
+
+          uint16_t bits_per_sample;
+          if (! TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE,
+                                       &bits_per_sample))
+            error ("Failed to obtain the number of samples per pixel");
+
+          uint32_t count = 1 << bits_per_sample;
+          uint16_t *ch1, *ch2, *ch3;
+          if (samples_per_pixel == 1)
+            {
+              // validate_tiff_get_field (TIFFGetField (tif, TIFFTAG_COLORMAP, &ch1));
+            }
+          else
+            {
+              // validate_tiff_get_field (TIFFGetField (tif, TIFFTAG_COLORMAP,
+              //                                        &ch1, &ch2, &ch3));
+            }
+          break;
+        }
+      case TIFFTAG_PAGENUMBER:
+      case TIFFTAG_HALFTONEHINTS:
+      case TIFFTAG_DOTRANGE:
+      case TIFFTAG_YCBCRSUBSAMPLING:
+        {
+          uint16_t tag_part1, tag_part2;
+          // validate_tiff_get_field (TIFFGetField (tif, tag_id,
+          //                                        &tag_part1, &tag_part2));
+          break;
+        }
+      case TIFFTAG_SUBIFD:
+        {
+          uint16_t count;
+          uint64_t *offsets;
+          // validate_tiff_get_field (TIFFGetField (tif, tag_id, &count, &offsets));
+          break;
+        }
+      case TIFFTAG_EXTRASAMPLES:
+        {
+          uint16_t count;
+          uint16_t *types;
+          // validate_tiff_get_field (TIFFGetField (tif, tag_id, &count, &types));
+          break;
+        }
+      // TODO(maged): These tags are more complex to implement
+      //  will be implemented and tested later.
+      case TIFFTAG_XMLPACKET:
+      case TIFFTAG_RICHTIFFIPTC:
+      case TIFFTAG_PHOTOSHOP:
+      case TIFFTAG_ICCPROFILE:
+        {
+          error ("Complex Tags not implemented");
+          break;
+        }
+      // These tags are not mentioned in the LibTIFF documentation
+      // but are handled correctly by the library
+      case TIFFTAG_ZIPQUALITY:
+      case TIFFTAG_SGILOGDATAFMT:
+      case TIFFTAG_GRAYRESPONSEUNIT:
+        {
+          set_scalar_field_data (tif, fip, tag_ov);
+          break;
+        }
+      default:
+        set_scalar_field_data (tif, fip, tag_ov);
+    }
     uint32_t tag_data = tag_ov.double_value ();
 
     if (! TIFFSetField(tif, tag_id, tag_data))