changeset 31094:ab5b33e447b0

Modified getTag to account for different tag data types and multivalued tags, the current implementation is still buggy for most tags and data types
author magedrifaat <magedrifaat@gmail.com>
date Wed, 22 Jun 2022 23:32:22 +0200
parents e2bed4daae82
children edfedae9972a
files libinterp/dldfcn/__tiff__.cc scripts/io/Tiff.m
diffstat 2 files changed, 163 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__tiff__.cc	Fri Jun 17 17:43:41 2022 +0200
+++ b/libinterp/dldfcn/__tiff__.cc	Wed Jun 22 23:32:22 2022 +0200
@@ -1,4 +1,5 @@
 #include <string>
+#include <iostream>
 
 #include "defun-dld.h"
 #include "ov.h"
@@ -10,6 +11,106 @@
 
 // TODO(maged): Tidy up the formatting to be consistant with octave
 
+octave_value interpret_data(void *data, uint32_t count, TIFFDataType tag_datatype)
+{
+    // TODO(maged): Find the correct way fo returning multivalues
+    octave_value_list ov_data;
+    switch (tag_datatype)
+    {
+        case TIFF_BYTE:
+        case TIFF_UNDEFINED:
+            for (uint32_t i = 0; i < count; i++)
+            {
+                ov_data(i) = octave_value(((uint8_t *)data)[i]);
+            }
+            break;
+
+        case TIFF_ASCII:
+            ov_data(0) = octave_value((char *)data);
+            break;
+
+        case TIFF_SHORT:
+            for (uint32_t i = 0; i < count; i++)
+            {
+                ov_data(i) = octave_value(((uint16_t *)data)[i]);
+            }
+            break;
+        
+        case TIFF_LONG:
+            for (uint32_t i = 0; i < count; i++)
+            {
+                ov_data(i) = octave_value(((uint32_t *)data)[i]);
+            }
+            break;
+
+        // case TIFF_RATIONAL:
+        //     uint32_t *u32data = (uint32_t *)data;
+        //     for (uint32_t i = 0; i < count; i+=2)
+        //     {
+        //         ov_data(i / 2) = octave_value((float)u32data[i] / (float)u32data[i+1]);
+        //     }
+        //     break;
+
+        // case TIFF_SBYTE:
+        //     int8_t *s8data = (int8_t *)data;
+        //     for (uint32_t i = 0; i < count; i++)
+        //     {
+        //         ov_data(i) = octave_value(s8data[i]);
+        //     }
+        //     break;
+        
+        // case TIFF_SSHORT:
+        //     int16_t *s16data = (int16_t *)data;
+        //     for (uint32_t i = 0; i < count; i++)
+        //     {
+        //         ov_data(i) = octave_value(s16data[i]);
+        //     }
+        //     break;
+
+        // case TIFF_SLONG:
+        //     int32_t *s32data = (int32_t *)data;
+        //     for (uint32_t i = 0; i < count; i++)
+        //     {
+        //         ov_data(i) = octave_value(s32data[i]);
+        //     }
+        //     break;
+
+        // case TIFF_FLOAT:
+        //     float *float_data = (float *)data;
+        //     for (uint32_t i = 0; i < count; i++)
+        //     {
+        //         ov_data(i) = octave_value(double_data[i]);
+        //     }
+        //     break;
+        
+        // case TIFF_DOUBLE:
+        //     double *double_data = (double *)data;
+        //     for (uint32_t i = 0; i < count; i++)
+        //     {
+        //         ov_data(i) = octave_value(double_data[i]);
+        //     }
+        //     break;
+
+        // case TIFF_SRATIONAL:
+        //     int32_t *s32data = (int32_t *)data;
+        //     for (uint32_t i = 0; i < count; i+=2)
+        //     {
+        //         ov_data(i / 2) = octave_value((float)s32data[i] / (float)s32data[i+1]);
+        //     }
+        //     break;
+
+        case TIFF_IFD:
+            // TODO(maged): implement IFD datatype
+            error("Unimplemented IFFD data type");
+            break;
+        default:
+            // TODO(maged): find the correct response in this case
+            error("Unsupported tag data type");
+    }
+
+    return octave_value(ov_data);
+}
+
 DEFUN_DLD (__open_tiff__, args, nargout,
            "Open a Tiff file and return its handle")
 {
@@ -28,6 +129,7 @@
     if (nargin == 2)
         mode = args(1).string_value();
     
+    // TODO(maged): Look into unwind action
     TIFF *tif = TIFFOpen(filename.c_str(), mode.c_str());
     // TODO(maged): print a better error
     if (!tif)
@@ -73,10 +175,11 @@
     TIFF *tif = (TIFF *)(args(0).uint64_value());
 
     uint32_t tag_ID;
+    const TIFFField *fip;
     if (args(1).type_name() == "string")
     {
         std::string tagName = args(1).string_value();
-        const TIFFField *fip = TIFFFieldWithName(tif, tagName.c_str());
+        fip = TIFFFieldWithName(tif, tagName.c_str());
         if (!fip)
             error("Tiff tag not found\n");
         
@@ -85,15 +188,67 @@
     else
     {
         tag_ID = args(1).int_value();
-        const TIFFField *fip = TIFFFieldWithTag(tif, tag_ID);
-        // TODO(maged): Handle other types of errors
+        fip = TIFFFieldWithTag(tif, tag_ID);
+        // TODO(maged): Handle other types of errors (e.g. unsupported tags)
         if (!fip)
             error("Tiff tag not found\n");
     }
 
-    // TODO(maged): Handle different data types/ multivalued tags.
-    uint32_t tag_data;
-    TIFFGetField(tif, tag_ID, &tag_data);
+    TIFFDataType tag_datatype = TIFFFieldDataType(fip);
 
-    return octave_value_list (octave_value(tag_data));
+    int count = TIFFFieldReadCount(fip);
+    octave_value tag_data_ov;
+    void *data;
+    if (count == TIFF_VARIABLE)
+    {
+        uint16_t count_param;
+        if (TIFFGetField(tif, tag_ID, &count_param, &data))
+        {
+            tag_data_ov = interpret_data(data, count_param, tag_datatype);
+        }
+        else
+        {
+            // TODO(maged): Give a better error message?
+            error("Failed to read tag");
+        }
+    }
+    else if (count == TIFF_VARIABLE2)
+    {
+        uint32_t count_param;
+        if (TIFFGetField(tif, tag_ID, &count_param, &data))
+        {
+            tag_data_ov = interpret_data(data, count_param, tag_datatype);
+        }
+        else
+        {
+            // TODO(maged): Give a better error message?
+            error("Failed to read tag");
+        }
+    }
+    else if (count == TIFF_SPP)
+    {
+        // TODO(maged): Handle TIFF_SPP
+        error("Unimplemented TIFF_SPP count");
+    }
+    else
+    {
+        int type_size = TIFFDataWidth(tag_datatype);
+        data = _TIFFmalloc(type_size * count);
+        // TODO(maged): This won't always work, e.g. string exepcts char **
+        if (TIFFGetField(tif, tag_ID, data))
+        {
+            tag_data_ov = interpret_data(data, count, tag_datatype);
+            _TIFFfree(data);
+        }
+        else
+        {
+            _TIFFfree(data);
+
+            // TODO(maged): Give a better error message?
+            error("Failed to read tag");
+        }
+        
+    }
+
+    return octave_value_list (octave_value(tag_data_ov));
 }
--- a/scripts/io/Tiff.m	Fri Jun 17 17:43:41 2022 +0200
+++ b/scripts/io/Tiff.m	Wed Jun 22 23:32:22 2022 +0200
@@ -1,5 +1,6 @@
 classdef Tiff
     properties (Constant = true)
+        % TODO(maged): Add the remaining fields
         TagID = struct(
             "ImageWidth", 256,
             "ImageLength", 257,