[gdk-pixbuf] Add JPEG image density metadata support



commit 9431ab4232ab992b1884f32403c408434dd1c136
Author: Robert Ancell <robert ancell canonical com>
Date:   Tue Oct 21 15:28:45 2014 -0400

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

 gdk-pixbuf/gdk-pixbuf-io.c |    4 ++-
 gdk-pixbuf/gdk-pixbuf.c    |    2 +
 gdk-pixbuf/io-jpeg.c       |   75 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 1 deletions(-)
---
diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c
index 21af5b4..43d283f 100644
--- a/gdk-pixbuf/gdk-pixbuf-io.c
+++ b/gdk-pixbuf/gdk-pixbuf-io.c
@@ -2357,7 +2357,9 @@ gdk_pixbuf_real_save_to_callback (GdkPixbuf         *pixbuf,
  * ]|
  *
  * Currently only few parameters exist. JPEG images can be saved with a
- * "quality" parameter; its value should be in the range [0,100].
+ * "quality" parameter; its value should be in the range [0,100]. JPEG
+ * density can be set by setting the "x-dpi" and "y-dpi" parameters
+ * to the appropriate values in dots per inch.
  *
  * Text chunks can be attached to PNG images by specifying parameters of
  * the form "tEXt::key", where key is an ASCII string of length 1-79.
diff --git a/gdk-pixbuf/gdk-pixbuf.c b/gdk-pixbuf/gdk-pixbuf.c
index d6008c8..feeb605 100644
--- a/gdk-pixbuf/gdk-pixbuf.c
+++ b/gdk-pixbuf/gdk-pixbuf.c
@@ -897,6 +897,8 @@ gdk_pixbuf_fill (GdkPixbuf *pixbuf,
  * return an "orientation" option string that corresponds to the embedded 
  * TIFF/Exif orientation tag (if present). Since 2.32, the TIFF loader sets
  * the "multipage" option string to "yes" when a multi-page TIFF is loaded.
+ * Since 2.32 the JPEG loader sets "x-dpi" and "y-dpi" if the file contains
+ * image density information in dots per inch.
  * 
  * Return value: the value associated with @key. This is a nul-terminated 
  * string that should not be freed or %NULL if @key was not found.
diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c
index 277a910..5e266b6 100644
--- a/gdk-pixbuf/io-jpeg.c
+++ b/gdk-pixbuf/io-jpeg.c
@@ -46,6 +46,8 @@
 /* we are a "source manager" as far as libjpeg is concerned */
 #define JPEG_PROG_BUF_SIZE 65536
 
+#define DPCM_TO_DPI(value) ((int) round ((value) / 2.54))
+
 typedef struct {
        struct jpeg_source_mgr pub;   /* public fields */
 
@@ -519,6 +521,7 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
 {
        gint   i;
        char   otag_str[5];
+       char  *density_str;
        GdkPixbuf * volatile pixbuf = NULL;
        guchar *dptr;
        guchar *lines[4]; /* Used to expand rows, via rec_outbuf_height, 
@@ -600,6 +603,27 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
                goto out; 
        }
 
+       switch (cinfo.density_unit) {
+       case 1:
+               /* Dots per inch (no conversion required) */
+               density_str = g_strdup_printf ("%d", cinfo.X_density);
+               gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
+               g_free (density_str);
+               density_str = g_strdup_printf ("%d", cinfo.Y_density);
+               gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
+               g_free (density_str);
+               break;
+       case 2:
+               /* Dots per cm - convert into dpi */
+               density_str = g_strdup_printf ("%d", DPCM_TO_DPI (cinfo.X_density));
+               gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
+               g_free (density_str);
+               density_str = g_strdup_printf ("%d", DPCM_TO_DPI (cinfo.Y_density));
+               gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
+               g_free (density_str);
+               break;
+       }
+
        /* if orientation tag was found */
        if (exif_context.orientation != 0) {
                g_snprintf (otag_str, sizeof (otag_str), "%d", exif_context.orientation);
@@ -1226,6 +1250,8 @@ real_save_jpeg (GdkPixbuf          *pixbuf,
        int n_channels;
        struct error_handler_data jerr;
        ToFunctionDestinationManager to_callback_destmgr;
+       int x_density = 0;
+       int y_density = 0;
        gchar *icc_profile = NULL;
        gchar *data;
        gint retval = TRUE;
@@ -1268,6 +1294,48 @@ real_save_jpeg (GdkPixbuf          *pixbuf,
                                        retval = FALSE;
                                        goto cleanup;
                                }
+                       } else if (strcmp (*kiter, "x-dpi") == 0) {
+                               char *endptr = NULL;
+                               x_density = strtol (*viter, &endptr, 10);
+                               if (endptr == *viter)
+                                       x_density = -1;
+
+                               if (x_density <= 0 ||
+                                   x_density > 65535) {
+                                       /* This is a user-visible error;
+                                        * lets people skip the range-checking
+                                        * in their app.
+                                        */
+                                       g_set_error (error,
+                                                    GDK_PIXBUF_ERROR,
+                                                    GDK_PIXBUF_ERROR_BAD_OPTION,
+                                                    _("JPEG x-dpi must be a value between 1 and 65535; value 
'%s' is not allowed."),
+                                                    *viter);
+
+                                       retval = FALSE;
+                                       goto cleanup;
+                               }
+                       } else if (strcmp (*kiter, "y-dpi") == 0) {
+                               char *endptr = NULL;
+                               y_density = strtol (*viter, &endptr, 10);
+                               if (endptr == *viter)
+                                       y_density = -1;
+
+                               if (y_density <= 0 ||
+                                   y_density > 65535) {
+                                       /* This is a user-visible error;
+                                        * lets people skip the range-checking
+                                        * in their app.
+                                        */
+                                       g_set_error (error,
+                                                    GDK_PIXBUF_ERROR,
+                                                    GDK_PIXBUF_ERROR_BAD_OPTION,
+                                                    _("JPEG y-dpi must be a value between 1 and 65535; value 
'%s' is not allowed."),
+                                                    *viter);
+
+                                       retval = FALSE;
+                                       goto cleanup;
+                               }
                        } else if (strcmp (*kiter, "icc-profile") == 0) {
                                /* decode from base64 */
                                icc_profile = (gchar*) g_base64_decode (*viter, &icc_profile_size);
@@ -1355,6 +1423,13 @@ real_save_jpeg (GdkPixbuf          *pixbuf,
        jpeg_set_defaults (&cinfo);
        jpeg_set_quality (&cinfo, quality, TRUE);
 
+       /* set density information */
+       if (x_density > 0 && y_density > 0) {
+           cinfo.density_unit = 1; /* Dots per inch */
+           cinfo.X_density = x_density;
+           cinfo.Y_density = y_density;
+       }
+
        jpeg_start_compress (&cinfo, TRUE);
 
        /* write ICC profile data */


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