[gimp] Issue #5691: Import/Export of GeoTIFF loses important header tags.



commit b67ca557f0838719d5e784d2b1084860c8814ccf
Author: Ruthra Kumar <ruthrab gmail com>
Date:   Thu Oct 29 08:01:26 2020 +0530

    Issue #5691: Import/Export of GeoTIFF loses important header tags.
    
    file-tiff plugin can read and write GeoTIFF tags
    New checkbox 'Save GeoTIFF data' has been added to Export dialog.
    
    Signed-off-by: Ruthra Kumar <ruthrab gmail com>

 plug-ins/file-tiff/file-tiff-io.c   | 20 +++++++++++
 plug-ins/file-tiff/file-tiff-io.h   | 18 ++++++++++
 plug-ins/file-tiff/file-tiff-load.c | 68 +++++++++++++++++++++++++++++++++++
 plug-ins/file-tiff/file-tiff-save.c | 72 +++++++++++++++++++++++++++++++++++++
 plug-ins/file-tiff/file-tiff.c      |  6 ++++
 5 files changed, 184 insertions(+)
---
diff --git a/plug-ins/file-tiff/file-tiff-io.c b/plug-ins/file-tiff/file-tiff-io.c
index 4c45b9e190..6c0a3040b4 100644
--- a/plug-ins/file-tiff/file-tiff-io.c
+++ b/plug-ins/file-tiff/file-tiff-io.c
@@ -46,6 +46,7 @@ typedef struct
   gsize          position;
 } TiffIO;
 
+static TIFFExtendProc parent_extender;
 
 static void      tiff_io_warning       (const gchar *module,
                                         const gchar *fmt,
@@ -64,6 +65,23 @@ static toff_t    tiff_io_seek          (thandle_t    handle,
                                         gint         whence);
 static gint      tiff_io_close         (thandle_t    handle);
 static toff_t    tiff_io_get_file_size (thandle_t    handle);
+static void      register_geotags      (TIFF        *tif);
+
+static void
+register_geotags (TIFF *tif)
+{
+  static gboolean geotifftags_registered = FALSE;
+
+  if (geotifftags_registered)
+    return;
+
+  geotifftags_registered = TRUE;
+
+  TIFFMergeFieldInfo (tif, geotifftags_fieldinfo, (sizeof (geotifftags_fieldinfo) / sizeof 
(geotifftags_fieldinfo[0])));
+
+  if (parent_extender)
+    (*parent_extender) (tif);
+}
 
 
 static TiffIO tiff_io = { 0, };
@@ -77,6 +95,8 @@ tiff_open (GFile        *file,
   TIFFSetWarningHandler ((TIFFErrorHandler) tiff_io_warning);
   TIFFSetErrorHandler ((TIFFErrorHandler) tiff_io_error);
 
+  parent_extender = TIFFSetTagExtender (register_geotags);
+
   tiff_io.file = file;
 
   if (! strcmp (mode, "r"))
diff --git a/plug-ins/file-tiff/file-tiff-io.h b/plug-ins/file-tiff/file-tiff-io.h
index f4d4e31879..fc26357758 100644
--- a/plug-ins/file-tiff/file-tiff-io.h
+++ b/plug-ins/file-tiff/file-tiff-io.h
@@ -22,6 +22,24 @@
 #ifndef __FILE_TIFF_IO_H__
 #define __FILE_TIFF_IO_H__
 
+/* Adding support for GeoTIFF Tags */
+
+#define GEOTIFF_MODELPIXELSCALE      33550
+#define GEOTIFF_MODELTIEPOINT        33922
+#define GEOTIFF_MODELTRANSFORMATION  34264
+#define GEOTIFF_KEYDIRECTORY         34735
+#define GEOTIFF_DOUBLEPARAMS         34736
+#define GEOTIFF_ASCIIPARAMS          34737
+
+
+static const TIFFFieldInfo geotifftags_fieldinfo[] = {
+  { GEOTIFF_MODELPIXELSCALE,      -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE,  "GeoModelPixelScale" },
+  { GEOTIFF_MODELTIEPOINT,        -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE,  "GeoTiePoints" },
+  { GEOTIFF_MODELTRANSFORMATION,  -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE,  "GeoModelTransformation" },
+  { GEOTIFF_KEYDIRECTORY,         -1, -1, TIFF_SHORT,  FIELD_CUSTOM, TRUE, TRUE,  "GeoKeyDirectory" },
+  { GEOTIFF_DOUBLEPARAMS,         -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE,  "GeoDoubleParams" },
+  { GEOTIFF_ASCIIPARAMS,          -1, -1, TIFF_ASCII,  FIELD_CUSTOM, TRUE, FALSE, "GeoAsciiParams" }
+};
 
 TIFF * tiff_open (GFile        *file,
                   const gchar  *mode,
diff --git a/plug-ins/file-tiff/file-tiff-load.c b/plug-ins/file-tiff/file-tiff-load.c
index 56c504af91..2edd742470 100644
--- a/plug-ins/file-tiff/file-tiff-load.c
+++ b/plug-ins/file-tiff/file-tiff-load.c
@@ -887,6 +887,74 @@ load_image (GFile        *file,
           }
       }
 
+
+      /* Attach GeoTIFF Tags as Parasite, If available */
+      {
+        GimpParasite *parasite    = NULL;
+        void         *geotag_data = NULL;
+        uint32        count       = 0;
+
+        if (TIFFGetField (tif, GEOTIFF_MODELPIXELSCALE, &count, &geotag_data))
+          {
+            parasite = gimp_parasite_new ("Gimp_GeoTIFF_ModelPixelScale",
+                                          GIMP_PARASITE_PERSISTENT,
+                                          (TIFFDataWidth (TIFF_DOUBLE) * count),
+                                          geotag_data);
+            gimp_image_attach_parasite (*image, parasite);
+            gimp_parasite_free (parasite);
+          }
+
+        if (TIFFGetField (tif, GEOTIFF_MODELTIEPOINT, &count, &geotag_data))
+          {
+            parasite = gimp_parasite_new ("Gimp_GeoTIFF_ModelTiePoint",
+                                          GIMP_PARASITE_PERSISTENT,
+                                          (TIFFDataWidth (TIFF_DOUBLE) * count),
+                                          geotag_data);
+            gimp_image_attach_parasite (*image, parasite);
+            gimp_parasite_free (parasite);
+          }
+
+        if (TIFFGetField (tif, GEOTIFF_MODELTRANSFORMATION, &count, &geotag_data))
+          {
+            parasite = gimp_parasite_new ("Gimp_GeoTIFF_ModelTransformation",
+                                          GIMP_PARASITE_PERSISTENT,
+                                          (TIFFDataWidth (TIFF_DOUBLE) * count),
+                                          geotag_data);
+            gimp_image_attach_parasite (*image, parasite);
+            gimp_parasite_free (parasite);
+          }
+
+        if (TIFFGetField (tif, GEOTIFF_KEYDIRECTORY, &count, &geotag_data) )
+          {
+            parasite = gimp_parasite_new ("Gimp_GeoTIFF_KeyDirectory",
+                                          GIMP_PARASITE_PERSISTENT,
+                                          (TIFFDataWidth (TIFF_SHORT) * count),
+                                          geotag_data);
+            gimp_image_attach_parasite (*image, parasite);
+            gimp_parasite_free (parasite);
+          }
+
+        if (TIFFGetField (tif, GEOTIFF_DOUBLEPARAMS, &count, &geotag_data))
+          {
+            parasite = gimp_parasite_new ("Gimp_GeoTIFF_DoubleParams",
+                                          GIMP_PARASITE_PERSISTENT,
+                                          (TIFFDataWidth (TIFF_DOUBLE) * count),
+                                          geotag_data);
+            gimp_image_attach_parasite (*image, parasite);
+            gimp_parasite_free (parasite);
+          }
+
+        if (TIFFGetField (tif, GEOTIFF_ASCIIPARAMS, &count, &geotag_data))
+          {
+            parasite = gimp_parasite_new ("Gimp_GeoTIFF_Asciiparams",
+                                          GIMP_PARASITE_PERSISTENT,
+                                          (TIFFDataWidth (TIFF_ASCII) * count),
+                                          geotag_data);
+            gimp_image_attach_parasite (*image, parasite);
+            gimp_parasite_free (parasite);
+          }
+      }
+
       /* any resolution info in the file? */
       {
         gfloat   xres = 72.0;
diff --git a/plug-ins/file-tiff/file-tiff-save.c b/plug-ins/file-tiff/file-tiff-save.c
index 337ad08aa8..0965cdbc66 100644
--- a/plug-ins/file-tiff/file-tiff-save.c
+++ b/plug-ins/file-tiff/file-tiff-save.c
@@ -320,10 +320,12 @@ save_layer (TIFF        *tif,
   gint              offset_x, offset_y;
   gint              config_compression;
   gboolean          config_save_transp_pixels;
+  gboolean          config_save_geotiff_tags;
 
   g_object_get (config,
                 "compression",             &config_compression,
                 "save-transparent-pixels", &config_save_transp_pixels,
+                "save-geotiff",            &config_save_geotiff_tags,
                 NULL);
 
   compression = gimp_compression_to_tiff_compression (config_compression);
@@ -771,6 +773,72 @@ save_layer (TIFF        *tif,
                               * (gdouble) row / (gdouble) rows);
     }
 
+  /* Save GeoTIFF tags to file, if available */
+  if (config_save_geotiff_tags)
+    {
+      GimpParasite *parasite = NULL;
+
+      parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_ModelPixelScale");
+
+      if (parasite)
+        {
+          TIFFSetField (tif,
+                        GEOTIFF_MODELPIXELSCALE,
+                        (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
+                        gimp_parasite_data (parasite));
+          gimp_parasite_free (parasite);
+        }
+
+      parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_ModelTiePoint");
+      if (parasite)
+        {
+          TIFFSetField (tif,
+                        GEOTIFF_MODELTIEPOINT,
+                        (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
+                        gimp_parasite_data (parasite));
+          gimp_parasite_free (parasite);
+        }
+
+      parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_ModelTransformation");
+      if (parasite)
+        {
+          TIFFSetField (tif,
+                        GEOTIFF_MODELTRANSFORMATION,
+                        (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
+                        gimp_parasite_data (parasite));
+          gimp_parasite_free (parasite);
+        }
+
+      parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_KeyDirectory");
+      if (parasite)
+        {
+          TIFFSetField (tif,
+                        GEOTIFF_KEYDIRECTORY,
+                        (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_SHORT)),
+                        gimp_parasite_data (parasite));
+          gimp_parasite_free (parasite);
+        }
+
+      parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_DoubleParams");
+      if (parasite)
+        {
+          TIFFSetField (tif,
+                        GEOTIFF_DOUBLEPARAMS,
+                        (gimp_parasite_data_size (parasite) / TIFFDataWidth (TIFF_DOUBLE)),
+                        gimp_parasite_data (parasite));
+          gimp_parasite_free (parasite);
+        }
+
+      parasite = gimp_image_get_parasite (image,"Gimp_GeoTIFF_Asciiparams");
+      if (parasite)
+        {
+          TIFFSetField (tif,
+                        GEOTIFF_ASCIIPARAMS,
+                        gimp_parasite_data (parasite));
+          gimp_parasite_free (parasite);
+        }
+    }
+
   TIFFWriteDirectory (tif);
 
   gimp_progress_update (progress_base + progress_fraction);
@@ -1358,6 +1426,10 @@ save_dialog (GimpImage     *image,
                                        _("Save thumbnail"));
   gtk_grid_attach (GTK_GRID (grid), button, 0, row++, 2, 1);
 
+  button = gimp_prop_check_button_new (config, "save-geotiff",
+                                       _("Save GeoTIFF data"));
+  gtk_grid_attach (GTK_GRID (grid), button, 0 ,row++, 2, 1);
+
 #ifdef TIFFTAG_ICCPROFILE
   button = gimp_prop_check_button_new (config, "save-color-profile",
                                        _("Save color profile"));
diff --git a/plug-ins/file-tiff/file-tiff.c b/plug-ins/file-tiff/file-tiff.c
index 9b9c6bbf15..b05e3dbd44 100644
--- a/plug-ins/file-tiff/file-tiff.c
+++ b/plug-ins/file-tiff/file-tiff.c
@@ -258,6 +258,12 @@ tiff_create_procedure (GimpPlugIn  *plug_in,
                                  "Save color profile",
                                  gimp_export_color_profile (),
                                  G_PARAM_READWRITE);
+
+      GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-geotiff",
+                                 "Save GeoTIFF data",
+                                 "Save GeoTIFF data",
+                                 TRUE,
+                                 G_PARAM_READWRITE);
     }
 
   return procedure;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]