diff --git a/plug-ins/file-jpeg/Makefile.am b/plug-ins/file-jpeg/Makefile.am index 007ac53ab7..20a307ee34 100644 --- a/plug-ins/file-jpeg/Makefile.am +++ b/plug-ins/file-jpeg/Makefile.am @@ -22,7 +22,6 @@ AM_LDFLAGS = $(mwindows) libexecdir = $(gimpplugindir)/plug-ins/file-jpeg AM_CPPFLAGS = \ - -DGIMP_DEPRECATED_REPLACE_NEW_API \ -I$(top_srcdir) \ $(GTK_CFLAGS) \ $(EXIF_CFLAGS) \ diff --git a/plug-ins/file-jpeg/jpeg-load.c b/plug-ins/file-jpeg/jpeg-load.c index aefa7c2438..2e96df3f2f 100644 --- a/plug-ins/file-jpeg/jpeg-load.c +++ b/plug-ins/file-jpeg/jpeg-load.c @@ -40,7 +40,7 @@ #include "jpeg-settings.h" #include "jpeg-load.h" -static gboolean jpeg_load_resolution (gint32 image_ID, +static gboolean jpeg_load_resolution (GimpImage *image, struct jpeg_decompress_struct *cinfo); @@ -52,18 +52,18 @@ static void jpeg_load_cmyk_to_rgb (guchar *buf, glong pixels, gpointer transform); -gint32 volatile preview_image_ID; -gint32 preview_layer_ID; +GimpImage * volatile preview_image; +GimpLayer * preview_layer; -gint32 +GimpImage * load_image (const gchar *filename, GimpRunMode runmode, gboolean preview, gboolean *resolution_loaded, GError **error) { - gint32 volatile image_ID; - gint32 layer_ID; + GimpImage * volatile image; + GimpLayer *layer; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; jpeg_saved_marker_ptr marker; @@ -96,10 +96,10 @@ load_image (const gchar *filename, g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), g_strerror (errno)); - return -1; + return NULL; } - image_ID = -1; + image = NULL; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) @@ -111,8 +111,8 @@ load_image (const gchar *filename, if (infile) fclose (infile); - if (image_ID != -1 && !preview) - gimp_image_delete (image_ID); + if (image && !preview) + gimp_image_delete (image); if (preview) destroy_preview (); @@ -120,7 +120,7 @@ load_image (const gchar *filename, if (buffer) g_object_unref (buffer); - return -1; + return NULL; } /* Now we can initialize the JPEG decompression object. */ @@ -207,7 +207,7 @@ load_image (const gchar *filename, "with %d color channels, using colorspace %d (%d).", cinfo.output_components, cinfo.out_color_space, cinfo.jpeg_color_space); - return -1; + return NULL; break; } @@ -215,7 +215,7 @@ load_image (const gchar *filename, { layer_name = _("JPEG preview"); - image_ID = preview_image_ID; + image = preview_image; } else { @@ -225,16 +225,16 @@ load_image (const gchar *filename, layer_name = _("Background"); - image_ID = gimp_image_new_with_precision (cinfo.output_width, - cinfo.output_height, - image_type, - GIMP_PRECISION_U8_NON_LINEAR); + image = gimp_image_new_with_precision (cinfo.output_width, + cinfo.output_height, + image_type, + GIMP_PRECISION_U8_NON_LINEAR); - gimp_image_undo_disable (image_ID); - gimp_image_set_filename (image_ID, filename); + gimp_image_undo_disable (image); + gimp_image_set_filename (image, filename); /* Step 5.0: save the original JPEG settings in a parasite */ - jpeg_detect_original_settings (&cinfo, image_ID); + jpeg_detect_original_settings (&cinfo, image); /* Step 5.1: check for comments, or Exif metadata in APP1 markers */ for (marker = cinfo.marker_list; marker; marker = marker->next) @@ -271,7 +271,7 @@ load_image (const gchar *filename, } } - if (jpeg_load_resolution (image_ID, &cinfo)) + if (jpeg_load_resolution (image, &cinfo)) { if (resolution_loaded) *resolution_loaded = TRUE; @@ -287,7 +287,7 @@ load_image (const gchar *filename, GIMP_PARASITE_PERSISTENT, strlen (comment_buffer->str) + 1, comment_buffer->str); - gimp_image_attach_parasite (image_ID, parasite); + gimp_image_attach_parasite (image, parasite); gimp_parasite_free (parasite); g_string_free (comment_buffer, TRUE); @@ -309,7 +309,7 @@ load_image (const gchar *filename, NULL); if (profile) { - gimp_image_set_color_profile (image_ID, profile); + gimp_image_set_color_profile (image, profile); g_object_unref (profile); } } @@ -321,15 +321,15 @@ load_image (const gchar *filename, */ } - layer_ID = gimp_layer_new (image_ID, layer_name, - cinfo.output_width, - cinfo.output_height, - layer_type, - 100, - gimp_image_get_default_new_layer_mode (image_ID)); + layer = gimp_layer_new (image, layer_name, + cinfo.output_width, + cinfo.output_height, + layer_type, + 100, + gimp_image_get_default_new_layer_mode (image)); if (preview) - preview_layer_ID = layer_ID; + preview_layer = layer; /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ @@ -338,11 +338,11 @@ load_image (const gchar *filename, * loop counter, so that we don't have to keep track ourselves. */ - buffer = gimp_drawable_get_buffer (layer_ID); + buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); format = babl_format_with_space (image_type == GIMP_RGB ? "R'G'B' u8" : "Y' u8", - gimp_drawable_get_format (layer_ID)); + gimp_drawable_get_format (GIMP_DRAWABLE (layer))); while (cinfo.output_scanline < cinfo.output_height) { @@ -433,13 +433,13 @@ load_image (const gchar *filename, gimp_progress_update (1.0); } - gimp_image_insert_layer (image_ID, layer_ID, -1, 0); + gimp_image_insert_layer (image, layer, NULL, 0); - return image_ID; + return image; } static gboolean -jpeg_load_resolution (gint32 image_ID, +jpeg_load_resolution (GimpImage *image, struct jpeg_decompress_struct *cinfo) { if (cinfo->saw_JFIF_marker && cinfo->X_density != 0 && cinfo->Y_density != 0) @@ -455,7 +455,7 @@ jpeg_load_resolution (gint32 image_ID, */ asymmetry = xresolution / yresolution; - gimp_image_get_resolution (image_ID, &xresolution, &yresolution); + gimp_image_get_resolution (image, &xresolution, &yresolution); xresolution *= asymmetry; break; @@ -466,7 +466,7 @@ jpeg_load_resolution (gint32 image_ID, case 2: /* dots per cm */ xresolution *= 2.54; yresolution *= 2.54; - gimp_image_set_unit (image_ID, GIMP_UNIT_MM); + gimp_image_set_unit (image, GIMP_UNIT_MM); break; default: @@ -475,7 +475,7 @@ jpeg_load_resolution (gint32 image_ID, break; } - gimp_image_set_resolution (image_ID, xresolution, yresolution); + gimp_image_set_resolution (image, xresolution, yresolution); return TRUE; } @@ -509,14 +509,14 @@ jpeg_load_sanitize_comment (gchar *comment) } } -gint32 +GimpImage * load_thumbnail_image (GFile *file, gint *width, gint *height, GimpImageType *type, GError **error) { - gint32 volatile image_ID = -1; + GimpImage * volatile image = NULL; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile = NULL; @@ -524,9 +524,9 @@ load_thumbnail_image (GFile *file, gimp_progress_init_printf (_("Opening thumbnail for '%s'"), g_file_get_parse_name (file)); - image_ID = gimp_image_metadata_load_thumbnail (file, error); - if (image_ID < 1) - return -1; + image = gimp_image_metadata_load_thumbnail (file, error); + if (! image) + return NULL; cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; @@ -538,10 +538,10 @@ load_thumbnail_image (GFile *file, _("Could not open '%s' for reading: %s"), g_file_get_parse_name (file), g_strerror (errno)); - if (image_ID != -1) - gimp_image_delete (image_ID); + if (image) + gimp_image_delete (image); - return -1; + return NULL; } /* Establish the setjmp return context for my_error_exit to use. */ @@ -553,10 +553,10 @@ load_thumbnail_image (GFile *file, */ jpeg_destroy_decompress (&cinfo); - if (image_ID != -1) - gimp_image_delete (image_ID); + if (image) + gimp_image_delete (image); - return -1; + return NULL; } /* Now we can initialize the JPEG decompression object. */ @@ -599,8 +599,8 @@ load_thumbnail_image (GFile *file, cinfo.output_components, cinfo.out_color_space, cinfo.jpeg_color_space); - gimp_image_delete (image_ID); - image_ID = -1; + gimp_image_delete (image); + image = NULL; break; } @@ -613,7 +613,7 @@ load_thumbnail_image (GFile *file, fclose (infile); - return image_ID; + return image; } static gpointer diff --git a/plug-ins/file-jpeg/jpeg-load.h b/plug-ins/file-jpeg/jpeg-load.h index 3844097781..9bf25d8a06 100644 --- a/plug-ins/file-jpeg/jpeg-load.h +++ b/plug-ins/file-jpeg/jpeg-load.h @@ -18,16 +18,16 @@ #ifndef __JPEG_LOAD_H__ #define __JPEG_LOAD_H__ -gint32 load_image (const gchar *filename, - GimpRunMode runmode, - gboolean preview, - gboolean *resolution_loaded, - GError **error); +GimpImage * load_image (const gchar *filename, + GimpRunMode runmode, + gboolean preview, + gboolean *resolution_loaded, + GError **error); -gint32 load_thumbnail_image (GFile *file, - gint *width, - gint *height, - GimpImageType *type, - GError **error); +GimpImage * load_thumbnail_image (GFile *file, + gint *width, + gint *height, + GimpImageType *type, + GError **error); #endif /* __JPEG_LOAD_H__ */ diff --git a/plug-ins/file-jpeg/jpeg-save.c b/plug-ins/file-jpeg/jpeg-save.c index 7926ab5872..510a82ec54 100644 --- a/plug-ins/file-jpeg/jpeg-save.c +++ b/plug-ins/file-jpeg/jpeg-save.c @@ -261,9 +261,9 @@ background_jpeg_save (PreviewPersistent *pp) gboolean save_image (const gchar *filename, - gint32 image_ID, - gint32 drawable_ID, - gint32 orig_image_ID, + GimpImage *image, + GimpDrawable *drawable, + GimpImage *orig_image, gboolean preview, GError **error) { @@ -285,9 +285,9 @@ save_image (const gchar *filename, gboolean out_linear = FALSE; gint rowstride, yend; - drawable_type = gimp_drawable_type (drawable_ID); - buffer = gimp_drawable_get_buffer (drawable_ID); - space = gimp_drawable_get_format (drawable_ID); + drawable_type = gimp_drawable_type (drawable); + buffer = gimp_drawable_get_buffer (drawable); + space = gimp_drawable_get_format (drawable); if (! preview) gimp_progress_init_printf (_("Exporting '%s'"), @@ -346,7 +346,7 @@ save_image (const gchar *filename, */ if (jsvals.save_profile) { - profile = gimp_image_get_color_profile (orig_image_ID); + profile = gimp_image_get_color_profile (orig_image); /* If a profile is explicitly set, follow its TRC, whatever the * storage format. @@ -357,11 +357,11 @@ save_image (const gchar *filename, if (! profile) { /* There is always an effective profile. */ - profile = gimp_image_get_effective_color_profile (orig_image_ID); + profile = gimp_image_get_effective_color_profile (orig_image); if (gimp_color_profile_is_linear (profile)) { - if (gimp_image_get_precision (image_ID) != GIMP_PRECISION_U8_LINEAR) + if (gimp_image_get_precision (image) != GIMP_PRECISION_U8_LINEAR) { GimpColorProfile *saved_profile; @@ -390,7 +390,7 @@ save_image (const gchar *filename, g_printerr ("%s: error getting the profile space: %s", G_STRFUNC, (*error)->message); g_clear_error (error); - space = gimp_drawable_get_format (drawable_ID); + space = gimp_drawable_get_format (drawable); } } @@ -476,7 +476,7 @@ save_image (const gchar *filename, gint t; /* override tables generated by jpeg_set_quality() with custom tables */ - quant_tables = jpeg_restore_original_tables (image_ID, num_quant_tables); + quant_tables = jpeg_restore_original_tables (image, num_quant_tables); if (quant_tables) { for (t = 0; t < num_quant_tables; t++) @@ -498,7 +498,7 @@ save_image (const gchar *filename, else cinfo.optimize_coding = jsvals.optimize; - subsampling = (gimp_drawable_is_rgb (drawable_ID) ? + subsampling = (gimp_drawable_is_rgb (drawable) ? jsvals.subsmp : JPEG_SUBSAMPLING_1x1_1x1_1x1); /* smoothing is not supported with nonstandard sampling ratios */ @@ -576,13 +576,13 @@ save_image (const gchar *filename, gdouble xresolution; gdouble yresolution; - gimp_image_get_resolution (orig_image_ID, &xresolution, &yresolution); + gimp_image_get_resolution (orig_image, &xresolution, &yresolution); if (xresolution > 1e-5 && yresolution > 1e-5) { gdouble factor; - factor = gimp_unit_get_factor (gimp_image_get_unit (orig_image_ID)); + factor = gimp_unit_get_factor (gimp_image_get_unit (orig_image)); if (factor == 2.54 /* cm */ || factor == 25.4 /* mm */) @@ -746,19 +746,19 @@ make_preview (void) { /* we freeze undo saving so that we can avoid sucking up * tile cache with our unneeded preview steps. */ - gimp_image_undo_freeze (preview_image_ID); + gimp_image_undo_freeze (preview_image); undo_touched = TRUE; } save_image (tn, - preview_image_ID, - drawable_ID_global, - orig_image_ID_global, + preview_image, + drawable_global, + orig_image_global, TRUE, NULL); - if (display_ID == -1) - display_ID = gimp_display_new (preview_image_ID); + if (! display) + display = gimp_display_new (preview_image); } else { @@ -779,15 +779,15 @@ destroy_preview (void) g_source_remove (id); } - if (gimp_image_is_valid (preview_image_ID) && - gimp_item_is_valid (preview_layer_ID)) + if (gimp_image_is_valid (preview_image) && + gimp_item_is_valid (preview_layer)) { /* assuming that reference counting is working correctly, we do not need to delete the layer, removing it from the image should be sufficient */ - gimp_image_remove_layer (preview_image_ID, preview_layer_ID); + gimp_image_remove_layer (preview_image, preview_layer); - preview_layer_ID = -1; + preview_layer = NULL; } } @@ -1189,7 +1189,7 @@ save_dialog (void) gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); - if (gimp_drawable_is_rgb (drawable_ID_global)) + if (gimp_drawable_is_rgb (drawable_global)) { gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), jsvals.subsmp, @@ -1439,7 +1439,7 @@ load_gui_defaults (JpegSaveGui *pg) { gtk_adjustment_set_value (pg->quality, jsvals.quality); - if (gimp_drawable_is_rgb (drawable_ID_global)) + if (gimp_drawable_is_rgb (drawable_global)) { gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (pg->subsmp), jsvals.subsmp); diff --git a/plug-ins/file-jpeg/jpeg-save.h b/plug-ins/file-jpeg/jpeg-save.h index 34f0eb544d..58b5c4e91d 100644 --- a/plug-ins/file-jpeg/jpeg-save.h +++ b/plug-ins/file-jpeg/jpeg-save.h @@ -40,14 +40,14 @@ typedef struct extern JpegSaveVals jsvals; -extern gint32 orig_image_ID_global; -extern gint32 drawable_ID_global; +extern GimpImage *orig_image_global; +extern GimpDrawable *drawable_global; gboolean save_image (const gchar *filename, - gint32 image_ID, - gint32 drawable_ID, - gint32 orig_image_ID, + GimpImage *image, + GimpDrawable *drawable, + GimpImage *orig_image, gboolean preview, GError **error); gboolean save_dialog (void); diff --git a/plug-ins/file-jpeg/jpeg-settings.c b/plug-ins/file-jpeg/jpeg-settings.c index 65a2d216b6..ed80db4f81 100644 --- a/plug-ins/file-jpeg/jpeg-settings.c +++ b/plug-ins/file-jpeg/jpeg-settings.c @@ -61,21 +61,21 @@ /** * jpeg_detect_original_settings: * @cinfo: a pointer to a JPEG decompressor info. - * @image_ID: the image to which the parasite should be attached. + * @image: the image to which the parasite should be attached. * * Analyze the image being decompressed (@cinfo) and extract the * sampling factors, quantization tables and overall image quality. - * Store this information in a parasite and attach it to @image_ID. + * Store this information in a parasite and attach it to @image. * * This function must be called after jpeg_read_header() so that * @cinfo contains the quantization tables and the sampling factors * for each component. * - * Returns: TRUE if a parasite has been attached to @image_ID. + * Returns: TRUE if a parasite has been attached to @image. */ gboolean jpeg_detect_original_settings (struct jpeg_decompress_struct *cinfo, - gint32 image_ID) + GimpImage *image) { guint parasite_size; guchar *parasite_data; @@ -132,8 +132,9 @@ jpeg_detect_original_settings (struct jpeg_decompress_struct *cinfo, parasite_size, parasite_data); g_free (parasite_data); - gimp_image_attach_parasite (image_ID, parasite); + gimp_image_attach_parasite (image, parasite); gimp_parasite_free (parasite); + return TRUE; } @@ -143,28 +144,28 @@ jpeg_detect_original_settings (struct jpeg_decompress_struct *cinfo, * GIMP color space of the drawable to be saved. If one of them is * grayscale and the other isn't, then the quality setting may be used * but the subsampling parameters and quantization tables should be - * ignored. The drawable_ID needs to be passed around because the + * ignored. The drawable needs to be passed around because the * color space of the drawable may be different from that of the image * (e.g., when saving a mask or channel). */ /** * jpeg_restore_original_settings: - * @image_ID: the image that may contain original jpeg settings in a parasite. + * @image: the image that may contain original jpeg settings in a parasite. * @quality: where to store the original jpeg quality. * @subsmp: where to store the original subsampling type. * @num_quant_tables: where to store the number of quantization tables found. * * Retrieve the original JPEG settings (quality, type of subsampling * and number of quantization tables) from the parasite attached to - * @image_ID. If the number of quantization tables is greater than + * @image. If the number of quantization tables is greater than * zero, then these tables can be retrieved from the parasite by * calling jpeg_restore_original_tables(). * * Returns: TRUE if a valid parasite was attached to the image */ gboolean -jpeg_restore_original_settings (gint32 image_ID, +jpeg_restore_original_settings (GimpImage *image, gint *quality, JpegSubsampling *subsmp, gint *num_quant_tables) @@ -183,7 +184,7 @@ jpeg_restore_original_settings (gint32 image_ID, g_return_val_if_fail (subsmp != NULL, FALSE); g_return_val_if_fail (num_quant_tables != NULL, FALSE); - parasite = gimp_image_get_parasite (image_ID, "jpeg-settings"); + parasite = gimp_image_get_parasite (image, "jpeg-settings"); if (parasite) { src = gimp_parasite_data (parasite); @@ -248,11 +249,11 @@ jpeg_restore_original_settings (gint32 image_ID, /** * jpeg_restore_original_tables: - * @image_ID: the image that may contain original jpeg settings in a parasite. + * @image: the image that may contain original jpeg settings in a parasite. * @num_quant_tables: the number of quantization tables to restore. * * Retrieve the original quantization tables from the parasite - * attached to @image_ID. Each table is an array of coefficients that + * attached to @image. Each table is an array of coefficients that * can be associated with a component of a JPEG image when saving it. * * An array of newly allocated tables is returned if @num_quant_tables @@ -267,8 +268,8 @@ jpeg_restore_original_settings (gint32 image_ID, * Returns: (nullable): an array of quantization tables, or NULL. */ guint ** -jpeg_restore_original_tables (gint32 image_ID, - gint num_quant_tables) +jpeg_restore_original_tables (GimpImage *image, + gint num_quant_tables) { GimpParasite *parasite; const guchar *src; @@ -279,7 +280,7 @@ jpeg_restore_original_tables (gint32 image_ID, gint t; gint i; - parasite = gimp_image_get_parasite (image_ID, "jpeg-settings"); + parasite = gimp_image_get_parasite (image, "jpeg-settings"); if (parasite) { src_size = gimp_parasite_data_size (parasite); @@ -319,7 +320,7 @@ jpeg_restore_original_tables (gint32 image_ID, /** * jpeg_swap_original_settings: - * @image_ID: the image that may contain original jpeg settings in a parasite. + * @image: the image that may contain original jpeg settings in a parasite. * * Swap the horizontal and vertical axis for the saved subsampling * parameters and quantization tables. This should be done if the @@ -327,7 +328,7 @@ jpeg_restore_original_tables (gint32 image_ID, * mirrored along its diagonal. */ void -jpeg_swap_original_settings (gint32 image_ID) +jpeg_swap_original_settings (GimpImage *image) { GimpParasite *parasite; const guchar *src; @@ -340,7 +341,7 @@ jpeg_swap_original_settings (gint32 image_ID) gint i; gint j; - parasite = gimp_image_get_parasite (image_ID, "jpeg-settings"); + parasite = gimp_image_get_parasite (image, "jpeg-settings"); if (parasite) { src_size = gimp_parasite_data_size (parasite); @@ -389,7 +390,7 @@ jpeg_swap_original_settings (gint32 image_ID) src_size, new_data); g_free (new_data); - gimp_image_attach_parasite (image_ID, parasite); + gimp_image_attach_parasite (image, parasite); } } gimp_parasite_free (parasite); diff --git a/plug-ins/file-jpeg/jpeg-settings.h b/plug-ins/file-jpeg/jpeg-settings.h index 0399b84ba2..70cbea14b0 100644 --- a/plug-ins/file-jpeg/jpeg-settings.h +++ b/plug-ins/file-jpeg/jpeg-settings.h @@ -22,16 +22,16 @@ #define __JPEG_SETTINGS_H__ gboolean jpeg_detect_original_settings (struct jpeg_decompress_struct *cinfo, - gint32 image_ID); + GimpImage *image); -gboolean jpeg_restore_original_settings (gint32 image_ID, +gboolean jpeg_restore_original_settings (GimpImage *image, gint *quality, JpegSubsampling *subsmp, gint *num_quant_tables); -guint **jpeg_restore_original_tables (gint32 image_ID, +guint **jpeg_restore_original_tables (GimpImage *image, gint num_quant_tables); -void jpeg_swap_original_settings (gint32 image_ID); +void jpeg_swap_original_settings (GimpImage *image); #endif /* __JPEG_SETTINGS_H__ */ diff --git a/plug-ins/file-jpeg/jpeg.c b/plug-ins/file-jpeg/jpeg.c index f645d64da4..7e9373df6f 100644 --- a/plug-ins/file-jpeg/jpeg.c +++ b/plug-ins/file-jpeg/jpeg.c @@ -34,568 +34,660 @@ #include "jpeg-load.h" #include "jpeg-save.h" -/* Declare local functions. - */ -static void query (void); -static void run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals); +typedef struct _Jpeg Jpeg; +typedef struct _JpegClass JpegClass; + +struct _Jpeg +{ + GimpPlugIn parent_instance; +}; + +struct _JpegClass +{ + GimpPlugInClass parent_class; +}; + + +#define JPEG_TYPE (jpeg_get_type ()) +#define JPEG (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), JPEG_TYPE, Jpeg)) + +GType jpeg_get_type (void) G_GNUC_CONST; + +static GList * jpeg_query_procedures (GimpPlugIn *plug_in); +static GimpProcedure * jpeg_create_procedure (GimpPlugIn *plug_in, + const gchar *name); + +static GimpValueArray * jpeg_load (GimpProcedure *procedure, + GimpRunMode run_mode, + GFile *file, + const GimpValueArray *args, + gpointer run_data); +static GimpValueArray * jpeg_load_thumb (GimpProcedure *procedure, + GFile *file, + gint size, + const GimpValueArray *args, + gpointer run_data); +static GimpValueArray * jpeg_save (GimpProcedure *procedure, + GimpRunMode run_mode, + GimpImage *image, + GimpDrawable *drawable, + GFile *file, + const GimpValueArray *args, + gpointer run_data); + + +G_DEFINE_TYPE (Jpeg, jpeg, GIMP_TYPE_PLUG_IN) + +GIMP_MAIN (JPEG_TYPE) + gboolean undo_touched; gboolean load_interactive; gchar *image_comment; -gint32 display_ID; +GimpDisplay *display; JpegSaveVals jsvals; -gint32 orig_image_ID_global; -gint32 drawable_ID_global; +GimpImage *orig_image_global; +GimpDrawable *drawable_global; gint orig_quality; JpegSubsampling orig_subsmp; gint num_quant_tables; -const GimpPlugInInfo PLUG_IN_INFO = -{ - NULL, /* init_proc */ - NULL, /* quit_proc */ - query, /* query_proc */ - run, /* run_proc */ -}; - - -MAIN () - - static void -query (void) +jpeg_class_init (JpegClass *klass) { - static const GimpParamDef load_args[] = - { - { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, - { GIMP_PDB_STRING, "filename", "The name of the file to load" }, - { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" } - }; - static const GimpParamDef load_return_vals[] = - { - { GIMP_PDB_IMAGE, "image", "Output image" } - }; + GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass); - static const GimpParamDef thumb_args[] = - { - { GIMP_PDB_STRING, "filename", "The name of the file to load" }, - { GIMP_PDB_INT32, "thumb-size", "Preferred thumbnail size" } - }; - static const GimpParamDef thumb_return_vals[] = - { - { GIMP_PDB_IMAGE, "image", "Thumbnail image" }, - { GIMP_PDB_INT32, "image-width", "Width of full-sized image" }, - { GIMP_PDB_INT32, "image-height", "Height of full-sized image" } - }; - - static const GimpParamDef save_args[] = - { - { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, - { GIMP_PDB_IMAGE, "image", "Input image" }, - { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" }, - { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" }, - { GIMP_PDB_STRING, "raw-filename", "The name of the file to save the image in" }, - { 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", "Use optimized tables during Huffman coding (0/1)" }, - { GIMP_PDB_INT32, "progressive", "Create progressive JPEG images (0/1)" }, - { GIMP_PDB_STRING, "comment", "Image comment" }, - { GIMP_PDB_INT32, "subsmp", "Sub-sampling type { 0, 1, 2, 3 } 0 == 4:2:0 (chroma quartered), 1 == 4:2:2 Horizontal (chroma halved), 2 == 4:4:4 (best quality), 3 == 4:2:2 Vertical (chroma halved)" }, - { GIMP_PDB_INT32, "baseline", "Force creation of a baseline JPEG (non-baseline JPEGs can't be read by all decoders) (0/1)" }, - { GIMP_PDB_INT32, "restart", "Interval of restart markers (in MCU rows, 0 = no restart markers)" }, - { GIMP_PDB_INT32, "dct", "DCT method to use { INTEGER (0), FIXED (1), FLOAT (2) }" } - }; - - gimp_install_procedure (LOAD_PROC, - "loads files in the JPEG file format", - "loads files in the JPEG file format", - "Spencer Kimball, Peter Mattis & others", - "Spencer Kimball & Peter Mattis", - "1995-2007", - N_("JPEG image"), - NULL, - GIMP_PLUGIN, - G_N_ELEMENTS (load_args), - G_N_ELEMENTS (load_return_vals), - load_args, load_return_vals); - - gimp_register_file_handler_mime (LOAD_PROC, "image/jpeg"); - gimp_register_magic_load_handler (LOAD_PROC, - "jpg,jpeg,jpe", - "", - "6,string,JFIF,6,string,Exif"); - - gimp_install_procedure (LOAD_THUMB_PROC, - "Loads a thumbnail from a JPEG image", - "Loads a thumbnail from a JPEG image (only if it exists)", - "Mukund Sivaraman , Sven Neumann ", - "Mukund Sivaraman , Sven Neumann ", - "November 15, 2004", - NULL, - NULL, - GIMP_PLUGIN, - G_N_ELEMENTS (thumb_args), - G_N_ELEMENTS (thumb_return_vals), - thumb_args, thumb_return_vals); - - gimp_register_thumbnail_loader (LOAD_PROC, LOAD_THUMB_PROC); - - gimp_install_procedure (SAVE_PROC, - "saves files in the JPEG file format", - "saves files in the lossy, widely supported JPEG format", - "Spencer Kimball, Peter Mattis & others", - "Spencer Kimball & Peter Mattis", - "1995-2007", - N_("JPEG image"), - "RGB*, GRAY*", - GIMP_PLUGIN, - G_N_ELEMENTS (save_args), 0, - save_args, NULL); - - gimp_register_file_handler_mime (SAVE_PROC, "image/jpeg"); - gimp_register_save_handler (SAVE_PROC, "jpg,jpeg,jpe", ""); + plug_in_class->query_procedures = jpeg_query_procedures; + plug_in_class->create_procedure = jpeg_create_procedure; } static void -run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals) +jpeg_init (Jpeg *jpeg) { - static GimpParam values[6]; - GimpRunMode run_mode; - GimpPDBStatusType status = GIMP_PDB_SUCCESS; - gint32 image_ID; - gint32 drawable_ID; - GimpParasite *parasite; - GError *error = NULL; +} - run_mode = param[0].data.d_int32; +static GList * +jpeg_query_procedures (GimpPlugIn *plug_in) +{ + GList *list = NULL; + + list = g_list_append (list, g_strdup (LOAD_PROC)); + list = g_list_append (list, g_strdup (LOAD_THUMB_PROC)); + list = g_list_append (list, g_strdup (SAVE_PROC)); + + return list; +} + +static GimpProcedure * +jpeg_create_procedure (GimpPlugIn *plug_in, + const gchar *name) +{ + GimpProcedure *procedure = NULL; + + if (! strcmp (name, LOAD_PROC)) + { + procedure = gimp_load_procedure_new (plug_in, name, GIMP_PLUGIN, + jpeg_load, NULL, NULL); + + gimp_procedure_set_menu_label (procedure, N_("JPEG image")); + + gimp_procedure_set_documentation (procedure, + "Loads files in the JPEG file format", + "Loads files in the JPEG file format", + name); + gimp_procedure_set_attribution (procedure, + "Spencer Kimball, Peter Mattis & others", + "Spencer Kimball & Peter Mattis", + "1995-2007"); + + gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure), + "image/jpeg"); + gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), + "jpg,jpeg,jpe"); + gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure), + "6,string,JFIF,6,string,Exif"); + + gimp_load_procedure_set_thumbnail_loader (GIMP_LOAD_PROCEDURE (procedure), + LOAD_THUMB_PROC); + } + else if (! strcmp (name, LOAD_THUMB_PROC)) + { + procedure = gimp_thumbnail_procedure_new (plug_in, name, GIMP_PLUGIN, + jpeg_load_thumb, NULL, NULL); + + gimp_procedure_set_documentation (procedure, + "Loads a thumbnail from a JPEG image", + "Loads a thumbnail from a JPEG image, " + "if one exists", + name); + gimp_procedure_set_attribution (procedure, + "Mukund Sivaraman , " + "Sven Neumann ", + "Mukund Sivaraman , " + "Sven Neumann ", + "November 15, 2004"); + } + else if (! strcmp (name, SAVE_PROC)) + { + procedure = gimp_save_procedure_new (plug_in, name, GIMP_PLUGIN, + jpeg_save, NULL, NULL); + + gimp_procedure_set_image_types (procedure, "RGB*, GRAY*"); + + gimp_procedure_set_menu_label (procedure, N_("JPEG image")); + + gimp_procedure_set_documentation (procedure, + "Saves files in the JPEG file format", + "Saves files in the lossy, widely " + "supported JPEG format", + name); + gimp_procedure_set_attribution (procedure, + "Spencer Kimball, Peter Mattis & others", + "Spencer Kimball & Peter Mattis", + "1995-2007"); + + gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure), + "image/jpeg"); + gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), + "jpg,jpeg,jpe"); + + GIMP_PROC_ARG_DOUBLE (procedure, "quality", + "Quality", + "Quality of saved image", + 0.0, 1.0, 0.9, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_DOUBLE (procedure, "smoothing", + "Smoothing", + "Smoothing factor for saved image", + 0.0, 1.0, 0.0, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_BOOLEAN (procedure, "optimize", + "Optimize", + "Use optimized tables during Huffman coding", + TRUE, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_BOOLEAN (procedure, "progressive", + "Progressive", + "Create progressive JPEG images", + TRUE, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_STRING (procedure, "comment", + "Comment", + "Image comment", + NULL, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_INT (procedure, "sub-sampling", + "Sub-sampling", + "Sub-sampling type { 0 == 4:2:0 (chroma quartered), " + "1 == 4:2:2 Horizontal (chroma halved), " + "2 == 4:4:4 (best quality), " + "3 == 4:2:2 Vertical (chroma halved)", + JPEG_SUBSAMPLING_2x2_1x1_1x1, + JPEG_SUBSAMPLING_1x2_1x1_1x1, + JPEG_SUBSAMPLING_1x1_1x1_1x1, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_BOOLEAN (procedure, "baseline", + "Baseline", + "Force creation of a baseline JPEG " + "(non-baseline JPEGs can't be read by all decoders)", + TRUE, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_INT (procedure, "restart", + "Restart", + "Interval of restart markers " + "(in MCU rows, 0 = no restart markers)", + 0, 64, 0, + G_PARAM_READWRITE); + + GIMP_PROC_ARG_INT (procedure, "dct", + "DCT", + "DCT method to use { " + "INTEGER (0), " + "FIXED (1), " + "FLOAT (2) }", + 0, 2, 0, + G_PARAM_READWRITE); + } + + return procedure; +} + +static GimpValueArray * +jpeg_load (GimpProcedure *procedure, + GimpRunMode run_mode, + GFile *file, + const GimpValueArray *args, + gpointer run_data) +{ + GimpValueArray *return_vals; + gchar *filename; + GimpImage *image; + gboolean resolution_loaded = FALSE; + GError *error = NULL; INIT_I18N (); gegl_init (NULL, NULL); - *nreturn_vals = 1; - *return_vals = values; - values[0].type = GIMP_PDB_STATUS; - values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; - - preview_image_ID = -1; - preview_layer_ID = -1; + preview_image = NULL; + preview_layer = NULL; orig_quality = 0; orig_subsmp = JPEG_SUBSAMPLING_2x2_1x1_1x1; num_quant_tables = 0; - if (strcmp (name, LOAD_PROC) == 0) + filename = g_file_get_path (file); + + switch (run_mode) { - GFile *file = g_file_new_for_uri (param[1].data.d_string); + case GIMP_RUN_INTERACTIVE: + case GIMP_RUN_WITH_LAST_VALS: + gimp_ui_init (PLUG_IN_BINARY, FALSE); + load_interactive = TRUE; + break; - gboolean resolution_loaded = FALSE; + default: + load_interactive = FALSE; + break; + } - switch (run_mode) + image = load_image (filename, run_mode, FALSE, + &resolution_loaded, &error); + + if (image) + { + GimpMetadata *metadata; + + metadata = gimp_image_metadata_load_prepare (image, "image/jpeg", + file, NULL); + + if (metadata) { - case GIMP_RUN_INTERACTIVE: - case GIMP_RUN_WITH_LAST_VALS: - gimp_ui_init (PLUG_IN_BINARY, FALSE); - load_interactive = TRUE; + GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL; + + if (resolution_loaded) + flags &= ~GIMP_METADATA_LOAD_RESOLUTION; + + gimp_image_metadata_load_finish (image, "image/jpeg", + metadata, flags, + load_interactive); + + g_object_unref (metadata); + } + } + + g_free (filename); + + if (! image) + return gimp_procedure_new_return_values (procedure, + GIMP_PDB_EXECUTION_ERROR, + error); + + return_vals = gimp_procedure_new_return_values (procedure, + GIMP_PDB_SUCCESS, + NULL); + + GIMP_VALUES_SET_IMAGE (return_vals, 1, image); + + return return_vals; +} + +static GimpValueArray * +jpeg_load_thumb (GimpProcedure *procedure, + GFile *file, + gint size, + const GimpValueArray *args, + gpointer run_data) +{ + GimpValueArray *return_vals; + GimpImage *image; + gint width = 0; + gint height = 0; + GimpImageType type = -1; + GError *error = NULL; + + INIT_I18N (); + gegl_init (NULL, NULL); + + preview_image = NULL; + preview_layer = NULL; + + orig_quality = 0; + orig_subsmp = JPEG_SUBSAMPLING_2x2_1x1_1x1; + num_quant_tables = 0; + + image = load_thumbnail_image (file, &width, &height, &type, + &error); + + + if (! image) + return gimp_procedure_new_return_values (procedure, + GIMP_PDB_EXECUTION_ERROR, + error); + + return_vals = gimp_procedure_new_return_values (procedure, + GIMP_PDB_SUCCESS, + NULL); + + GIMP_VALUES_SET_IMAGE (return_vals, 1, image); + GIMP_VALUES_SET_INT (return_vals, 2, width); + GIMP_VALUES_SET_INT (return_vals, 3, height); + GIMP_VALUES_SET_ENUM (return_vals, 4, type); + GIMP_VALUES_SET_INT (return_vals, 5, 1); /* 1 layer */ + + return return_vals; +} + +static GimpValueArray * +jpeg_save (GimpProcedure *procedure, + GimpRunMode run_mode, + GimpImage *image, + GimpDrawable *drawable, + GFile *file, + const GimpValueArray *args, + gpointer run_data) +{ + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + gchar *filename; + GimpParasite *parasite; + GimpMetadata *metadata; + GimpMetadataSaveFlags metadata_flags; + GimpImage *orig_image; + GimpExportReturn export = GIMP_EXPORT_CANCEL; + GError *error = NULL; + + INIT_I18N (); + gegl_init (NULL, NULL); + + preview_image = NULL; + preview_layer = NULL; + + orig_quality = 0; + orig_subsmp = JPEG_SUBSAMPLING_2x2_1x1_1x1; + num_quant_tables = 0; + + orig_image = image; + + filename = g_file_get_path (file); + + switch (run_mode) + { + case GIMP_RUN_INTERACTIVE: + case GIMP_RUN_WITH_LAST_VALS: + gimp_ui_init (PLUG_IN_BINARY, FALSE); + + export = gimp_export_image (&image, &drawable, "JPEG", + GIMP_EXPORT_CAN_HANDLE_RGB | + GIMP_EXPORT_CAN_HANDLE_GRAY); + + switch (export) + { + case GIMP_EXPORT_EXPORT: + { + gchar *tmp = g_filename_from_utf8 (_("Export Preview"), -1, + NULL, NULL, NULL); + if (tmp) + { + gimp_image_set_filename (image, tmp); + g_free (tmp); + } + + display = NULL; + } break; - default: - load_interactive = FALSE; + + case GIMP_EXPORT_IGNORE: + break; + + case GIMP_EXPORT_CANCEL: + return gimp_procedure_new_return_values (procedure, + GIMP_PDB_CANCEL, + NULL); break; } + break; - image_ID = load_image (g_file_get_path (file), run_mode, FALSE, - &resolution_loaded, &error); + default: + break; + } - if (image_ID != -1) + /* Initialize with hardcoded defaults */ + load_defaults (); + + /* Override the defaults with preferences. */ + metadata = gimp_image_metadata_save_prepare (orig_image, + "image/jpeg", + &metadata_flags); + jsvals.save_exif = (metadata_flags & GIMP_METADATA_SAVE_EXIF) != 0; + jsvals.save_xmp = (metadata_flags & GIMP_METADATA_SAVE_XMP) != 0; + jsvals.save_iptc = (metadata_flags & GIMP_METADATA_SAVE_IPTC) != 0; + jsvals.save_thumbnail = (metadata_flags & GIMP_METADATA_SAVE_THUMBNAIL) != 0; + jsvals.save_profile = (metadata_flags & GIMP_METADATA_SAVE_COLOR_PROFILE) != 0; + + parasite = gimp_image_get_parasite (orig_image, "gimp-comment"); + if (parasite) + { + image_comment = g_strndup (gimp_parasite_data (parasite), + gimp_parasite_data_size (parasite)); + gimp_parasite_free (parasite); + } + + /* Override preferences from JPG export defaults (if saved). */ + load_parasite (); + + switch (run_mode) + { + case GIMP_RUN_NONINTERACTIVE: + g_free (image_comment); + + jsvals.quality = GIMP_VALUES_GET_DOUBLE (args, 0) * 100.0; + jsvals.smoothing = GIMP_VALUES_GET_DOUBLE (args, 1); + jsvals.optimize = GIMP_VALUES_GET_BOOLEAN (args, 2); + jsvals.progressive = GIMP_VALUES_GET_BOOLEAN (args, 3); + image_comment = GIMP_VALUES_DUP_STRING (args, 4); + jsvals.subsmp = GIMP_VALUES_GET_DOUBLE (args, 5); + jsvals.baseline = GIMP_VALUES_GET_DOUBLE (args, 6); + jsvals.restart = GIMP_VALUES_GET_DOUBLE (args, 7); + jsvals.dct = GIMP_VALUES_GET_DOUBLE (args, 8); + jsvals.preview = FALSE; + break; + + case GIMP_RUN_INTERACTIVE: + case GIMP_RUN_WITH_LAST_VALS: + /* restore the values found when loading the file (if available) */ + jpeg_restore_original_settings (orig_image, + &orig_quality, + &orig_subsmp, + &num_quant_tables); + + /* load up the previously used values (if file was saved once) */ + parasite = gimp_image_get_parasite (orig_image, + "jpeg-save-options"); + if (parasite) { - GimpMetadata *metadata; + const JpegSaveVals *save_vals = gimp_parasite_data (parasite); - metadata = gimp_image_metadata_load_prepare (image_ID, "image/jpeg", - file, NULL); + jsvals.quality = save_vals->quality; + jsvals.smoothing = save_vals->smoothing; + jsvals.optimize = save_vals->optimize; + jsvals.progressive = save_vals->progressive; + jsvals.baseline = save_vals->baseline; + jsvals.subsmp = save_vals->subsmp; + jsvals.restart = save_vals->restart; + jsvals.dct = save_vals->dct; + 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; + jsvals.save_iptc = save_vals->save_iptc; + jsvals.use_orig_quality = save_vals->use_orig_quality; - if (metadata) - { - GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL; - - if (resolution_loaded) - flags &= ~GIMP_METADATA_LOAD_RESOLUTION; - - gimp_image_metadata_load_finish (image_ID, "image/jpeg", - metadata, flags, - load_interactive); - - g_object_unref (metadata); - } - - *nreturn_vals = 2; - values[1].type = GIMP_PDB_IMAGE; - values[1].data.d_image = image_ID; + gimp_parasite_free (parasite); } else + { + /* We are called with GIMP_RUN_WITH_LAST_VALS but this image + * doesn't have a "jpeg-save-options" parasite. It's better + * to prompt the user with a dialog now so that she has + * control over the JPEG encoding parameters. + */ + run_mode = GIMP_RUN_INTERACTIVE; + + /* If this image was loaded from a JPEG file and has not + * been saved yet, try to use some of the settings from the + * original file if they are better than the default values. + */ + if (orig_quality > jsvals.quality) + { + jsvals.quality = orig_quality; + } + + /* Skip changing subsampling to original if we already have + * best setting or if original have worst setting + */ + if (!(jsvals.subsmp == JPEG_SUBSAMPLING_1x1_1x1_1x1 || + orig_subsmp == JPEG_SUBSAMPLING_2x2_1x1_1x1)) + { + jsvals.subsmp = orig_subsmp; + } + + if (orig_quality == jsvals.quality && + orig_subsmp == jsvals.subsmp) + { + jsvals.use_orig_quality = TRUE; + } + } + break; + } + + if (run_mode == GIMP_RUN_INTERACTIVE) + { + if (jsvals.preview) + { + /* we freeze undo saving so that we can avoid sucking up + * tile cache with our unneeded preview steps. */ + gimp_image_undo_freeze (image); + + undo_touched = TRUE; + } + + /* prepare for the preview */ + preview_image = image; + orig_image_global = orig_image; + drawable_global = drawable; + + /* First acquire information with a dialog */ + if (! save_dialog ()) + { + status = GIMP_PDB_CANCEL; + } + + if (undo_touched) + { + /* thaw undo saving and flush the displays to have them + * reflect the current shortcuts + */ + gimp_image_undo_thaw (image); + gimp_displays_flush (); + } + } + + if (status == GIMP_PDB_SUCCESS) + { + if (! save_image (filename, + image, drawable, orig_image, FALSE, + &error)) { status = GIMP_PDB_EXECUTION_ERROR; } } - else if (strcmp (name, LOAD_THUMB_PROC) == 0) + + if (export == GIMP_EXPORT_EXPORT) { - if (nparams < 2) - { - status = GIMP_PDB_CALLING_ERROR; - } + /* If the image was exported, delete the new display. This also + * deletes the image. + */ + if (display) + gimp_display_delete (display); else - { - GFile *file = g_file_new_for_uri (param[0].data.d_string); - gint width = 0; - gint height = 0; - GimpImageType type = -1; - - image_ID = load_thumbnail_image (file, &width, &height, &type, - &error); - - g_object_unref (file); - - if (image_ID != -1) - { - *nreturn_vals = 6; - values[1].type = GIMP_PDB_IMAGE; - values[1].data.d_image = image_ID; - values[2].type = GIMP_PDB_INT32; - values[2].data.d_int32 = width; - values[3].type = GIMP_PDB_INT32; - values[3].data.d_int32 = height; - values[4].type = GIMP_PDB_INT32; - values[4].data.d_int32 = type; - values[5].type = GIMP_PDB_INT32; - values[5].data.d_int32 = 1; /* num_layers */ - } - else - { - status = GIMP_PDB_EXECUTION_ERROR; - } - } + gimp_image_delete (image); } - else if (strcmp (name, SAVE_PROC) == 0) + + if (status == GIMP_PDB_SUCCESS) { - GFile *file = g_file_new_for_uri (param[3].data.d_string); - GimpMetadata *metadata; - GimpMetadataSaveFlags metadata_flags; - gint32 orig_image_ID; - GimpExportReturn export = GIMP_EXPORT_CANCEL; + /* pw - now we need to change the defaults to be whatever was + * used to save this image. Dump the old parasites and add new + * ones. + */ - image_ID = param[1].data.d_int32; - drawable_ID = param[2].data.d_int32; - - orig_image_ID = image_ID; - - switch (run_mode) + gimp_image_detach_parasite (orig_image, "gimp-comment"); + if (image_comment && strlen (image_comment)) { - case GIMP_RUN_INTERACTIVE: - case GIMP_RUN_WITH_LAST_VALS: - gimp_ui_init (PLUG_IN_BINARY, FALSE); - - export = gimp_export_image (&image_ID, &drawable_ID, "JPEG", - GIMP_EXPORT_CAN_HANDLE_RGB | - GIMP_EXPORT_CAN_HANDLE_GRAY); - - switch (export) - { - case GIMP_EXPORT_EXPORT: - { - gchar *tmp = g_filename_from_utf8 (_("Export Preview"), -1, - NULL, NULL, NULL); - if (tmp) - { - gimp_image_set_filename (image_ID, tmp); - g_free (tmp); - } - - display_ID = -1; - } - break; - - case GIMP_EXPORT_IGNORE: - break; - - case GIMP_EXPORT_CANCEL: - values[0].data.d_status = GIMP_PDB_CANCEL; - return; - break; - } - break; - - default: - break; - } - - /* Initialize with hardcoded defaults */ - load_defaults (); - - /* Override the defaults with preferences. */ - metadata = gimp_image_metadata_save_prepare (orig_image_ID, - "image/jpeg", - &metadata_flags); - jsvals.save_exif = (metadata_flags & GIMP_METADATA_SAVE_EXIF) != 0; - jsvals.save_xmp = (metadata_flags & GIMP_METADATA_SAVE_XMP) != 0; - jsvals.save_iptc = (metadata_flags & GIMP_METADATA_SAVE_IPTC) != 0; - jsvals.save_thumbnail = (metadata_flags & GIMP_METADATA_SAVE_THUMBNAIL) != 0; - jsvals.save_profile = (metadata_flags & GIMP_METADATA_SAVE_COLOR_PROFILE) != 0; - - parasite = gimp_image_get_parasite (orig_image_ID, "gimp-comment"); - if (parasite) - { - image_comment = g_strndup (gimp_parasite_data (parasite), - gimp_parasite_data_size (parasite)); + parasite = gimp_parasite_new ("gimp-comment", + GIMP_PARASITE_PERSISTENT, + strlen (image_comment) + 1, + image_comment); + gimp_image_attach_parasite (orig_image, parasite); gimp_parasite_free (parasite); } - /* Override preferences from JPG export defaults (if saved). */ - load_parasite (); + parasite = gimp_parasite_new ("jpeg-save-options", + 0, sizeof (jsvals), &jsvals); + gimp_image_attach_parasite (orig_image, parasite); + gimp_parasite_free (parasite); - switch (run_mode) - { - case GIMP_RUN_NONINTERACTIVE: - /* Make sure all the arguments are there! */ - /* pw - added two more progressive and comment */ - /* sg - added subsampling, preview, baseline, restarts and DCT */ - if (nparams != 14) - { - status = GIMP_PDB_CALLING_ERROR; - } - else - { - /* Once the PDB gets default parameters, remove this hack */ - if (param[5].data.d_float >= 0.01) - { - jsvals.quality = 100.0 * param[5].data.d_float; - jsvals.smoothing = param[6].data.d_float; - jsvals.optimize = param[7].data.d_int32; - jsvals.progressive = param[8].data.d_int32; - jsvals.baseline = param[11].data.d_int32; - jsvals.subsmp = param[10].data.d_int32; - jsvals.restart = param[12].data.d_int32; - jsvals.dct = param[13].data.d_int32; - - /* free up the default -- wasted some effort earlier */ - g_free (image_comment); - image_comment = g_strdup (param[9].data.d_string); - } - - jsvals.preview = FALSE; - - if (jsvals.quality < 0.0 || jsvals.quality > 100.0) - status = GIMP_PDB_CALLING_ERROR; - else if (jsvals.smoothing < 0.0 || jsvals.smoothing > 1.0) - status = GIMP_PDB_CALLING_ERROR; - else if (jsvals.subsmp < 0 || jsvals.subsmp > 3) - status = GIMP_PDB_CALLING_ERROR; - else if (jsvals.dct < 0 || jsvals.dct > 2) - status = GIMP_PDB_CALLING_ERROR; - } - break; - - case GIMP_RUN_INTERACTIVE: - case GIMP_RUN_WITH_LAST_VALS: - /* restore the values found when loading the file (if available) */ - jpeg_restore_original_settings (orig_image_ID, - &orig_quality, - &orig_subsmp, - &num_quant_tables); - - /* load up the previously used values (if file was saved once) */ - parasite = gimp_image_get_parasite (orig_image_ID, - "jpeg-save-options"); - if (parasite) - { - const JpegSaveVals *save_vals = gimp_parasite_data (parasite); - - jsvals.quality = save_vals->quality; - jsvals.smoothing = save_vals->smoothing; - jsvals.optimize = save_vals->optimize; - jsvals.progressive = save_vals->progressive; - jsvals.baseline = save_vals->baseline; - jsvals.subsmp = save_vals->subsmp; - jsvals.restart = save_vals->restart; - jsvals.dct = save_vals->dct; - 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; - jsvals.save_iptc = save_vals->save_iptc; - jsvals.use_orig_quality = save_vals->use_orig_quality; - - gimp_parasite_free (parasite); - } - else - { - /* We are called with GIMP_RUN_WITH_LAST_VALS but this image - * doesn't have a "jpeg-save-options" parasite. It's better - * to prompt the user with a dialog now so that she has control - * over the JPEG encoding parameters. - */ - run_mode = GIMP_RUN_INTERACTIVE; - - /* If this image was loaded from a JPEG file and has not been - * saved yet, try to use some of the settings from the - * original file if they are better than the default values. - */ - if (orig_quality > jsvals.quality) - { - jsvals.quality = orig_quality; - } - - /* Skip changing subsampling to original if we already have best - * setting or if original have worst setting */ - if (!(jsvals.subsmp == JPEG_SUBSAMPLING_1x1_1x1_1x1 || - orig_subsmp == JPEG_SUBSAMPLING_2x2_1x1_1x1)) - { - jsvals.subsmp = orig_subsmp; - } - - if (orig_quality == jsvals.quality && - orig_subsmp == jsvals.subsmp) - { - jsvals.use_orig_quality = TRUE; - } - } - break; - } - - if (run_mode == GIMP_RUN_INTERACTIVE) - { - if (jsvals.preview) - { - /* we freeze undo saving so that we can avoid sucking up - * tile cache with our unneeded preview steps. */ - gimp_image_undo_freeze (image_ID); - - undo_touched = TRUE; - } - - /* prepare for the preview */ - preview_image_ID = image_ID; - orig_image_ID_global = orig_image_ID; - drawable_ID_global = drawable_ID; - - /* First acquire information with a dialog */ - status = (save_dialog () ? GIMP_PDB_SUCCESS : GIMP_PDB_CANCEL); - - if (undo_touched) - { - /* thaw undo saving and flush the displays to have them - * reflect the current shortcuts */ - gimp_image_undo_thaw (image_ID); - gimp_displays_flush (); - } - } - - if (status == GIMP_PDB_SUCCESS) - { - if (! save_image (g_file_get_path (file), - image_ID, drawable_ID, orig_image_ID, FALSE, - &error)) - { - status = GIMP_PDB_EXECUTION_ERROR; - } - } - - if (export == GIMP_EXPORT_EXPORT) - { - /* If the image was exported, delete the new display. */ - /* This also deletes the image. - */ - - if (display_ID != -1) - gimp_display_delete (display_ID); - else - gimp_image_delete (image_ID); - } - - if (status == GIMP_PDB_SUCCESS) - { - /* pw - now we need to change the defaults to be whatever - * was used to save this image. Dump the old parasites - * and add new ones. - */ - - gimp_image_detach_parasite (orig_image_ID, "gimp-comment"); - if (image_comment && strlen (image_comment)) - { - parasite = gimp_parasite_new ("gimp-comment", - GIMP_PARASITE_PERSISTENT, - strlen (image_comment) + 1, - image_comment); - gimp_image_attach_parasite (orig_image_ID, parasite); - gimp_parasite_free (parasite); - } - - parasite = gimp_parasite_new ("jpeg-save-options", - 0, sizeof (jsvals), &jsvals); - gimp_image_attach_parasite (orig_image_ID, parasite); - gimp_parasite_free (parasite); - - /* write metadata */ - - if (metadata) - { - gimp_metadata_set_bits_per_sample (metadata, 8); - - if (jsvals.save_exif) - metadata_flags |= GIMP_METADATA_SAVE_EXIF; - else - metadata_flags &= ~GIMP_METADATA_SAVE_EXIF; - - if (jsvals.save_xmp) - metadata_flags |= GIMP_METADATA_SAVE_XMP; - else - metadata_flags &= ~GIMP_METADATA_SAVE_XMP; - - if (jsvals.save_iptc) - metadata_flags |= GIMP_METADATA_SAVE_IPTC; - else - metadata_flags &= ~GIMP_METADATA_SAVE_IPTC; - - if (jsvals.save_thumbnail) - metadata_flags |= GIMP_METADATA_SAVE_THUMBNAIL; - else - metadata_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL; - - if (jsvals.save_profile) - metadata_flags |= GIMP_METADATA_SAVE_COLOR_PROFILE; - else - metadata_flags &= ~GIMP_METADATA_SAVE_COLOR_PROFILE; - - gimp_image_metadata_save_finish (orig_image_ID, - "image/jpeg", - metadata, metadata_flags, - file, NULL); - } - } + /* write metadata */ if (metadata) - g_object_unref (metadata); - } - else - { - status = GIMP_PDB_CALLING_ERROR; + { + gimp_metadata_set_bits_per_sample (metadata, 8); + + if (jsvals.save_exif) + metadata_flags |= GIMP_METADATA_SAVE_EXIF; + else + metadata_flags &= ~GIMP_METADATA_SAVE_EXIF; + + if (jsvals.save_xmp) + metadata_flags |= GIMP_METADATA_SAVE_XMP; + else + metadata_flags &= ~GIMP_METADATA_SAVE_XMP; + + if (jsvals.save_iptc) + metadata_flags |= GIMP_METADATA_SAVE_IPTC; + else + metadata_flags &= ~GIMP_METADATA_SAVE_IPTC; + + if (jsvals.save_thumbnail) + metadata_flags |= GIMP_METADATA_SAVE_THUMBNAIL; + else + metadata_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL; + + if (jsvals.save_profile) + metadata_flags |= GIMP_METADATA_SAVE_COLOR_PROFILE; + else + metadata_flags &= ~GIMP_METADATA_SAVE_COLOR_PROFILE; + + gimp_image_metadata_save_finish (orig_image, + "image/jpeg", + metadata, metadata_flags, + file, NULL); + } } - if (status != GIMP_PDB_SUCCESS && error) - { - *nreturn_vals = 2; - values[1].type = GIMP_PDB_STRING; - values[1].data.d_string = error->message; - } + if (metadata) + g_object_unref (metadata); - values[0].data.d_status = status; + g_free (filename); + + return gimp_procedure_new_return_values (procedure, status, error); } /* diff --git a/plug-ins/file-jpeg/jpeg.h b/plug-ins/file-jpeg/jpeg.h index 0bf9af0cf3..ca0710c948 100644 --- a/plug-ins/file-jpeg/jpeg.h +++ b/plug-ins/file-jpeg/jpeg.h @@ -51,11 +51,11 @@ typedef enum JPEG_SUBSAMPLING_1x2_1x1_1x1 = 3 } JpegSubsampling; -extern gint32 volatile preview_image_ID; -extern gint32 preview_layer_ID; +extern GimpImage * volatile preview_image; +extern GimpLayer * preview_layer; extern gboolean undo_touched; extern gboolean load_interactive; -extern gint32 display_ID; +extern GimpDisplay *display; extern gchar *image_comment; extern gint orig_quality; extern JpegSubsampling orig_subsmp;