[gdk-pixbuf] Add TIFF image density metadata support



commit d5c1910154219fca19fae2ac1d3b8f7d416630c5
Author: Robert Ancell <robert ancell canonical com>
Date:   Wed Oct 22 13:38:06 2014 -0400

    Add TIFF image density metadata support
    
    https://bugzilla.gnome.org/show_bug.cgi?id=498721

 gdk-pixbuf/gdk-pixbuf-private.h |    1 +
 gdk-pixbuf/io-tiff.c            |   70 +++++++++++++++++++++++++++++++++++++++
 tests/Makefile.am               |    5 ++-
 tests/dpi.tiff                  |  Bin 0 -> 2805 bytes
 tests/pixbuf-dpi.c              |   23 +++++++-----
 tests/test-common.c             |    2 +-
 6 files changed, 88 insertions(+), 13 deletions(-)
---
diff --git a/gdk-pixbuf/gdk-pixbuf-private.h b/gdk-pixbuf/gdk-pixbuf-private.h
index d41dd3a..552e084 100644
--- a/gdk-pixbuf/gdk-pixbuf-private.h
+++ b/gdk-pixbuf/gdk-pixbuf-private.h
@@ -26,6 +26,7 @@
 #define GDK_PIXBUF_PRIVATE_H
 
 #include <stdio.h>
+#include <math.h>
 
 #include <glib-object.h>
 #include <glib/gi18n.h>
diff --git a/gdk-pixbuf/io-tiff.c b/gdk-pixbuf/io-tiff.c
index 67c300c..5f753fd 100644
--- a/gdk-pixbuf/io-tiff.c
+++ b/gdk-pixbuf/io-tiff.c
@@ -94,6 +94,8 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
         gchar *icc_profile_base64;
         const gchar *icc_profile;
         guint icc_profile_size;
+        uint16 resolution_unit;
+        gchar *density_str;
         gint retval;
 
         /* We're called with the lock held. */
@@ -236,6 +238,33 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
                 g_free (icc_profile_base64);
         }
 
+        retval = TIFFGetField (tiff, TIFFTAG_RESOLUTIONUNIT, &resolution_unit);
+        if (retval == 1) {
+                float x_resolution = 0, y_resolution = 0;
+
+                TIFFGetField (tiff, TIFFTAG_XRESOLUTION, &x_resolution);
+                TIFFGetField (tiff, TIFFTAG_YRESOLUTION, &y_resolution);
+
+                switch (resolution_unit) {
+                case RESUNIT_INCH:
+                        density_str = g_strdup_printf ("%d", (int) round (x_resolution));
+                        gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
+                        g_free (density_str);
+                        density_str = g_strdup_printf ("%d", (int) round (y_resolution));
+                        gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
+                        g_free (density_str);
+                        break;
+                case RESUNIT_CENTIMETER:
+                        density_str = g_strdup_printf ("%d", DPCM_TO_DPI (x_resolution));
+                        gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
+                        g_free (density_str);
+                        density_str = g_strdup_printf ("%d", DPCM_TO_DPI (y_resolution));
+                        gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
+                        g_free (density_str);
+                        break;
+                }
+        }
+
        if (context && context->prepare_func)
                (* context->prepare_func) (pixbuf, NULL, context->user_data);
 
@@ -661,6 +690,8 @@ gdk_pixbuf__tiff_image_save_to_callback (GdkPixbufSaveFunc   save_func,
         TiffSaveContext *context;
         gboolean retval;
         const gchar *icc_profile = NULL;
+        const gchar *x_dpi = NULL;
+        const gchar *y_dpi = NULL;
 
         tiff_set_handlers ();
 
@@ -703,6 +734,10 @@ gdk_pixbuf__tiff_image_save_to_callback (GdkPixbufSaveFunc   save_func,
                             compression = values[i];
                     else if (g_str_equal (keys[i], "icc-profile"))
                             icc_profile = values[i];
+                    else if (g_str_equal (keys[i], "x-dpi"))
+                            x_dpi = values[i];
+                    else if (g_str_equal (keys[i], "y-dpi"))
+                            y_dpi = values[i];
                    i++;
             }
         }
@@ -859,6 +894,41 @@ gdk_pixbuf__tiff_image_save_to_callback (GdkPixbufSaveFunc   save_func,
                 goto cleanup;
         }
 
+        if (x_dpi != NULL && y_dpi != NULL) {
+                char *endptr = NULL;
+                uint16 resolution_unit = RESUNIT_INCH;
+                float x_dpi_value, y_dpi_value;
+
+                x_dpi_value = strtol (x_dpi, &endptr, 10);
+                if (x_dpi[0] != '\0' && *endptr != '\0')
+                        x_dpi_value = -1;
+                if (x_dpi_value <= 0) {
+                    g_set_error (error,
+                                 GDK_PIXBUF_ERROR,
+                                 GDK_PIXBUF_ERROR_BAD_OPTION,
+                                 _("TIFF x-dpi must be greater than zero; value '%s' is not allowed."),
+                                 x_dpi);
+                    retval = FALSE;
+                    goto cleanup;
+                }
+                y_dpi_value = strtol (y_dpi, &endptr, 10);
+                if (y_dpi[0] != '\0' && *endptr != '\0')
+                        y_dpi_value = -1;
+                if (y_dpi_value <= 0) {
+                    g_set_error (error,
+                                 GDK_PIXBUF_ERROR,
+                                 GDK_PIXBUF_ERROR_BAD_OPTION,
+                                 _("TIFF y-dpi must be greater than zero; value '%s' is not allowed."),
+                                 y_dpi);
+                    retval = FALSE;
+                    goto cleanup;
+                }
+
+                TIFFSetField (tiff, TIFFTAG_RESOLUTIONUNIT, resolution_unit);
+                TIFFSetField (tiff, TIFFTAG_XRESOLUTION, x_dpi_value);
+                TIFFSetField (tiff, TIFFTAG_YRESOLUTION, y_dpi_value);
+        }
+
         TIFFClose (tiff);
 
         /* Now call the callback */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 99238c3..bf1ec82 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -43,8 +43,9 @@ dist_installed_test_data =            \
        test-animation.ani              \
        icc-profile.jpeg                \
        icc-profile.png                 \
-       dpi.jpeg                                \
-       dpi.png                                 \
+       dpi.jpeg                        \
+       dpi.png                         \
+       dpi.tiff                        \
        $(wildcard $(srcdir)/test-images/*)
 
 pixbuf_icc_SOURCES =                   \
diff --git a/tests/dpi.tiff b/tests/dpi.tiff
new file mode 100644
index 0000000..0a8971f
Binary files /dev/null and b/tests/dpi.tiff differ
diff --git a/tests/pixbuf-dpi.c b/tests/pixbuf-dpi.c
index 51613e0..7d5495e 100644
--- a/tests/pixbuf-dpi.c
+++ b/tests/pixbuf-dpi.c
@@ -54,12 +54,13 @@ test_incremental (gconstpointer data)
   g_assert_no_error (error);
 
   pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+  g_assert_nonnull (pixbuf);
   x_dpi = gdk_pixbuf_get_option (pixbuf, "x-dpi");
   y_dpi = gdk_pixbuf_get_option (pixbuf, "y-dpi");
-  g_assert (x_dpi != NULL);
-  g_assert (y_dpi != NULL);
-  g_assert (strcmp (x_dpi, "300") == 0);
-  g_assert (strcmp (y_dpi, "600") == 0);
+  g_assert_nonnull (x_dpi);
+  g_assert_nonnull (y_dpi);
+  g_assert_cmpstr (x_dpi, ==, "300");
+  g_assert_cmpstr (y_dpi, ==, "600");
 
   g_object_unref (loader);
   g_free (contents);
@@ -84,10 +85,10 @@ test_nonincremental (gconstpointer data)
 
   x_dpi = gdk_pixbuf_get_option (pixbuf, "x-dpi");
   y_dpi = gdk_pixbuf_get_option (pixbuf, "y-dpi");
-  g_assert (x_dpi != NULL);
-  g_assert (y_dpi != NULL);
-  g_assert (strcmp (x_dpi, "300") == 0);
-  g_assert (strcmp (y_dpi, "600") == 0);
+  g_assert_nonnull (x_dpi);
+  g_assert_nonnull (y_dpi);
+  g_assert_cmpstr (x_dpi, ==, "300");
+  g_assert_cmpstr (y_dpi, ==, "600");
 
   g_object_unref (pixbuf);
 }
@@ -98,9 +99,11 @@ main (int argc, char **argv)
   g_test_init (&argc, &argv, NULL);
 
   g_test_add_data_func ("/pixbuf/dpi/png", "dpi.png", test_nonincremental);
+  g_test_add_data_func ("/pixbuf/dpi/png-incremental", "dpi.png", test_incremental);
   g_test_add_data_func ("/pixbuf/dpi/jpeg", "dpi.jpeg", test_nonincremental);
-  g_test_add_data_func ("/pixbuf/dpi/png/incremental", "dpi.png", test_incremental);
-  g_test_add_data_func ("/pixbuf/dpi/jpeg/incremental", "dpi.jpeg", test_incremental);
+  g_test_add_data_func ("/pixbuf/dpi/jpeg-incremental", "dpi.jpeg", test_incremental);
+  g_test_add_data_func ("/pixbuf/dpi/tiff", "dpi.tiff", test_nonincremental);
+  g_test_add_data_func ("/pixbuf/dpi/tiff-incremental", "dpi.tiff", test_incremental);
 
   return g_test_run ();
 }
diff --git a/tests/test-common.c b/tests/test-common.c
index a7107a1..b7ff926 100644
--- a/tests/test-common.c
+++ b/tests/test-common.c
@@ -33,7 +33,7 @@ format_supported (const gchar *filename)
   GSList *formats, *l;
   gboolean retval;
   const gchar *names[] = { "png", "jpeg", "bmp", "gif", "ras",
-    "tga", "xpm", "xbm", "ico" };
+    "tga", "xpm", "xbm", "ico", "tiff" };
   gint i;
 
   for (i = 0; i < G_N_ELEMENTS (names); i++)


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