Commit 1793a085 authored by Michael Natterer's avatar Michael Natterer 😴

plug-ins: port file-png to GimpProcedureConfig and use propwidgets

Remove the save dialog's builder file and construct the dialog
manually, which is actually less and more obvious code thanks to
propwidgets, which are not suited for a builder GUI.

I guess file-png-save counts as a real test for the new procedure
config stuff, and it seems to work nicely. The only thing that's a bit
ugly is the GimpMetadata integration which doesn't exist yet.
parent 8b53d25e
Pipeline #117829 passed with stages
in 12 minutes and 7 seconds
......@@ -48,32 +48,24 @@
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include <png.h> /* PNG library definitions */
#include <png.h>
#include "libgimp/stdplugins-intl.h"
/*
* Constants...
*/
#define LOAD_PROC "file-png-load"
#define SAVE_PROC "file-png-save"
#define PLUG_IN_BINARY "file-png"
#define PLUG_IN_ROLE "gimp-file-png"
#define LOAD_PROC "file-png-load"
#define SAVE_PROC "file-png-save"
#define PLUG_IN_BINARY "file-png"
#define PLUG_IN_ROLE "gimp-file-png"
#define PLUG_IN_VERSION "1.3.4 - 03 September 2002"
#define SCALE_WIDTH 125
#define PLUG_IN_VERSION "1.3.4 - 03 September 2002"
#define SCALE_WIDTH 125
#define DEFAULT_GAMMA 2.20
#define DEFAULT_GAMMA 2.20
#define PNG_DEFAULTS_PARASITE "png-save-defaults"
/*
* Structures...
*/
typedef enum _PngExportformat {
typedef enum _PngExportformat
{
PNG_FORMAT_AUTO = 0,
PNG_FORMAT_RGB8,
PNG_FORMAT_GRAY8,
......@@ -85,60 +77,6 @@ typedef enum _PngExportformat {
PNG_FORMAT_GRAYA16
} PngExportFormat;
typedef struct
{
gboolean interlaced;
gboolean bkgd;
gboolean gama;
gboolean offs;
gboolean phys;
gboolean time;
gboolean comment;
gboolean save_transp_pixels;
gint compression_level;
gboolean save_exif;
gboolean save_xmp;
gboolean save_iptc;
gboolean save_thumbnail;
gboolean save_profile;
PngExportFormat export_format;
}
PngSaveVals;
typedef struct
{
gboolean run;
GtkWidget *interlaced;
GtkWidget *bkgd;
GtkWidget *gama;
GtkWidget *offs;
GtkWidget *phys;
GtkWidget *time;
GtkWidget *comment;
GtkWidget *pixelformat;
GtkWidget *save_transp_pixels;
GtkAdjustment *compression_level;
GtkWidget *save_exif;
GtkWidget *save_xmp;
GtkWidget *save_iptc;
GtkWidget *save_thumbnail;
GtkWidget *save_profile;
}
PngSaveGui;
/* These are not saved or restored. */
typedef struct
{
gboolean has_trns;
png_bytep trans;
int num_trans;
gboolean has_plte;
png_colorp palette;
int num_palette;
}
PngGlobals;
typedef struct _Png Png;
typedef struct _PngClass PngClass;
......@@ -176,42 +114,37 @@ static GimpValueArray * png_save (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
static GimpImage * load_image (GFile *file,
gboolean interactive,
gboolean *resolution_loaded,
gboolean *profile_loaded,
GError **error);
static gboolean save_image (GFile *file,
GimpImage *image,
GimpDrawable *drawable,
GimpImage *orig_image,
gboolean *profile_saved,
GError **error);
static int respin_cmap (png_structp pp,
png_infop info,
guchar *remap,
GimpImage *image,
GimpDrawable *drawable);
static GimpImage * load_image (GFile *file,
gboolean interactive,
gboolean *resolution_loaded,
gboolean *profile_loaded,
GError **error);
static gboolean save_image (GFile *file,
GimpImage *image,
GimpDrawable *drawable,
GimpImage *orig_image,
GObject *config,
gboolean *profile_saved,
GError **error);
static gboolean save_dialog (GimpImage *image,
gboolean alpha);
static int respin_cmap (png_structp pp,
png_infop info,
guchar *remap,
GimpImage *image,
GimpDrawable *drawable);
static void save_dialog_response (GtkWidget *widget,
gint response_id,
gpointer data);
static gboolean save_dialog (GimpImage *image,
GimpProcedure *procedure,
GObject *config,
gboolean alpha);
static gboolean offsets_dialog (gint offset_x,
gint offset_y);
static gboolean offsets_dialog (gint offset_x,
gint offset_y);
static gboolean ia_has_transparent_pixels (GeglBuffer *buffer);
static gboolean ia_has_transparent_pixels (GeglBuffer *buffer);
static gint find_unused_ia_color (GeglBuffer *buffer,
gint *colors);
static void load_parasite (void);
static void save_parasite (void);
static void load_gui_defaults (PngSaveGui *pg);
static gint find_unused_ia_color (GeglBuffer *buffer,
gint *colors);
G_DEFINE_TYPE (Png, png, GIMP_TYPE_PLUG_IN)
......@@ -219,28 +152,6 @@ G_DEFINE_TYPE (Png, png, GIMP_TYPE_PLUG_IN)
GIMP_MAIN (PNG_TYPE)
static const PngSaveVals defaults =
{
FALSE,
TRUE,
FALSE,
FALSE,
TRUE,
TRUE,
TRUE,
TRUE,
9,
FALSE, /* save exif */
FALSE, /* save xmp */
FALSE, /* save iptc */
TRUE, /* save thumbnail */
PNG_FORMAT_AUTO
};
static PngSaveVals pngvals;
static PngGlobals pngg;
static void
png_class_init (PngClass *klass)
{
......@@ -328,8 +239,8 @@ png_create_procedure (GimpPlugIn *plug_in,
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
"png");
GIMP_PROC_ARG_BOOLEAN (procedure, "interlace",
"Interlace",
GIMP_PROC_ARG_BOOLEAN (procedure, "interlaced",
"Interlaced",
"Use Adam7 interlacing?",
FALSE,
G_PARAM_READWRITE);
......@@ -376,11 +287,48 @@ png_create_procedure (GimpPlugIn *plug_in,
TRUE,
G_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "save-trans",
"Save trans",
GIMP_PROC_ARG_BOOLEAN (procedure, "save-transparent",
"Save transparent",
"Preserve color of transparent pixels?",
TRUE,
G_PARAM_READWRITE);
GIMP_PROC_AUX_ARG_INT (procedure, "format",
"Format",
"PNG export format",
PNG_FORMAT_AUTO, PNG_FORMAT_GRAYA16,
PNG_FORMAT_AUTO,
G_PARAM_READWRITE);
GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-exif",
"Save Exif",
"Save Exif",
gimp_export_exif (),
G_PARAM_READWRITE);
GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-xmp",
"Save XMP",
"Save XMP",
gimp_export_xmp (),
G_PARAM_READWRITE);
GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-iptc",
"Save IPTC",
"Save IPTC",
gimp_export_iptc (),
G_PARAM_READWRITE);
GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-thumbnail",
"Save thumbnail",
"Save thumbnail",
TRUE,
G_PARAM_READWRITE);
GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "save-profile",
"Save profile",
"Save color profile",
gimp_export_color_profile (),
G_PARAM_READWRITE);
}
return procedure;
......@@ -465,13 +413,12 @@ png_save (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data)
{
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpMetadata *metadata;
GimpMetadataSaveFlags metadata_flags;
GimpImage *orig_image;
GimpExportReturn export = GIMP_EXPORT_CANCEL;
gboolean alpha;
GError *error = NULL;
GimpProcedureConfig *config;
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpExportReturn export = GIMP_EXPORT_CANCEL;
GimpImage *orig_image;
gboolean alpha;
GError *error = NULL;
INIT_I18N ();
gegl_init (NULL, NULL);
......@@ -499,9 +446,10 @@ png_save (GimpProcedure *procedure,
break;
}
/* Initialize with hardcoded defaults */
pngvals = defaults;
config = gimp_procedure_create_config (procedure);
gimp_procedure_config_begin_run (config, orig_image, run_mode, args);
#if 0
/* Override the defaults with preferences. */
metadata = gimp_image_metadata_save_prepare (orig_image,
"image/png",
......@@ -511,83 +459,71 @@ png_save (GimpProcedure *procedure,
pngvals.save_iptc = (metadata_flags & GIMP_METADATA_SAVE_IPTC) != 0;
pngvals.save_thumbnail = (metadata_flags & GIMP_METADATA_SAVE_THUMBNAIL) != 0;
pngvals.save_profile = (metadata_flags & GIMP_METADATA_SAVE_COLOR_PROFILE) != 0;
#endif
alpha = gimp_drawable_has_alpha (drawable);
/* Override preferences from PNG export defaults (if saved). */
/* FIXME this is currently broken for NONINTERACTICE until we have
* new default value handling, if simply gets overwritten below
/* If the image has no transparency, then there is usually no need
* to save a bKGD chunk. For more information, see:
* http://bugzilla.gnome.org/show_bug.cgi?id=92395
*/
load_parasite ();
if (! alpha)
g_object_set (config,
"bkgd", FALSE,
NULL);
switch (run_mode)
if (run_mode == GIMP_RUN_INTERACTIVE)
{
case GIMP_RUN_INTERACTIVE:
/* Finally possibly retrieve data from previous run. */
gimp_get_data (SAVE_PROC, &pngvals);
alpha = gimp_drawable_has_alpha (drawable);
/* If the image has no transparency, then there is usually
* no need to save a bKGD chunk. For more information, see:
* http://bugzilla.gnome.org/show_bug.cgi?id=92395
*/
if (! alpha)
pngvals.bkgd = FALSE;
/* Then acquire information with a dialog...
*/
if (! save_dialog (orig_image, alpha))
if (! save_dialog (orig_image, procedure, G_OBJECT (config), alpha))
status = GIMP_PDB_CANCEL;
break;
case GIMP_RUN_NONINTERACTIVE:
pngvals.interlaced = GIMP_VALUES_GET_BOOLEAN (args, 0);
pngvals.compression_level = GIMP_VALUES_GET_INT (args, 1);
pngvals.bkgd = GIMP_VALUES_GET_BOOLEAN (args, 2);
pngvals.gama = GIMP_VALUES_GET_BOOLEAN (args, 3);
pngvals.offs = GIMP_VALUES_GET_BOOLEAN (args, 4);
pngvals.phys = GIMP_VALUES_GET_BOOLEAN (args, 5);
pngvals.time = GIMP_VALUES_GET_BOOLEAN (args, 6);
pngvals.comment = GIMP_VALUES_GET_BOOLEAN (args, 7);
pngvals.save_transp_pixels = GIMP_VALUES_GET_BOOLEAN (args, 8);
break;
case GIMP_RUN_WITH_LAST_VALS:
/* possibly retrieve data */
gimp_get_data (SAVE_PROC, &pngvals);
break;
default:
break;
}
if (status == GIMP_PDB_SUCCESS)
{
gboolean profile_saved = FALSE;
if (save_image (file,
image, drawable, orig_image,
if (save_image (file, image, drawable, orig_image, G_OBJECT (config),
&profile_saved, &error))
{
GimpMetadata *metadata;
GimpMetadataSaveFlags metadata_flags;
metadata = gimp_image_metadata_save_prepare (orig_image,
"image/png",
&metadata_flags);
if (metadata)
{
gboolean save_exif;
gboolean save_xmp;
gboolean save_iptc;
gboolean save_thumbnail;
g_object_get (config,
"save-exif", &save_exif,
"save-xmp", &save_xmp,
"save-iptc", &save_iptc,
"save-thumbnail", &save_thumbnail,
NULL);
gimp_metadata_set_bits_per_sample (metadata, 8);
if (pngvals.save_exif)
if (save_exif)
metadata_flags |= GIMP_METADATA_SAVE_EXIF;
else
metadata_flags &= ~GIMP_METADATA_SAVE_EXIF;
if (pngvals.save_xmp)
if (save_xmp)
metadata_flags |= GIMP_METADATA_SAVE_XMP;
else
metadata_flags &= ~GIMP_METADATA_SAVE_XMP;
if (pngvals.save_iptc)
if (save_iptc)
metadata_flags |= GIMP_METADATA_SAVE_IPTC;
else
metadata_flags &= ~GIMP_METADATA_SAVE_IPTC;
if (pngvals.save_thumbnail)
if (save_thumbnail)
metadata_flags |= GIMP_METADATA_SAVE_THUMBNAIL;
else
metadata_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL;
......@@ -604,9 +540,11 @@ png_save (GimpProcedure *procedure,
"image/png",
metadata, metadata_flags,
file, NULL);
g_object_unref (metadata);
}
gimp_set_data (SAVE_PROC, &pngvals, sizeof (pngvals));
gimp_procedure_config_end_run (config, orig_image, run_mode);
}
else
{
......@@ -614,12 +552,11 @@ png_save (GimpProcedure *procedure,
}
}
g_object_unref (config);
if (export == GIMP_EXPORT_EXPORT)
gimp_image_delete (image);
if (metadata)
g_object_unref (metadata);
return gimp_procedure_new_return_values (procedure, status, error);
}
......@@ -1162,10 +1099,9 @@ load_image (GFile *file,
pixel,
GEGL_AUTO_ROWSTRIDE);
gimp_progress_update
(((gdouble) pass +
(gdouble) end / (gdouble) height) /
(gdouble) num_passes);
gimp_progress_update (((gdouble) pass +
(gdouble) end / (gdouble) height) /
(gdouble) num_passes);
}
}
......@@ -1325,11 +1261,25 @@ offsets_dialog (gint offset_x,
* 'save_image ()' - Export the specified image to a PNG file.
*/
typedef struct
{
gboolean has_trns;
png_bytep trans;
int num_trans;
gboolean has_plte;
png_colorp palette;
int num_palette;
}
PngGlobals;
static PngGlobals pngg;
static gboolean
save_image (GFile *file,
GimpImage *image,
GimpDrawable *drawable,
GimpImage *orig_image,
GObject *config,
gboolean *profile_saved,
GError **error)
{
......@@ -1370,6 +1320,40 @@ save_image (GFile *file,
png_textp text = NULL;
gboolean save_interlaced;
gboolean save_bkgd;
gboolean save_gama;
gboolean save_offs;
gboolean save_phys;
gboolean save_time;
gboolean save_comment;
gboolean save_transp_pixels;
gint compression_level;
PngExportFormat export_format;
gboolean save_exif;
gboolean save_xmp;
gboolean save_iptc;
gboolean save_thumbnail;
gboolean save_profile;
g_object_get (config,
"interlaced", &save_interlaced,
"bkgd", &save_bkgd,
"gama", &save_gama,
"offs", &save_offs,
"phys", &save_phys,
"time", &save_time,
"comment", &save_comment,
"save-transparent", &save_transp_pixels,
"compression", &compression_level,
"format", &export_format,
"save-exif", &save_exif,
"save-xmp", &save_xmp,
"save-iptc", &save_iptc,
"save-thumbnail", &save_thumbnail,
"save-profile", &save_profile,
NULL);
out_linear = FALSE;
space = gimp_drawable_get_format (drawable);
#if defined(PNG_iCCP_SUPPORTED)
......@@ -1380,16 +1364,16 @@ save_image (GFile *file,
* - when export from 8-bit storage: follow the storage TRC.
* - when converting high bit depth to 8-bit: export as sRGB.
*/
if (pngvals.save_profile)
if (save_profile)
{
profile = gimp_image_get_color_profile (orig_image);
if (profile ||
pngvals.export_format == PNG_FORMAT_AUTO ||
pngvals.export_format == PNG_FORMAT_RGB16 ||
pngvals.export_format == PNG_FORMAT_RGBA16 ||
pngvals.export_format == PNG_FORMAT_GRAY16 ||
pngvals.export_format == PNG_FORMAT_GRAYA16 ||
export_format == PNG_FORMAT_AUTO ||
export_format == PNG_FORMAT_RGB16 ||
export_format == PNG_FORMAT_RGBA16 ||
export_format == PNG_FORMAT_GRAY16 ||
export_format == PNG_FORMAT_GRAYA16 ||
gimp_image_get_precision (image) == GIMP_PRECISION_U8_LINEAR ||
gimp_image_get_precision (image) == GIMP_PRECISION_U8_NON_LINEAR ||
gimp_image_get_precision (image) == GIMP_PRECISION_U8_PERCEPTUAL)
......@@ -1531,7 +1515,7 @@ save_image (GFile *file,
for (i = 0; i < 256; i++)
remap[i] = i;
if (pngvals.export_format == PNG_FORMAT_AUTO)
if (export_format == PNG_FORMAT_AUTO)
{
/*
* Set color type and remember bytes per pixel count
......@@ -1634,7 +1618,7 @@ save_image (GFile *file,
}
else
{
switch (pngvals.export_format)
switch (export_format)
{
case PNG_FORMAT_RGB8:
color_type = PNG_COLOR_TYPE_RGB;
......@@ -1713,7 +1697,7 @@ save_image (GFile *file,
/* Note: png_set_IHDR() must be called before any other png_set_*()
functions. */
png_set_IHDR (pp, info, width, height, bit_depth, color_type,
pngvals.interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
save_interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
......@@ -1725,12 +1709,12 @@ save_image (GFile *file,
/* Set the compression level */
png_set_compression_level (pp, pngvals.compression_level);
png_set_compression_level (pp, compression_level);
/* All this stuff is optional extras, if the user is aiming for smallest
possible file size she can turn them all off */
if (pngvals.bkgd)
if (save_bkgd)
{
GimpRGB color;
guchar red, green, blue;
......@@ -1746,7 +1730,7 @@ save_image (GFile *file,
png_set_bKGD (pp, info, &background);
}
if (pngvals.gama)
if (save_gama)
{
GimpParasite *parasite;
gdouble gamma = 1.0 / DEFAULT_GAMMA;
......@@ -1761,21 +1745,21 @@ save_image (GFile *file,
png_set_gAMA (pp, info, gamma);
}
if (pngvals.offs)
if (save_offs)
{
gimp_drawable_offsets (drawable, &offx, &offy);
if (offx != 0 || offy != 0)
png_set_oFFs (pp, info, offx, offy, PNG_OFFSET_PIXEL);
}
if (pngvals.phys)
if (save_phys)
{
gimp_image_get_resolution (orig_image, &xres, &yres);
png_set_pHYs (pp, info, RINT (xres / 0.0254), RINT (yres / 0.0254),
PNG_RESOLUTION_METER);
}
if (pngvals.time)
if (save_time)
{
cutime = time (NULL); /* time right NOW */
gmt = gmtime (&cutime);
......@@ -1790,7 +1774,7 @@ save_image (GFile *file,
}
#if defined(PNG_iCCP_SUPPORTED)
if (pngvals.save_profile)
if (save_profile)
{
GimpParasite *parasite;
gchar *profile_name = NULL;
......@@ -1826,7 +1810,7 @@ save_image (GFile *file,
#define COMPRESSION_WORTHY_LENGTH 200
#endif
if (pngvals.comment)
if (save_comment)
{
GimpParasite *parasite;
gsize text_length = 0;
......@@ -1927,7 +1911,7 @@ save_image (GFile *file,
* Turn on interlace handling...
*/
if (pngvals.interlaced)
if (save_interlaced)
num_passes = png_set_interlace_handling (pp);
else
num_passes = 1;
......@@ -1972,7 +1956,7 @@ save_image (GFile *file,
/* If we are with a RGBA image and have to pre-multiply the
alpha channel */
if (bpp == 4 && ! pngvals.save_transp_pixels)
if (bpp == 4 && ! save_transp_pixels)
{
for (i = 0; i < num; ++i)
{
......@@ -1986,7 +1970,7 @@ save_image (GFile *file,
}
}
if (bpp == 8 && ! pngvals.save_transp_pixels)
if (bpp == 8 && ! save_transp_pixels)
{
for (i = 0; i < num; ++i)
{
......@@ -2104,9 +2088,10 @@ ia_has_transparent_pixels (GeglBuffer *buffer)
return FALSE;
}
/* Try to find a color in the palette which isn't actually
* used in the image, so that we can use it as the transparency
* index. Taken from gif.c */
/* Try to find a color in the palette which isn't actually used in the
* image, so that we can use it as the transparency index. Taken from
* gif.c
*/
static gint
find_unused_ia_color (GeglBuffer *buffer,
gint *colors)
......@@ -2149,7 +2134,8 @@ find_unused_ia_color (GeglBuffer *buffer,
/* If there is still some room at the end of the palette, increment
* the number of colors in the image and assign a transparent pixel
* there. */
* there.
*/
if ((*colors) < 256)
{
(*colors)++;
......@@ -2166,7 +2152,6 @@ find_unused_ia_color (GeglBuffer *buffer,
return -1;
}
static int
respin_cmap (png_structp pp,
png_infop info,
......@@ -2183,8 +2168,7 @@ respin_cmap (png_structp pp,
before = gimp_image_get_colormap (image, &colors);
buffer = gimp_drawable_get_buffer (drawable);
/*
* Make sure there is something in the colormap.
/* Make sure there is something in the colormap.
*/
if (colors == 0)
{
......@@ -2194,8 +2178,9 @@ respin_cmap (png_structp pp,
colors = 1;
}
/* Try to find an entry which isn't actually used in the
image, for a transparency index. */
/* Try to find an entry which isn't actually used in the image, for
* a transparency index.
*/
if (ia_has_transparent_pixels (buffer))
{
......@@ -2203,7 +2188,8 @@ respin_cmap (png_structp pp,
if (transparent != -1) /* we have a winner for a transparent
* index - do like gif2png and swap
* index 0 and index transparent */
* index 0 and index transparent
*/
{
static png_color palette[256];
gint i;
......@@ -2213,9 +2199,10 @@ respin_cmap (png_structp pp,
pngg.trans = trans;
pngg.num_trans = 1;
/* Transform all pixels with a value = transparent to
* 0 and vice versa to compensate for re-ordering in palette
* due to png_set_tRNS() */
/* Transform all pixels with a value = transparent to 0 and
* vice versa to compensate for re-ordering in palette due
* to png_set_tRNS()
*/
remap[0] = transparent;
for (i = 1; i <= transparent; i++)
......@@ -2223,7 +2210,8 @@ respin_cmap (png_structp pp,
/* Copy from index 0 to index transparent - 1 to index 1 to
* transparent of after, then from transparent+1 to colors-1
* unchanged, and finally from index transparent to index 0. */
* unchanged, and finally from index transparent to index 0.
*/
for (i = 0; i < colors; i++)
{
......@@ -2240,7 +2228,8 @@ respin_cmap (png_structp pp,
else
{
/* Inform the user that we couldn't losslessly save the
* transparency & just use the full palette */
* transparency & just use the full palette
*/
g_message (_("Couldn't losslessly save transparency, "
"saving opacity instead."));