gimp/plug-ins/common/png.c

1384 lines
39 KiB
C
Raw Normal View History

1997-11-25 06:05:25 +08:00
/*
* "$Id$"
*
* Portable Network Graphics (PNG) plug-in for The GIMP -- an image
* manipulation program
*
* Copyright 1997-1998 Michael Sweet (mike@easysw.com) and
1997-11-25 06:05:25 +08:00
* Daniel Skarda (0rfelyus@atrey.karlin.mff.cuni.cz).
* and 1999-2000 Nick Lamb (njl195@zepler.org.uk)
1997-11-25 06:05:25 +08:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1997-11-25 06:05:25 +08:00
*
* Contents:
*
* main() - Main entry - just call gimp_main()...
* query() - Respond to a plug-in query...
* run() - Run the plug-in...
* load_image() - Load a PNG image into a new image window.
* respin_cmap() - Re-order a Gimp colormap for PNG tRNS
1997-11-25 06:05:25 +08:00
* save_image() - Save the specified image to a PNG file.
* save_ok_callback() - Destroy the save dialog and save the image.
* save_compression_callback() - Update the image compression level.
* save_interlace_update() - Update the interlacing option.
* save_dialog() - Pop up the save dialog.
*
* Revision History:
*
1999-06-29 14:15:15 +08:00
* see ChangeLog
1997-11-25 06:05:25 +08:00
*/
#include "config.h"
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
#include <errno.h>
1997-11-25 06:05:25 +08:00
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
1997-11-25 06:05:25 +08:00
#include <gtk/gtk.h>
1997-11-25 06:05:25 +08:00
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
1997-11-25 06:05:25 +08:00
#include <png.h> /* PNG library definitions */
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
configure.in removed tips files, AC_SUBST GIMP_PLUGINS and GIMP_MODULES so * configure.in * Makefile.am: removed tips files, AC_SUBST GIMP_PLUGINS and GIMP_MODULES so you can easily skip those parts of the build * acinclude.m4 * config.sub * config.guess * ltconfig * ltmain.sh: libtool 1.3.2 * app/fileops.c: shuffle #includes to avoid warning about MIN and MAX [ The following is a big i18n patch from David Monniaux <david.monniaux@ens.fr> ] * tips/gimp_conseils.fr.txt * tips/gimp_tips.txt * tips/Makefile.am * configure.in: moved tips to separate dir * po-plugins: new dir for plug-in translation files * configure.in: add po-plugins dir and POTFILES processing * app/boundary.c * app/brightness_contrast.c * app/by_color_select.c * app/color_balance.c * app/convert.c * app/curves.c * app/free_select.c * app/gdisplay.c * app/gimpimage.c * app/gimpunit.c * app/gradient.c * app/gradient_select.c * app/install.c * app/session.c: various i18n tweaks * app/tips_dialog.c: localize tips filename * libgimp/gimpunit.c * libgimp/gimpunitmenu.c: #include "config.h" * plug-ins/CEL * plug-ins/CML_explorer * plug-ins/Lighting * plug-ins/apply_lens * plug-ins/autostretch_hsv * plug-ins/blur * plug-ins/bmp * plug-ins/borderaverage * plug-ins/bumpmap * plug-ins/bz2 * plug-ins/checkerboard * plug-ins/colorify * plug-ins/compose * plug-ins/convmatrix * plug-ins/cubism * plug-ins/depthmerge * plug-ins/destripe * plug-ins/gif * plug-ins/gifload * plug-ins/jpeg * plug-ins/mail * plug-ins/oilify * plug-ins/png * plug-ins/print * plug-ins/ps * plug-ins/xbm * plug-ins/xpm * plug-ins/xwd: plug-in i18n stuff -Yosh
1999-05-30 00:35:47 +08:00
#include "libgimp/stdplugins-intl.h"
1997-11-25 06:05:25 +08:00
1997-11-25 06:05:25 +08:00
/*
* Constants...
*/
#define PLUG_IN_VERSION "1.3.4 - 03 September 2002"
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
#define SCALE_WIDTH 125
1997-11-25 06:05:25 +08:00
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
#define DEFAULT_GAMMA 2.20
1997-11-25 06:05:25 +08:00
/*
* Structures...
*/
typedef struct
{
gint interlaced;
gint compression_level;
gint bkgd;
gint gama;
gint offs;
gint phys;
gint time;
}
PngSaveVals;
1997-11-25 06:05:25 +08:00
/*
* Local functions...
*/
static void query (void);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
static gint32 load_image (const gchar *filename);
static gint save_image (const gchar *filename,
gint32 image_ID,
gint32 drawable_ID,
gint32 orig_image_ID);
static void respin_cmap (png_structp pp,
png_infop info,
guchar * remap,
gint32 image_ID,
GimpDrawable * drawable);
static gint save_dialog (void);
static void save_ok_callback (GtkWidget * widget,
gpointer data);
static int find_unused_ia_colour (guchar * pixels,
int numpixels,
int *colors);
1997-11-25 06:05:25 +08:00
/*
* Globals...
*/
GimpPlugInInfo PLUG_IN_INFO = {
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
1997-11-25 06:05:25 +08:00
};
PngSaveVals pngvals = {
FALSE,
6,
TRUE, FALSE, FALSE, TRUE, TRUE
1997-11-25 06:05:25 +08:00
};
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
static gboolean runme = FALSE;
1997-11-25 06:05:25 +08:00
/*
* 'main()' - Main entry - just call gimp_main()...
*/
MAIN ()
/* Try to find a colour 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 int find_unused_ia_colour (guchar * pixels,
int numpixels,
int *colors)
{
int i;
gboolean ix_used[256]; // max of 256 palette entries
gboolean trans_used = FALSE;
for (i = 0; i < *colors; i++)
{
ix_used[i] = FALSE;
}
for (i = 0; i < numpixels; i++)
{
/* If alpha is over a threshold, the colour index in the
* palette is taken. Otherwise, this pixel is transparent. */
if (pixels[i * 2 + 1] > 127)
ix_used[pixels[i * 2]] = TRUE;
else
trans_used = TRUE;
}
// If there is no transparency, ignore alpha.
if (trans_used == FALSE)
return -1;
for (i = 0; i < *colors; i++)
{
if (ix_used[i] == FALSE)
{
return i;
}
}
/* Couldn't find an unused colour index within the number of
bits per pixel we wanted. Will have to increment the number
of colours in the image and assign a transparent pixel there. */
if ((*colors) < 256)
{
(*colors)++;
return ((*colors) - 1);
}
return (-1);
}
1997-11-25 06:05:25 +08:00
/*
* 'query()' - Respond to a plug-in query...
*/
static void
query (void)
1997-11-25 06:05:25 +08:00
{
static GimpParamDef load_args[] = {
{GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
{GIMP_PDB_STRING, "filename", "The name of the file to load"},
{GIMP_PDB_STRING, "raw_filename", "The name of the file to load"}
1997-11-25 06:05:25 +08:00
};
static GimpParamDef load_return_vals[] = {
{GIMP_PDB_IMAGE, "image", "Output image"}
1997-11-25 06:05:25 +08:00
};
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
static GimpParamDef save_args[] = {
{GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"},
{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_INT32, "interlace", "Use Adam7 interlacing?"},
{GIMP_PDB_INT32, "compression", "Deflate Compression factor (0--9)"},
{GIMP_PDB_INT32, "bkgd", "Write bKGD chunk?"},
{GIMP_PDB_INT32, "gama", "Write gAMA chunk?"},
{GIMP_PDB_INT32, "offs", "Write oFFs chunk?"},
{GIMP_PDB_INT32, "phys", "Write tIME chunk?"},
{GIMP_PDB_INT32, "time", "Write pHYs chunk?"}
1997-11-25 06:05:25 +08:00
};
gimp_install_procedure ("file_png_load",
"Loads files in PNG file format",
"This plug-in loads Portable Network Graphics (PNG) files.",
"Michael Sweet <mike@easysw.com>, Daniel Skarda <0rfelyus@atrey.karlin.mff.cuni.cz>",
"Michael Sweet <mike@easysw.com>, Daniel Skarda <0rfelyus@atrey.karlin.mff.cuni.cz>, Nick Lamb <njl195@zepler.org.uk>",
PLUG_IN_VERSION,
"<Load>/PNG",
NULL,
GIMP_PLUGIN,
G_N_ELEMENTS (load_args),
G_N_ELEMENTS (load_return_vals),
load_args, load_return_vals);
gimp_install_procedure ("file_png_save",
"Saves files in PNG file format",
"This plug-in saves Portable Network Graphics (PNG) files.",
"Michael Sweet <mike@easysw.com>, Daniel Skarda <0rfelyus@atrey.karlin.mff.cuni.cz>",
"Michael Sweet <mike@easysw.com>, Daniel Skarda <0rfelyus@atrey.karlin.mff.cuni.cz>, Nick Lamb <njl195@zepler.org.uk>",
PLUG_IN_VERSION,
"<Save>/PNG",
"RGB*,GRAY*,INDEXED*",
GIMP_PLUGIN,
G_N_ELEMENTS (save_args), 0, save_args, NULL);
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
gimp_register_magic_load_handler ("file_png_load",
"png", "", "0,string,\211PNG\r\n\032\n");
gimp_register_save_handler ("file_png_save", "png", "");
1997-11-25 06:05:25 +08:00
}
/*
* 'run()' - Run the plug-in...
*/
static void
run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
1997-11-25 06:05:25 +08:00
{
static GimpParam values[2];
GimpRunMode run_mode;
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
gint32 image_ID;
gint32 drawable_ID;
gint32 orig_image_ID;
GimpExportReturnType export = GIMP_EXPORT_CANCEL;
1997-11-25 06:05:25 +08:00
INIT_I18N ();
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
*nreturn_vals = 1;
*return_vals = values;
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
1997-11-25 06:05:25 +08:00
if (strcmp (name, "file_png_load") == 0)
{
image_ID = load_image (param[1].data.d_string);
1997-11-25 06:05:25 +08:00
if (image_ID != -1)
{
*nreturn_vals = 2;
values[1].type = GIMP_PDB_IMAGE;
values[1].data.d_image = image_ID;
}
else
{
status = GIMP_PDB_EXECUTION_ERROR;
}
1997-11-25 06:05:25 +08:00
}
else if (strcmp (name, "file_png_save") == 0)
{
run_mode = param[0].data.d_int32;
image_ID = orig_image_ID = param[1].data.d_int32;
drawable_ID = param[2].data.d_int32;
/* eventually export the image */
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
case GIMP_RUN_WITH_LAST_VALS:
gimp_ui_init ("png", FALSE);
export = gimp_export_image (&image_ID, &drawable_ID, "PNG",
(GIMP_EXPORT_CAN_HANDLE_RGB |
GIMP_EXPORT_CAN_HANDLE_GRAY |
GIMP_EXPORT_CAN_HANDLE_INDEXED |
GIMP_EXPORT_CAN_HANDLE_ALPHA));
if (export == GIMP_EXPORT_CANCEL)
{
*nreturn_vals = 1;
values[0].data.d_status = GIMP_PDB_CANCEL;
return;
}
break;
default:
break;
}
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
/*
* Possibly retrieve data...
*/
gimp_get_data ("file_png_save", &pngvals);
1997-11-25 06:05:25 +08:00
/*
* 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 (! gimp_drawable_has_alpha (drawable_ID))
pngvals.bkgd = FALSE;
/*
* Then acquire information with a dialog...
*/
if (!save_dialog ())
status = GIMP_PDB_CANCEL;
1997-11-25 06:05:25 +08:00
break;
case GIMP_RUN_NONINTERACTIVE:
/*
* Make sure all the arguments are there!
*/
2000-08-07 16:10:11 +08:00
if (nparams != 12)
{
status = GIMP_PDB_CALLING_ERROR;
}
1997-11-25 06:05:25 +08:00
else
{
pngvals.interlaced = param[5].data.d_int32;
pngvals.compression_level = param[6].data.d_int32;
pngvals.bkgd = param[7].data.d_int32;
pngvals.gama = param[8].data.d_int32;
pngvals.phys = param[9].data.d_int32;
pngvals.offs = param[10].data.d_int32;
pngvals.time = param[11].data.d_int32;
if (pngvals.compression_level < 0 ||
pngvals.compression_level > 9)
status = GIMP_PDB_CALLING_ERROR;
};
1997-11-25 06:05:25 +08:00
break;
case GIMP_RUN_WITH_LAST_VALS:
/*
* Possibly retrieve data...
*/
gimp_get_data ("file_png_save", &pngvals);
1997-11-25 06:05:25 +08:00
break;
default:
1997-11-25 06:05:25 +08:00
break;
};
if (status == GIMP_PDB_SUCCESS)
{
if (save_image (param[3].data.d_string,
image_ID, drawable_ID, orig_image_ID))
{
gimp_set_data ("file_png_save", &pngvals, sizeof (pngvals));
}
else
{
status = GIMP_PDB_EXECUTION_ERROR;
}
}
if (export == GIMP_EXPORT_EXPORT)
gimp_image_delete (image_ID);
}
1997-11-25 06:05:25 +08:00
else
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
{
status = GIMP_PDB_EXECUTION_ERROR;
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
}
values[0].data.d_status = status;
1997-11-25 06:05:25 +08:00
}
/*
* 'load_image()' - Load a PNG image into a new image window.
*/
static gint32
load_image (const gchar *filename)
1997-11-25 06:05:25 +08:00
{
int i, /* Looping var */
trns, /* Transparency present */
bpp, /* Bytes per pixel */
image_type, /* Type of image */
layer_type, /* Type of drawable/layer */
empty, /* Number of fully transparent indices */
num_passes, /* Number of interlace passes in file */
pass, /* Current pass in file */
tile_height, /* Height of tile in GIMP */
begin, /* Beginning tile row */
end, /* Ending tile row */
num; /* Number of rows to load */
FILE *fp; /* File pointer */
volatile gint32 image; /* Image -- preserved against setjmp() */
gint32 layer; /* Layer */
GimpDrawable *drawable; /* Drawable for layer */
GimpPixelRgn pixel_rgn; /* Pixel region for layer */
png_structp pp; /* PNG read pointer */
png_infop info; /* PNG info pointers */
guchar **pixels, /* Pixel rows */
*pixel; /* Pixel data */
gchar *progress; /* Title for progress display... */
guchar alpha[256], /* Index -> Alpha */
*alpha_ptr; /* Temporary pointer */
png_textp text;
gint num_texts;
/*
* PNG 0.89 and newer have a sane, forwards compatible constructor.
* Some SGI IRIX users will not have a new enough version though
*/
1997-11-25 06:05:25 +08:00
#if PNG_LIBPNG_VER > 88
pp = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info = png_create_info_struct (pp);
1997-11-25 06:05:25 +08:00
#else
pp = (png_structp) calloc (sizeof (png_struct), 1);
png_read_init (pp);
1997-11-25 06:05:25 +08:00
info = (png_infop) calloc (sizeof (png_info), 1);
1997-11-25 06:05:25 +08:00
#endif /* PNG_LIBPNG_VER > 88 */
if (setjmp (pp->jmpbuf))
{
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message (_("'%s':\nPNG error. File corrupted?"), filename);
return image;
}
/* initialise image here, thus avoiding compiler warnings */
2000-04-21 09:38:36 +08:00
image = -1;
2000-04-21 09:38:36 +08:00
/*
* Open the file and initialize the PNG read "engine"...
*/
1997-11-25 06:05:25 +08:00
fp = fopen (filename, "rb");
if (fp == NULL)
{
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message (_("Can't open '%s':\n%s"), filename, g_strerror (errno));
gimp_quit ();
}
1997-11-25 06:05:25 +08:00
png_init_io (pp, fp);
1997-11-25 06:05:25 +08:00
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
progress = g_strdup_printf (_("Opening '%s'..."), filename);
gimp_progress_init (progress);
g_free (progress);
1997-11-25 06:05:25 +08:00
/*
* Get the image dimensions and create the image...
*/
1997-11-25 06:05:25 +08:00
png_read_info (pp, info);
1997-11-25 06:05:25 +08:00
/*
* Latest attempt, this should be my best yet :)
*/
if (info->bit_depth == 16)
{
png_set_strip_16 (pp);
}
if (info->color_type == PNG_COLOR_TYPE_GRAY && info->bit_depth < 8)
{
png_set_expand (pp);
}
if (info->color_type == PNG_COLOR_TYPE_PALETTE && info->bit_depth < 8)
{
png_set_packing (pp);
}
/*
* Expand G+tRNS to GA, RGB+tRNS to RGBA
*/
if (info->color_type != PNG_COLOR_TYPE_PALETTE &&
(info->valid & PNG_INFO_tRNS))
{
png_set_expand (pp);
}
1997-11-25 06:05:25 +08:00
/*
* Turn on interlace handling... libpng returns just 1 (ie single pass)
* if the image is not interlaced
*/
1997-11-25 06:05:25 +08:00
num_passes = png_set_interlace_handling (pp);
/*
* Special handling for INDEXED + tRNS (transparency palette)
*/
#if PNG_LIBPNG_VER > 99
if (png_get_valid (pp, info, PNG_INFO_tRNS) &&
info->color_type == PNG_COLOR_TYPE_PALETTE)
{
png_get_tRNS (pp, info, &alpha_ptr, &num, NULL);
/* Copy the existing alpha values from the tRNS chunk */
for (i = 0; i < num; ++i)
alpha[i] = alpha_ptr[i];
/* And set any others to fully opaque (255) */
for (i = num; i < 256; ++i)
alpha[i] = 255;
trns = 1;
}
else
{
trns = 0;
}
#else
trns = 0;
#endif /* PNG_LIBPNG_VER > 99 */
/*
* Update the info structures after the transformations take effect
*/
png_read_update_info (pp, info);
1997-11-25 06:05:25 +08:00
switch (info->color_type)
{
case PNG_COLOR_TYPE_RGB: /* RGB */
bpp = 3;
image_type = GIMP_RGB;
layer_type = GIMP_RGB_IMAGE;
break;
case PNG_COLOR_TYPE_RGB_ALPHA: /* RGBA */
bpp = 4;
image_type = GIMP_RGB;
layer_type = GIMP_RGBA_IMAGE;
break;
case PNG_COLOR_TYPE_GRAY: /* Grayscale */
bpp = 1;
image_type = GIMP_GRAY;
layer_type = GIMP_GRAY_IMAGE;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA: /* Grayscale + alpha */
bpp = 2;
image_type = GIMP_GRAY;
layer_type = GIMP_GRAYA_IMAGE;
break;
case PNG_COLOR_TYPE_PALETTE: /* Indexed */
bpp = 1;
image_type = GIMP_INDEXED;
layer_type = GIMP_INDEXED_IMAGE;
break;
default: /* Aie! Unknown type */
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message (_("'%s':\nUnknown PNG color model"), filename);
return -1;
};
1997-11-25 06:05:25 +08:00
image = gimp_image_new (info->width, info->height, image_type);
1997-11-25 06:05:25 +08:00
if (image == -1)
{
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message ("'%s'\nCan't allocate new image", filename);
gimp_quit ();
};
1997-11-25 06:05:25 +08:00
/*
* Create the "background" layer to hold the image...
*/
layer = gimp_layer_new (image, _("Background"), info->width, info->height,
layer_type, 100, GIMP_NORMAL_MODE);
gimp_image_add_layer (image, layer, 0);
/*
* Find out everything we can about the image resolution
* This is only practical with the new 1.0 APIs, I'm afraid
* due to a bug in libpng-1.0.6, see png-implement for details
*/
#if PNG_LIBPNG_VER > 99
if (png_get_valid (pp, info, PNG_INFO_gAMA))
{
/* I sure would like to handle this, but there's no mechanism to
do so in Gimp :( */
}
if (png_get_valid (pp, info, PNG_INFO_oFFs))
{
gimp_layer_set_offsets (layer, png_get_x_offset_pixels (pp, info),
png_get_y_offset_pixels (pp, info));
}
if (png_get_valid (pp, info, PNG_INFO_pHYs))
{
gimp_image_set_resolution (image,
((double)
png_get_x_pixels_per_meter (pp,
info)) * 0.0254,
((double)
png_get_y_pixels_per_meter (pp,
info)) *
0.0254);
}
#endif /* PNG_LIBPNG_VER > 99 */
gimp_image_set_filename (image, filename);
1997-11-25 06:05:25 +08:00
/*
* Load the colormap as necessary...
*/
1997-11-25 06:05:25 +08:00
empty = 0; /* by default assume no full transparent palette entries */
if (info->color_type & PNG_COLOR_MASK_PALETTE)
{
#if PNG_LIBPNG_VER > 99
if (png_get_valid (pp, info, PNG_INFO_tRNS))
{
for (empty = 0; empty < 256 && alpha[empty] == 0; ++empty);
/* Calculates number of fully transparent "empty" entries */
gimp_image_set_cmap (image, (guchar *) (info->palette + empty),
info->num_palette - empty);
}
else
{
gimp_image_set_cmap (image, (guchar *) info->palette,
info->num_palette);
}
#else
gimp_image_set_cmap (image, (guchar *) info->palette,
info->num_palette);
#endif /* PNG_LIBPNG_VER > 99 */
}
1997-11-25 06:05:25 +08:00
/*
* Get the drawable and set the pixel region for our load...
*/
1997-11-25 06:05:25 +08:00
drawable = gimp_drawable_get (layer);
1997-11-25 06:05:25 +08:00
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
drawable->height, TRUE, FALSE);
1997-11-25 06:05:25 +08:00
/*
* Temporary buffer...
*/
1997-11-25 06:05:25 +08:00
tile_height = gimp_tile_height ();
pixel = g_new (guchar, tile_height * info->width * bpp);
pixels = g_new (guchar *, tile_height);
1997-11-25 06:05:25 +08:00
for (i = 0; i < tile_height; i++)
1997-11-25 06:05:25 +08:00
pixels[i] = pixel + info->width * info->channels * i;
for (pass = 0; pass < num_passes; pass++)
1997-11-25 06:05:25 +08:00
{
/*
* This works if you are only reading one row at a time...
*/
1997-11-25 06:05:25 +08:00
for (begin = 0, end = tile_height;
begin < info->height; begin += tile_height, end += tile_height)
{
if (end > info->height)
end = info->height;
1997-11-25 06:05:25 +08:00
num = end - begin;
1997-11-25 06:05:25 +08:00
if (pass != 0) /* to handle interlaced PiNGs */
gimp_pixel_rgn_get_rect (&pixel_rgn, pixel, 0, begin,
drawable->width, num);
1997-11-25 06:05:25 +08:00
png_read_rows (pp, pixels, NULL, num);
1997-11-25 06:05:25 +08:00
gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, begin,
drawable->width, num);
1997-11-25 06:05:25 +08:00
gimp_progress_update (((double) pass +
(double) end / (double) info->height) /
(double) num_passes);
};
};
1997-11-25 06:05:25 +08:00
png_read_end (pp, info);
if (png_get_text (pp, info, &text, &num_texts))
{
gchar *comment = NULL;
for (i = 0; i < num_texts && !comment; i++)
{
if (text->key == NULL || strcmp (text->key, "Comment"))
continue;
if (text->text_length > 0) /* tEXt */
{
comment = g_convert (text->text, -1,
"UTF-8", "ISO-8859-1",
NULL, NULL, NULL);
}
else
{ /* iTXt */
comment = g_strdup (text->text);
}
}
if (comment && *comment)
{
GimpParasite *parasite;
parasite = gimp_parasite_new ("gimp-comment",
GIMP_PARASITE_PERSISTENT,
strlen (comment) + 1, comment);
gimp_image_parasite_attach (image, parasite);
gimp_parasite_free (parasite);
}
g_free (comment);
}
/*
* Done with the file...
*/
1997-11-25 06:05:25 +08:00
png_read_destroy (pp, info, NULL);
1997-11-25 06:05:25 +08:00
g_free (pixel);
g_free (pixels);
free (pp);
free (info);
fclose (fp);
if (trns)
{
gimp_layer_add_alpha (layer);
drawable = gimp_drawable_get (layer);
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
drawable->height, TRUE, FALSE);
pixel = g_new (guchar, tile_height * drawable->width * 2); /* bpp == 1 */
for (begin = 0, end = tile_height;
begin < drawable->height; begin += tile_height, end += tile_height)
{
if (end > drawable->height)
end = drawable->height;
num = end - begin;
gimp_pixel_rgn_get_rect (&pixel_rgn, pixel, 0, begin,
drawable->width, num);
for (i = 0; i < tile_height * drawable->width; ++i)
{
pixel[i * 2 + 1] = alpha[pixel[i * 2]];
pixel[i * 2] -= empty;
}
gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, begin,
drawable->width, num);
}
g_free (pixel);
}
/*
* Update the display...
*/
1997-11-25 06:05:25 +08:00
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
1997-11-25 06:05:25 +08:00
return (image);
}
/*
* 'save_image ()' - Save the specified image to a PNG file.
1997-11-25 06:05:25 +08:00
*/
static gint
save_image (const gchar *filename,
gint32 image_ID,
gint32 drawable_ID,
gint32 orig_image_ID)
1997-11-25 06:05:25 +08:00
{
int i, k, /* Looping vars */
bpp = 0, /* Bytes per pixel */
type, /* Type of drawable/layer */
num_passes, /* Number of interlace passes in file */
pass, /* Current pass in file */
tile_height, /* Height of tile in GIMP */
begin, /* Beginning tile row */
end, /* Ending tile row */
num; /* Number of rows to load */
FILE *fp; /* File pointer */
GimpDrawable *drawable; /* Drawable for layer */
GimpPixelRgn pixel_rgn; /* Pixel region for layer */
png_structp pp; /* PNG read pointer */
png_infop info; /* PNG info pointer */
gint num_colors; /* Number of colors in colormap */
gint offx, offy; /* Drawable offsets from origin */
guchar **pixels, /* Pixel rows */
*fixed, /* Fixed-up pixel data */
*pixel; /* Pixel data */
gchar *progress; /* Title for progress display... */
gdouble xres, yres; /* GIMP resolution (dpi) */
gdouble gamma; /* GIMP gamma e.g. 2.20 */
png_color_16 background; /* Background color */
png_time mod_time; /* Modification time (ie NOW) */
guchar red, green, blue; /* Used for palette background */
time_t cutime; /* Time since epoch */
struct tm *gmt; /* GMT broken down */
guchar remap[256]; /* Re-mapping for the palette */
png_textp text = NULL;
GimpParasite *parasite;
parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
if (parasite)
{
gchar *comment = g_strndup (gimp_parasite_data (parasite),
gimp_parasite_data_size (parasite));
gimp_parasite_free (parasite);
text = g_new0 (png_text, 1);
text->key = "Comment";
#ifdef PNG_iTXt_SUPPORTED
text->compression = PNG_ITXT_COMPRESSION_NONE;
text->text = comment
text->itxt_length = strlen (comment);
#else
text->compression = PNG_TEXT_COMPRESSION_NONE;
text->text = g_convert (comment, -1,
"ISO-8859-1", "UTF-8",
NULL, &text->text_length,
NULL);
#endif
if (!text->text)
{
g_free (text);
text = NULL;
}
}
/*
* PNG 0.89 and newer have a sane, forwards compatible constructor.
* Some SGI IRIX users will not have a new enough version though
*/
1997-11-25 06:05:25 +08:00
#if PNG_LIBPNG_VER > 88
pp = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info = png_create_info_struct (pp);
1997-11-25 06:05:25 +08:00
#else
pp = (png_structp) calloc (sizeof (png_struct), 1);
png_write_init (pp);
1997-11-25 06:05:25 +08:00
info = (png_infop) calloc (sizeof (png_info), 1);
1997-11-25 06:05:25 +08:00
#endif /* PNG_LIBPNG_VER > 88 */
if (setjmp (pp->jmpbuf))
{
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message (_("'%s':\nPNG error. Couldn't save image"), filename);
return 0;
}
if (text)
png_set_text (pp, info, text, 1);
/*
* Open the file and initialize the PNG write "engine"...
*/
1997-11-25 06:05:25 +08:00
fp = fopen (filename, "wb");
if (fp == NULL)
{
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message (_("Can't open '%s' for writing:\n%s"),
filename, g_strerror (errno));
return 0;
}
png_init_io (pp, fp);
1997-11-25 06:05:25 +08:00
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
progress = g_strdup_printf (_("Saving '%s'..."), filename);
gimp_progress_init (progress);
g_free (progress);
1997-11-25 06:05:25 +08:00
/*
* Get the drawable for the current image...
*/
1997-11-25 06:05:25 +08:00
drawable = gimp_drawable_get (drawable_ID);
type = gimp_drawable_type (drawable_ID);
1997-11-25 06:05:25 +08:00
/*
* Set the image dimensions, bit depth, interlacing and compression
*/
1997-11-25 06:05:25 +08:00
png_set_compression_level (pp, pngvals.compression_level);
1997-11-25 06:05:25 +08:00
info->width = drawable->width;
info->height = drawable->height;
info->bit_depth = 8;
1997-11-25 06:05:25 +08:00
info->interlace_type = pngvals.interlaced;
/*
* Initialise remap[]
*/
for (i = 0; i < 256; i++)
{
remap[i] = i;
}
/*
* Set color type and remember bytes per pixel count
*/
1997-11-25 06:05:25 +08:00
switch (type)
{
case GIMP_RGB_IMAGE:
info->color_type = PNG_COLOR_TYPE_RGB;
bpp = 3;
break;
case GIMP_RGBA_IMAGE:
info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
bpp = 4;
break;
case GIMP_GRAY_IMAGE:
info->color_type = PNG_COLOR_TYPE_GRAY;
bpp = 1;
break;
case GIMP_GRAYA_IMAGE:
info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
bpp = 2;
break;
case GIMP_INDEXED_IMAGE:
bpp = 1;
info->color_type = PNG_COLOR_TYPE_PALETTE;
info->valid |= PNG_INFO_PLTE;
info->palette =
(png_colorp) gimp_image_get_cmap (image_ID, &num_colors);
info->num_palette = num_colors;
break;
case GIMP_INDEXEDA_IMAGE:
bpp = 2;
info->color_type = PNG_COLOR_TYPE_PALETTE;
respin_cmap (pp, info, remap, image_ID, drawable); /* fix up transparency */
break;
1999-07-11 21:26:37 +08:00
default:
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message ("'%s':\nImage type can't be saved as PNG", filename);
return 0;
};
1997-11-25 06:05:25 +08:00
/*
* Fix bit depths for (possibly) smaller colormap images
*/
if (info->valid & PNG_INFO_PLTE)
{
if (info->num_palette <= 2)
info->bit_depth = 1;
else if (info->num_palette <= 4)
info->bit_depth = 2;
else if (info->num_palette <= 16)
info->bit_depth = 4;
/* otherwise the default is fine */
}
/* All this stuff is optional extras, if the user is aiming for smallest
possible file size she can turn them all off */
#if PNG_LIBPNG_VER > 99
if (pngvals.bkgd)
{
GimpRGB color;
tools/pdbgen/lib.pl tools/pdbgen/pdb.pl tools/pdbgen/pdb/channel.pdb 2001-01-25 Sven Neumann <sven@gimp.org> * tools/pdbgen/lib.pl * tools/pdbgen/pdb.pl * tools/pdbgen/pdb/channel.pdb * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/tools.pdb: changed these with the help of Yosh. PDB functions take GimpRGB as color type now. * app/plug_in.c * app/pdb/channel_cmds.c * app/pdb/internal_procs.c * app/pdb/palette_cmds.c * app/pdb/procedural_db.[ch] * app/pdb/tools_cmds.c * libgimp/gimp.[ch] * libgimp/gimpchannel.[ch] * libgimp/gimpchannel_pdb.[ch] * libgimp/gimppalette_pdb.[ch] * libgimp/gimpprotocol.[ch] * libgimp/gimptools_pdb.[ch]: incremented Gimp protocol version and changed color type from array of chars to GimpRGB. * libgimp/Makefile.am * libgimp/gimppalette.[ch]: removed these files again * app/libgimp_glue.[ch] * libgimpwidgets/gimpcolorbutton.c * plug-ins/Lighting/lighting_main.c * plug-ins/Lighting/lighting_preview.c * plug-ins/MapObject/mapobject_image.c * plug-ins/MapObject/mapobject_main.c * plug-ins/MapObject/mapobject_preview.c * plug-ins/common/apply_lens.c * plug-ins/common/blinds.c * plug-ins/common/borderaverage.c * plug-ins/common/checkerboard.c * plug-ins/common/colorify.c * plug-ins/common/colortoalpha.c * plug-ins/common/cubism.c * plug-ins/common/exchange.c * plug-ins/common/film.c * plug-ins/common/gif.c * plug-ins/common/grid.c * plug-ins/common/mapcolor.c * plug-ins/common/mblur.c * plug-ins/common/nova.c * plug-ins/common/papertile.c * plug-ins/common/png.c * plug-ins/common/polar.c * plug-ins/common/psd.c * plug-ins/common/semiflatten.c * plug-ins/common/sinus.c * plug-ins/common/sparkle.c * plug-ins/common/tiff.c * plug-ins/common/vpropagate.c * plug-ins/common/warp.c * plug-ins/common/whirlpinch.c * plug-ins/gap/gap_filter_iterators.c * plug-ins/gap/gap_mov_dialog.c * plug-ins/gdyntext/gdyntext.c * plug-ins/gfig/gfig.c * plug-ins/gfli/gfli.c * plug-ins/ifscompose/ifscompose.c * plug-ins/maze/handy.c * plug-ins/mosaic/mosaic.c * plug-ins/pagecurl/pagecurl.c * plug-ins/script-fu/script-fu-scripts.c * plug-ins/script-fu/script-fu.c * plug-ins/xjt/xjt.c: changed accordingly. A few plug-ins need to be looked at more closely after this change. I tried to put FIXME comments into those.
2001-01-25 09:20:05 +08:00
gimp_palette_get_background (&color);
gimp_rgb_get_uchar (&color, &red, &green, &blue);
background.index = 0;
background.red = red;
background.green = green;
background.blue = blue;
background.gray = gimp_rgb_intensity_uchar (&color);
png_set_bKGD (pp, info, &background);
}
if (pngvals.gama)
{
gamma = gimp_gamma ();
png_set_gAMA (pp, info, 1.0 / (gamma != 1.00 ? gamma : DEFAULT_GAMMA));
}
if (pngvals.offs)
{
gimp_drawable_offsets (drawable_ID, &offx, &offy);
if (offx != 0 || offy != 0)
{
png_set_oFFs (pp, info, offx, offy, PNG_OFFSET_PIXEL);
}
}
if (pngvals.phys)
{
gimp_image_get_resolution (orig_image_ID, &xres, &yres);
png_set_pHYs (pp, info, xres * 39.37, yres * 39.37,
PNG_RESOLUTION_METER);
}
if (pngvals.time)
{
cutime = time (NULL); /* time right NOW */
gmt = gmtime (&cutime);
mod_time.year = gmt->tm_year + 1900;
mod_time.month = gmt->tm_mon + 1;
mod_time.day = gmt->tm_mday;
mod_time.hour = gmt->tm_hour;
mod_time.minute = gmt->tm_min;
mod_time.second = gmt->tm_sec;
png_set_tIME (pp, info, &mod_time);
}
#endif /* PNG_LIBPNG_VER > 99 */
png_write_info (pp, info);
1997-11-25 06:05:25 +08:00
/*
* Turn on interlace handling...
*/
1997-11-25 06:05:25 +08:00
if (pngvals.interlaced)
num_passes = png_set_interlace_handling (pp);
1997-11-25 06:05:25 +08:00
else
num_passes = 1;
/*
* Convert unpacked pixels to packed if necessary
*/
if (info->color_type == PNG_COLOR_TYPE_PALETTE && info->bit_depth < 8)
png_set_packing (pp);
1997-11-25 06:05:25 +08:00
/*
* Allocate memory for "tile_height" rows and save the image...
*/
1997-11-25 06:05:25 +08:00
tile_height = gimp_tile_height ();
pixel = g_new (guchar, tile_height * drawable->width * bpp);
pixels = g_new (guchar *, tile_height);
1997-11-25 06:05:25 +08:00
for (i = 0; i < tile_height; i++)
pixels[i] = pixel + drawable->width * bpp * i;
1997-11-25 06:05:25 +08:00
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
drawable->height, FALSE, FALSE);
for (pass = 0; pass < num_passes; pass++)
{
/* This works if you are only writing one row at a time... */
for (begin = 0, end = tile_height;
begin < drawable->height; begin += tile_height, end += tile_height)
{
if (end > drawable->height)
end = drawable->height;
num = end - begin;
gimp_pixel_rgn_get_rect (&pixel_rgn, pixel, 0, begin,
drawable->width, num);
/* If we're dealing with a paletted image with
* transparency set, write out the remapped palette */
if (info->valid & PNG_INFO_tRNS)
{
for (i = 0; i < num; ++i)
{
fixed = pixels[i];
for (k = 0; k < drawable->width; ++k)
{
fixed[k] = (fixed[k*2+1] > 127) ?
remap[fixed[k*2]] :
0;
}
}
}
/* Otherwise if we have a paletted image and transparency
* couldn't be set, we ignore the alpha channel */
else if (info->valid & PNG_INFO_PLTE && bpp == 2)
{
for (i = 0; i < num; ++i)
{
fixed = pixels[i];
for (k = 0; k < drawable->width; ++k)
{
fixed[k] = fixed[k * 2];
}
}
}
png_write_rows (pp, pixels, num);
gimp_progress_update (((double) pass + (double) end /
(double) info->height) /
(double) num_passes);
};
};
1997-11-25 06:05:25 +08:00
png_write_end (pp, info);
png_write_destroy (pp);
1997-11-25 06:05:25 +08:00
g_free (pixel);
g_free (pixels);
1997-11-25 06:05:25 +08:00
/*
* Done with the file...
*/
1997-11-25 06:05:25 +08:00
if (text)
{
g_free (text->text);
g_free (text);
}
free (pp);
free (info);
1997-11-25 06:05:25 +08:00
fclose (fp);
1997-11-25 06:05:25 +08:00
return (1);
}
static void
save_ok_callback (GtkWidget * widget,
gpointer data)
1997-11-25 06:05:25 +08:00
{
runme = TRUE;
gtk_widget_destroy (GTK_WIDGET (data));
1997-11-25 06:05:25 +08:00
}
static void
respin_cmap (png_structp pp,
png_infop info,
guchar * remap,
gint32 image_ID,
GimpDrawable * drawable)
{
2000-09-15 08:50:12 +08:00
static const guchar trans[] = { 0 };
gint colors;
guchar *before;
gint transparent;
gint cols, rows;
GimpPixelRgn pixel_rgn;
guchar *pixels;
before = gimp_image_get_cmap (image_ID, &colors);
cols = drawable->width;
rows = drawable->height;
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
drawable->width, drawable->height, FALSE, FALSE);
pixels = (guchar *) g_malloc (drawable->width * drawable->height * 2);
gimp_pixel_rgn_get_rect (&pixel_rgn, pixels, 0, 0,
drawable->width, drawable->height);
/* Try to find an entry which isn't actually used in the
image, for a transparency index. */
transparent = find_unused_ia_colour (pixels,
drawable->width * drawable->height,
&colors);
#if PNG_LIBPNG_VER > 99
if (transparent != -1) /* we have a winner for a transparent
* index - do like gif2png and swap
* index 0 and index transparent */
{
png_color palette[256];
gint i;
png_set_tRNS (pp, info, (png_bytep) trans, 1, NULL);
/* 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;
remap[transparent] = 0;
/* 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. */
for (i = 0; i < colors; i++)
{
palette[i].red = before[3 * remap[i]];
palette[i].green = before[3 * remap[i] + 1];
palette[i].blue = before[3 * remap[i] + 2];
}
png_set_PLTE (pp, info, palette, colors);
}
else
{
/* Inform the user that we couldn't losslessly save the
* transparency & just use the full palette */
Cleaned up and improved the message system: 2003-06-13 Michael Natterer <mitch@gimp.org> Cleaned up and improved the message system: * app/core/gimp.[ch]: added "const gchar *domain" to GimpMessageFunc (a NULL domain means the message is from the GIMP core, everything else is a plug-in). * app/errors.c: pass "domain == NULL" to gimp_message(). * tools/pdbgen/pdb/message.pdb: derive the message domain from the current plug-in's menu_path (evil hack but works reasonably well). * app/pdb/message_cmds.c: regenerated. * app/widgets/gimpwidgets-utils.[ch] (gimp_message_box): added a header showing the message domain and changed the dialog layout to follow the HIG more closely. * app/gui/error-console-dialog.[ch]: removed. * app/widgets/gimperrorconsole.[ch] * app/gui/error-console-commands.[ch] * app/gui/error-console-menu.[ch]: new files containing a re-implementation of the error console dialog. * app/gui/Makefile.am * app/gui/dialogs-constructors.c * app/gui/gui.c * app/gui/menus.c * app/widgets/Makefile.am * app/widgets/widgets-types.h: changed accordingly. * app/display/gimpprogress.c: added more spacing and removed the separator (more HIG compliant). * plug-ins/[most plug-ins].c: Changed lots of messages and progress strings: - Removed plug-in names from messages since that's automatically covered by "domain" now. - Put all filenames in ''. - Changed "Loading" to "Opening". - Added "..." to all progress messages. - Cleaned up all file open/save error messages to look the same and include g_strerror(errno). - Removed special casing for progress bars and *always* show them, not only if run_mode != GIMP_RUN_NONINTERACTIVE (we can't expect all plug-ins to do this correctly but need to hack the core to sort out unwanted progress bars). Unrelated: - Cleaned up indentation, spacing, #includes, coding style and other stuff while I was at all these files.
2003-06-13 22:37:00 +08:00
g_message (_("Couldn't losslessly save transparency,\n"
"saving opacity instead."));
png_set_PLTE (pp, info, (png_colorp) before, colors);
}
#else
info->valid |= PNG_INFO_PLTE;
info->palette = (png_colorp) before;
info->num_palette = colors;
#endif /* PNG_LIBPNG_VER > 99 */
g_free (pixels);
}
1997-11-25 06:05:25 +08:00
static gint
save_dialog (void)
1997-11-25 06:05:25 +08:00
{
GtkWidget *dlg;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *toggle;
GtkWidget *scale;
GtkObject *scale_data;
1997-11-25 06:05:25 +08:00
dlg = gimp_dialog_new (_("Save as PNG"), "png",
gimp_standard_help_func, "filters/png.html",
GTK_WIN_POS_MOUSE,
FALSE, TRUE, FALSE,
GTK_STOCK_CANCEL, gtk_widget_destroy,
NULL, 1, NULL, FALSE, TRUE,
GTK_STOCK_OK, save_ok_callback,
NULL, NULL, NULL, TRUE, FALSE, NULL);
g_signal_connect (dlg, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
1997-11-25 06:05:25 +08:00
frame = gtk_frame_new (_("Parameter Settings"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
added -DGTK_DISABLE_COMPAT_H to CPPFLAGS. 2000-08-28 Michael Natterer <mitch@gimp.org> * configure.in: added -DGTK_DISABLE_COMPAT_H to CPPFLAGS. * app/app_procs.c * app/gdisplay.c * app/layers_dialog.c * app/menus.c * app/tips_dialog.c * libgimp/gimpcolorbutton.c * plug-ins/FractalExplorer/Dialogs.c * plug-ins/FractalExplorer/FractalExplorer.c * plug-ins/bmp/bmpwrite.c * plug-ins/common/AlienMap.c * plug-ins/common/AlienMap2.c * plug-ins/common/CML_explorer.c * plug-ins/common/animationplay.c * plug-ins/common/cubism.c * plug-ins/common/curve_bend.c * plug-ins/common/deinterlace.c * plug-ins/common/gee.c * plug-ins/common/glasstile.c * plug-ins/common/iwarp.c * plug-ins/common/mail.c * plug-ins/common/pat.c * plug-ins/common/pixelize.c * plug-ins/common/plugindetails.c * plug-ins/common/png.c * plug-ins/common/sample_colorize.c * plug-ins/common/sel_gauss.c * plug-ins/common/sinus.c * plug-ins/common/sparkle.c * plug-ins/common/spheredesigner.c * plug-ins/common/tga.c * plug-ins/common/tileit.c * plug-ins/common/vpropagate.c * plug-ins/common/warp.c * plug-ins/common/waves.c * plug-ins/common/wmf.c * plug-ins/flame/flame.c * plug-ins/fp/fp_gtk.c * plug-ins/gap/gap_arr_dialog.c * plug-ins/gap/gap_dbbrowser_utils.c * plug-ins/gap/gap_mov_dialog.c * plug-ins/gap/gap_navigator_dialog.c * plug-ins/gap/gap_resi_dialog.c * plug-ins/gdyntext/gdyntext_ui.c * plug-ins/gfig/gfig.c * plug-ins/gimpressionist/brush.c * plug-ins/gimpressionist/gimpressionist.c * plug-ins/pagecurl/pagecurl.c * plug-ins/print/gimp_main_window.c * plug-ins/rcm/rcm_callback.c * plug-ins/rcm/rcm_dialog.c * plug-ins/script-fu/script-fu-console.c * plug-ins/script-fu/script-fu-scripts.c * plug-ins/script-fu/script-fu-server.c * plug-ins/sel2path/sel2path_adv_dialog.c * plug-ins/xjt/xjt.c: removed COMPAT_CRUFT.
2000-08-28 08:42:32 +08:00
gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
1997-11-25 06:05:25 +08:00
table = gtk_table_new (2, 7, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_container_set_border_width (GTK_CONTAINER (table), 4);
gtk_container_add (GTK_CONTAINER (frame), table);
gtk_widget_show (table);
toggle = gtk_check_button_new_with_mnemonic (_("_Interlacing (Adam7)"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 0, 1, GTK_FILL, 0, 0, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
pngvals.interlaced);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
&pngvals.interlaced);
toggle = gtk_check_button_new_with_mnemonic (_("Save _background color"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 1, 2, GTK_FILL, 0, 0, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pngvals.bkgd);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update), &pngvals.bkgd);
toggle = gtk_check_button_new_with_mnemonic (_("Save _gamma"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 2, 3, GTK_FILL, 0, 0, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pngvals.gama);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update), &pngvals.gama);
toggle = gtk_check_button_new_with_mnemonic (_("Save _layer offset"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 3, 4, GTK_FILL, 0, 0, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pngvals.offs);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update), &pngvals.offs);
toggle = gtk_check_button_new_with_mnemonic (_("Save _resolution"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 4, 5, GTK_FILL, 0, 0, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pngvals.phys);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update), &pngvals.phys);
toggle = gtk_check_button_new_with_mnemonic (_("Save creation _time"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 5, 6, GTK_FILL, 0, 0, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pngvals.time);
gtk_widget_show (toggle);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update), &pngvals.time);
scale_data = gtk_adjustment_new (pngvals.compression_level,
0.0, 9.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data));
gtk_widget_set_size_request (scale, SCALE_WIDTH, -1);
1997-11-25 06:05:25 +08:00
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_scale_set_digits (GTK_SCALE (scale), 0);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 6,
_("Co_mpression Level:"), 1.0, 1.0,
scale, 1, FALSE);
gtk_widget_show (scale);
gimp_help_set_help_data (scale,
_("Choose a high compression level "
"for small file size"),
NULL);
g_signal_connect (scale_data, "value_changed",
G_CALLBACK (gimp_int_adjustment_update),
&pngvals.compression_level);
gtk_widget_show (dlg);
gtk_main ();
gdk_flush ();
return runme;
1997-11-25 06:05:25 +08:00
}