[gdk-pixbuf] Add JPEG image density metadata support
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gdk-pixbuf] Add JPEG image density metadata support
- Date: Wed, 22 Oct 2014 14:12:08 +0000 (UTC)
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]