Commit 5d300d57 authored by Raphael Quinet's avatar Raphael Quinet Committed by Raphaël Quinet
Browse files

updated test for libjpeg so that it requires version 6b (27-Mar-1998) or

2005-04-12  Raphael Quinet  <raphael@gimp.org>

	* configure.in: updated test for libjpeg so that it requires
	version 6b (27-Mar-1998) or later.

	* plug-ins/jpeg/jpeg.h
	* plug-ins/jpeg/jpeg.c
	* plug-ins/jpeg/jpeg-load.c
	* plug-ins/jpeg/jpeg-save.h
	* plug-ins/jpeg/jpeg-save.c: added support for loading and saving
	XMP packets in JPEG APP1 markers, simplified the code that reads
	comments from COM markers and removed #ifdef HAVE_PROGRESSIVE_JPEG
	because we require jpeg-6b, which includes progressive support.
parent c6df6e6a
2005-04-12 Raphaël Quinet <raphael@gimp.org>
* configure.in: updated test for libjpeg so that it requires
version 6b (27-Mar-1998) or later.
* plug-ins/jpeg/jpeg.h
* plug-ins/jpeg/jpeg.c
* plug-ins/jpeg/jpeg-load.c
* plug-ins/jpeg/jpeg-save.h
* plug-ins/jpeg/jpeg-save.c: added support for loading and saving
XMP packets in JPEG APP1 markers, simplified the code that reads
comments from COM markers and removed #ifdef HAVE_PROGRESSIVE_JPEG
because we require jpeg-6b, which includes progressive support.
2005-04-11 Bill Skaggs <weskaggs@primate.ucdavis.edu>
* plug-ins/Lighting/lighting_shade.c: Fix typo responsible for
......
......@@ -962,11 +962,11 @@ AC_ARG_WITH(libjpeg, [ --without-libjpeg build without JPEG support])
jpeg_ok=no)
AC_MSG_RESULT($jpeg_ok)
if test "$jpeg_ok" = yes; then
JPEG='jpeg$(EXEEXT)'; LIBJPEG='-ljpeg'
AC_CHECK_LIB(jpeg, jpeg_simple_progression,
AC_DEFINE(HAVE_PROGRESSIVE_JPEG, 1,
[Define to 1 if jpeglib supports progressive JPEG.]),
AC_MSG_WARN(JPEG library does not support progressive saving.))
AC_CHECK_LIB(jpeg, jpeg_save_markers,
JPEG='jpeg$(EXEEXT)'; LIBJPEG='-ljpeg',
[jpeg_ok=no
AC_MSG_WARN(*** JPEG plug-in will not be built (JPEG library is too old) ***)
AC_MSG_WARN(*** XJT plug-in will not be built (JPEG library is too old) ***)])
else
AC_MSG_WARN(*** JPEG plug-in will not be built (JPEG header file not found) ***)
AC_MSG_WARN(*** XJT plug-in will not be built (JPEG header file not found) ***)
......
......@@ -40,59 +40,6 @@
#include "jpeg-load.h"
/* Read next byte */
static guint
jpeg_getc (j_decompress_ptr cinfo)
{
struct jpeg_source_mgr *datasrc = cinfo->src;
if (datasrc->bytes_in_buffer == 0)
{
if (! (*datasrc->fill_input_buffer) (cinfo))
ERREXIT (cinfo, JERR_CANT_SUSPEND);
}
datasrc->bytes_in_buffer--;
return *datasrc->next_input_byte++;
}
/* We need our own marker parser, since early versions of libjpeg
* don't keep a conventient list of the marker's that have been
* seen. */
/*
* Marker processor for COM markers.
* This replaces the library's built-in processor, which just skips the marker.
* Note this code relies on a non-suspending data source.
*/
static GString *local_image_comments = NULL;
static boolean
COM_handler (j_decompress_ptr cinfo)
{
gint length;
guint ch;
length = jpeg_getc (cinfo) << 8;
length += jpeg_getc (cinfo);
if (length < 2)
return FALSE;
length -= 2; /* discount the length word itself */
if (!local_image_comments)
local_image_comments = g_string_new (NULL);
else
g_string_append_c (local_image_comments, '\n');
while (length-- > 0)
{
ch = jpeg_getc (cinfo);
g_string_append_c (local_image_comments, ch);
}
return TRUE;
}
gint32
load_image (const gchar *filename,
GimpRunMode runmode,
......@@ -113,8 +60,9 @@ load_image (const gchar *filename,
gint tile_height;
gint scanlines;
gint i, start, end;
GString *local_image_comments = NULL;
GimpParasite * volatile comment_parasite = NULL;
jpeg_saved_marker_ptr marker;
/* We set up the normal JPEG error routines. */
cinfo.err = jpeg_std_error (&jerr.pub);
......@@ -167,9 +115,11 @@ load_image (const gchar *filename,
jpeg_stdio_src (&cinfo, infile);
/* pw - step 2.1 let the lib know we want the comments. */
/* - step 2.1: tell the lib to save the comments */
jpeg_save_markers (&cinfo, JPEG_COM, 0xffff);
jpeg_set_marker_processor (&cinfo, JPEG_COM, COM_handler);
/* - step 2.2: tell the lib to save APP1 markers (may contain EXIF or XMP) */
jpeg_save_markers (&cinfo, JPEG_APP0 + 1, 0xffff);
/* Step 3: read file parameters with jpeg_read_header() */
......@@ -181,30 +131,6 @@ load_image (const gchar *filename,
* See libjpeg.doc for more info.
*/
if (!preview)
{
/* if we had any comments then make a parasite for them */
if (local_image_comments && local_image_comments->len)
{
gchar *comment = local_image_comments->str;
g_string_free (local_image_comments, FALSE);
local_image_comments = NULL;
if (g_utf8_validate (comment, -1, NULL))
comment_parasite = gimp_parasite_new ("gimp-comment",
GIMP_PARASITE_PERSISTENT,
strlen (comment) + 1,
comment);
g_free (comment);
}
/* Do not attach the "jpeg-save-options" parasite to the image
* because this conflics with the global defaults. See bug #75398:
* http://bugzilla.gnome.org/show_bug.cgi?id=75398 */
}
/* Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
......@@ -347,6 +273,84 @@ load_image (const gchar *filename,
gimp_image_set_resolution (image_ID, xresolution, yresolution);
}
/* Step 5.2: check for metadata (comments, markers containing EXIF or XMP) */
for (marker = cinfo.marker_list; marker; marker = marker->next)
{
if (marker->marker == JPEG_COM)
{
g_print ("jpeg-load: found image comment (%d bytes)\n",
marker->data_length);
if (!local_image_comments)
local_image_comments = g_string_new_len (marker->data,
marker->data_length);
else
{
g_string_append_c (local_image_comments, '\n');
g_string_append_len (local_image_comments,
marker->data, marker->data_length);
}
}
else if ((marker->marker == JPEG_APP0 + 1)
&& (marker->data_length > 13)
&& ! strcmp (JPEG_APP_HEADER_EXIF, marker->data))
{
/* FIXME: handle EXIF here once we don't use libexif anymore */
g_print ("jpeg-load: found EXIF block (%d bytes)\n",
marker->data_length - sizeof (JPEG_APP_HEADER_EXIF));
/* Note: maybe split the loop to ensure that the EXIF block is */
/* always parsed before any XMP packet */
}
else if ((marker->marker == JPEG_APP0 + 1)
&& (marker->data_length > 37)
&& ! strcmp (JPEG_APP_HEADER_XMP, marker->data))
{
GimpParam *return_vals;
gint nreturn_vals;
gchar *xmp_packet;
g_print ("jpeg-load: found XMP packet (%d bytes)\n",
marker->data_length - sizeof (JPEG_APP_HEADER_XMP));
xmp_packet = g_strndup (marker->data + sizeof (JPEG_APP_HEADER_XMP),
marker->data_length - sizeof (JPEG_APP_HEADER_XMP));
/* FIXME: running this through the PDB is not very efficient */
return_vals = gimp_run_procedure ("plug_in_metadata_decode_xmp",
&nreturn_vals,
GIMP_PDB_IMAGE, image_ID,
GIMP_PDB_STRING, xmp_packet,
GIMP_PDB_END);
if (return_vals[0].data.d_status != GIMP_PDB_SUCCESS)
{
g_warning ("JPEG - unable to decode XMP metadata packet");
}
gimp_destroy_params (return_vals, nreturn_vals);
g_free (xmp_packet);
}
}
if (!preview)
{
/* if we had any comments then make a parasite for them */
if (local_image_comments && local_image_comments->len)
{
gchar *comment = local_image_comments->str;
g_string_free (local_image_comments, FALSE);
local_image_comments = NULL;
if (g_utf8_validate (comment, -1, NULL))
comment_parasite = gimp_parasite_new ("gimp-comment",
GIMP_PARASITE_PERSISTENT,
strlen (comment) + 1,
comment);
g_free (comment);
}
/* Do not attach the "jpeg-save-options" parasite to the image
* because this conflics with the global defaults. See bug #75398:
* http://bugzilla.gnome.org/show_bug.cgi?id=75398 */
}
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
......
......@@ -36,8 +36,6 @@
#ifdef HAVE_EXIF
#include <libexif/exif-data.h>
#define MARKER_CODE_EXIF 0xE1
#endif /* HAVE_EXIF */
#include <libgimp/gimp.h>
......@@ -314,12 +312,10 @@ save_image (const gchar *filename,
cinfo.smoothing_factor = (gint) (jsvals.smoothing * 100);
cinfo.optimize_coding = jsvals.optimize;
#ifdef HAVE_PROGRESSIVE_JPEG
if (jsvals.progressive)
{
jpeg_simple_progression (&cinfo);
}
#endif /* HAVE_PROGRESSIVE_JPEG */
switch (jsvals.subsmp)
{
......@@ -469,7 +465,8 @@ save_image (const gchar *filename,
exif_data_save_data (exif_data, &exif_buf, &exif_buf_len);
}
jpeg_write_marker (&cinfo, MARKER_CODE_EXIF, exif_buf, exif_buf_len);
g_print ("jpeg-save: saving EXIF block (%d bytes)\n", exif_buf_len);
jpeg_write_marker (&cinfo, JPEG_APP0 + 1, exif_buf, exif_buf_len);
if (exif_buf)
free (exif_buf);
......@@ -479,10 +476,40 @@ save_image (const gchar *filename,
/* Step 4.1: Write the comment out - pw */
if (image_comment && *image_comment)
{
g_print ("jpeg-save: saving image comment (%d bytes)\n",
strlen (image_comment));
jpeg_write_marker (&cinfo, JPEG_COM,
(guchar *) image_comment, strlen (image_comment));
}
/* Step 4.2: Write the XMP packet in an APP1 marker */
if (jsvals.save_xmp)
{
GimpParasite *parasite;
/* FIXME: temporary hack until the right thing is done by a library */
parasite = gimp_image_parasite_find (orig_image_ID, "gimp-metadata");
if (parasite)
{
const gchar *xmp_data;
glong xmp_data_size;
gchar *app_block;
xmp_data = gimp_parasite_data (parasite) + 10;
xmp_data_size = gimp_parasite_data_size (parasite) - 10;
g_print ("jpeg-save: saving XMP packet (%d bytes)\n",
(int) xmp_data_size);
app_block = g_malloc (sizeof (JPEG_APP_HEADER_XMP) + xmp_data_size);
memcpy (app_block, JPEG_APP_HEADER_XMP,
sizeof (JPEG_APP_HEADER_XMP));
memcpy (app_block + sizeof (JPEG_APP_HEADER_XMP), xmp_data,
xmp_data_size);
jpeg_write_marker (&cinfo, JPEG_APP0 + 1, app_block,
sizeof (JPEG_APP_HEADER_XMP) + xmp_data_size);
g_free (app_block);
}
}
/* Step 5: while (scan lines remain to be written) */
/* jpeg_write_scanlines(...); */
......@@ -748,7 +775,7 @@ save_dialog (void)
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
table = gtk_table_new (4, 6, FALSE);
table = gtk_table_new (4, 7, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
gtk_table_set_col_spacing (GTK_TABLE (table), 1, 12);
......@@ -828,10 +855,6 @@ save_dialog (void)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
jsvals.progressive);
#ifndef HAVE_PROGRESSIVE_JPEG
gtk_widget_set_sensitive (toggle, FALSE);
#endif
toggle = gtk_check_button_new_with_label (_("Force baseline JPEG"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
gtk_widget_show (toggle);
......@@ -878,6 +901,19 @@ save_dialog (void)
jsvals.save_thumbnail);
#endif /* HAVE_EXIF */
/* XMP metadata */
toggle = gtk_check_button_new_with_label (_("Save XMP data"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 5, 6, GTK_FILL, 0, 0, 0);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
&jsvals.save_xmp);
/* FIXME: check if XMP packet exists, disable toggle if not */
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
jsvals.save_xmp);
/* Subsampling */
label = gtk_label_new (_("Subsampling:"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
......
......@@ -18,11 +18,6 @@
#define SCALE_WIDTH 125
/* if you are not compiling this from inside the gimp tree, you have to */
/* take care yourself if your JPEG library supports progressive mode */
/* #undef HAVE_PROGRESSIVE_JPEG if your library doesn't support it */
/* #define HAVE_PROGRESSIVE_JPEG if your library knows how to handle it */
/* See bugs #63610 and #61088 for a discussion about the quality settings */
#define DEFAULT_QUALITY 85.0
#define DEFAULT_SMOOTHING 0.0
......@@ -35,6 +30,7 @@
#define DEFAULT_PREVIEW FALSE
#define DEFAULT_EXIF TRUE
#define DEFAULT_THUMBNAIL FALSE
#define DEFAULT_XMP TRUE
typedef struct
{
......@@ -49,6 +45,7 @@ typedef struct
gboolean preview;
gboolean save_exif;
gboolean save_thumbnail;
gboolean save_xmp;
} JpegSaveVals;
JpegSaveVals jsvals;
......
......@@ -102,7 +102,7 @@ query (void)
{ GIMP_PDB_FLOAT, "quality", "Quality of saved image (0 <= quality <= 1)" },
{ GIMP_PDB_FLOAT, "smoothing", "Smoothing factor for saved image (0 <= smoothing <= 1)" },
{ GIMP_PDB_INT32, "optimize", "Optimization of entropy encoding parameters (0/1)" },
{ GIMP_PDB_INT32, "progressive", "Enable progressive jpeg image loading - ignored if not compiled with HAVE_PROGRESSIVE_JPEG (0/1)" },
{ GIMP_PDB_INT32, "progressive", "Enable progressive jpeg image loading (0/1)" },
{ GIMP_PDB_STRING, "comment", "Image comment" },
{ GIMP_PDB_INT32, "subsmp", "The subsampling option number" },
{ GIMP_PDB_INT32, "baseline", "Force creation of a baseline JPEG (non-baseline JPEGs can't be read by all decoders) (0/1)" },
......@@ -326,6 +326,7 @@ run (const gchar *name,
jsvals.preview = DEFAULT_PREVIEW;
jsvals.save_exif = DEFAULT_EXIF;
jsvals.save_thumbnail = DEFAULT_THUMBNAIL;
jsvals.save_xmp = DEFAULT_XMP;
#ifdef HAVE_EXIF
......@@ -358,6 +359,7 @@ run (const gchar *name,
jsvals.preview = save_vals->preview;
jsvals.save_exif = save_vals->save_exif;
jsvals.save_thumbnail = save_vals->save_thumbnail;
jsvals.save_xmp = save_vals->save_xmp;
gimp_parasite_free (parasite);
}
......@@ -407,9 +409,7 @@ run (const gchar *name,
jsvals.quality = 100.0 * param[5].data.d_float;
jsvals.smoothing = param[6].data.d_float;
jsvals.optimize = param[7].data.d_int32;
#ifdef HAVE_PROGRESSIVE_JPEG
jsvals.progressive = param[8].data.d_int32;
#endif /* HAVE_PROGRESSIVE_JPEG */
jsvals.baseline = param[11].data.d_int32;
jsvals.subsmp = param[10].data.d_int32;
jsvals.restart = param[12].data.d_int32;
......
......@@ -16,6 +16,10 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* headers used in some APPn markers */
#define JPEG_APP_HEADER_EXIF "Exif"
#define JPEG_APP_HEADER_XMP "http://ns.adobe.com/xap/1.0/"
typedef struct my_error_mgr
{
struct jpeg_error_mgr pub; /* "public" fields */
......@@ -40,7 +44,6 @@ gboolean load_interactive;
gint32 display_ID;
gchar *image_comment;
gint32 load_image (const gchar *filename,
GimpRunMode runmode,
gboolean preview);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment