gimp/plug-ins/common/file-cel.c

1026 lines
30 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* cel.c -- KISS CEL file format plug-in
* (copyright) 1997,1998 Nick Lamb (njl195@zepler.org.uk)
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
1997-11-24 22:05:25 +00:00
*/
New file. * plug-ins/makefile.msc: New file. * plug-ins/*/*.c (Well, not really all files, but many): Portability fixes. Include config.h, and guard inclusion of POSIX and Unix headers like <unistd.h>, <dirent.h> and <sys/time.h>. Include <string.h> if functions from it are used. Use g_ntohl() and g_htonl() insteead of ntohl() and htonl(), thus no need to include <netinet/in.h>. Include <io.h> on Win32 when using open/read/write (which actually are defined as _open/_read/_write by glib.h). Define S_* macros if necessary on Win32. Define rint() and M_PI if necessary (these definitions should be factored out somewhere, no sense repeating them in lots of files). Open files in binary mode when needed. * plug-ins/FractalExplorer/FractalExplorer.c: Use g_malloc()/g_free(). Use g_strdup_printf(). * plug-ins/dbbrowser/dbbrowser.c: No need to include <X11/Xlib.h>. * plug-ins/destripe/destripe.c: Guard use of SIGBUS. * plug-ins/{flame/flame,hrz/hrz,pnm/pnm}.c: No need to check for NULL returns from g_malloc() and g_new() as they abort on failure. Use g_strdup_printf(). * plug-ins/gz/gz.c: Win32 version of running the subprocess. * plug-ins/hrz/hrz.c: Win32 version. Use more generic tests for non-Unix (OS/2 and Win32), for instance HAVE_MMAP. * plug-ins/script-fu/interp_slib.c: Win32 version of myruntime(). * plug-ins/script-fu/interp_sliba.c: Handle \\ (escaped backslahsh). * plug-ins/script-fu/script-fu-console.c: Bypass on Win32. * plug-ins/script-fu/script-fu-scripts.c: Portability fixes. Use g_strdup_printf() instead of separate malloc() and sprintf(). Use g_strescape() for strings being passed to Scheme. Some Win32-only stuff.
1999-05-29 01:28:24 +00: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 14:37:00 +00:00
#include <errno.h>
1997-11-24 22:05:25 +00:00
#include <string.h>
#include <glib/gstdio.h>
1997-11-24 22:05:25 +00:00
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "libgimp/stdplugins-intl.h"
1997-11-24 22:05:25 +00:00
#define LOAD_PROC "file-cel-load"
#define SAVE_PROC "file-cel-save"
#define PLUG_IN_BINARY "file-cel"
#define PLUG_IN_ROLE "gimp-file-cel"
typedef struct _Cel Cel;
typedef struct _CelClass CelClass;
struct _Cel
{
GimpPlugIn parent_instance;
};
struct _CelClass
1997-11-24 22:05:25 +00:00
{
GimpPlugInClass parent_class;
1997-11-24 22:05:25 +00:00
};
#define CEL_TYPE (cel_get_type ())
#define CEL (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CEL_TYPE, Cel))
GType cel_get_type (void) G_GNUC_CONST;
static GList * cel_query_procedures (GimpPlugIn *plug_in);
static GimpProcedure * cel_create_procedure (GimpPlugIn *plug_in,
const gchar *name);
static GimpValueArray * cel_load (GimpProcedure *procedure,
GimpRunMode run_mode,
GFile *file,
const GimpValueArray *args,
gpointer run_data);
static GimpValueArray * cel_save (GimpProcedure *procedure,
GimpRunMode run_mode,
GimpImage *image,
gint n_drawables,
GimpDrawable **drawables,
GFile *file,
const GimpValueArray *args,
gpointer run_data);
static gint load_palette (GFile *file,
FILE *fp,
guchar palette[],
GError **error);
static GimpImage * load_image (GFile *file,
GError **error);
static gboolean save_image (GFile *file,
GimpImage *image,
GimpDrawable *drawable,
GError **error);
static void palette_dialog (const gchar *title);
static gboolean need_palette (GFile *file,
GError **error);
G_DEFINE_TYPE (Cel, cel, GIMP_TYPE_PLUG_IN)
GIMP_MAIN (CEL_TYPE)
DEFINE_STD_SET_I18N
static gchar *palette_file = NULL;
static gsize data_length = 0;
1997-11-24 22:05:25 +00:00
static void
cel_class_init (CelClass *klass)
{
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
1997-11-24 22:05:25 +00:00
plug_in_class->query_procedures = cel_query_procedures;
plug_in_class->create_procedure = cel_create_procedure;
plug_in_class->set_i18n = STD_SET_I18N;
}
1997-11-24 22:05:25 +00:00
static void
cel_init (Cel *cel)
{
1997-11-24 22:05:25 +00:00
}
static GList *
cel_query_procedures (GimpPlugIn *plug_in)
{
GList *list = NULL;
list = g_list_append (list, g_strdup (LOAD_PROC));
list = g_list_append (list, g_strdup (SAVE_PROC));
2012-11-19 18:43:35 +01:00
return list;
}
static GimpProcedure *
cel_create_procedure (GimpPlugIn *plug_in,
const gchar *name)
{
GimpProcedure *procedure = NULL;
1997-11-24 22:05:25 +00:00
if (! strcmp (name, LOAD_PROC))
{
procedure = gimp_load_procedure_new (plug_in, name,
GIMP_PDB_PROC_TYPE_PLUGIN,
cel_load, NULL, NULL);
gimp_procedure_set_menu_label (procedure, _("KISS CEL"));
gimp_procedure_set_documentation (procedure,
"Loads files in KISS CEL file format",
"This plug-in loads individual KISS "
"cell files.",
name);
gimp_procedure_set_attribution (procedure,
"Nick Lamb",
"Nick Lamb <njl195@zepler.org.uk>",
"May 1998");
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
"cel");
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
"0,string,KiSS\\040");
GIMP_PROC_ARG_STRING (procedure, "palette-filename",
"Palette filename",
"Filename to load palette from",
NULL,
G_PARAM_READWRITE |
GIMP_PARAM_NO_VALIDATE);
}
else if (! strcmp (name, SAVE_PROC))
{
procedure = gimp_save_procedure_new (plug_in, name,
GIMP_PDB_PROC_TYPE_PLUGIN,
cel_save, NULL, NULL);
gimp_procedure_set_image_types (procedure, "RGB*, INDEXED*");
gimp_procedure_set_menu_label (procedure, _("KISS CEL"));
gimp_procedure_set_documentation (procedure,
"Exports files in KISS CEL file format",
"This plug-in exports individual KISS "
"cell files.",
name);
gimp_procedure_set_attribution (procedure,
"Nick Lamb",
"Nick Lamb <njl195@zepler.org.uk>",
"May 1998");
gimp_file_procedure_set_handles_remote (GIMP_FILE_PROCEDURE (procedure),
TRUE);
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
"cel");
GIMP_PROC_ARG_STRING (procedure, "palette-filename",
"Palette filename",
"Filename to save palette to",
NULL,
G_PARAM_READWRITE |
GIMP_PARAM_NO_VALIDATE);
}
return procedure;
}
static GimpValueArray *
cel_load (GimpProcedure *procedure,
GimpRunMode run_mode,
GFile *file,
const GimpValueArray *args,
gpointer run_data)
{
GimpValueArray *return_vals;
GimpImage *image = NULL;
gboolean needs_palette = FALSE;
GError *error = NULL;
gegl_init (NULL, NULL);
1997-11-24 22:05:25 +00:00
if (run_mode != GIMP_RUN_NONINTERACTIVE)
{
data_length = gimp_get_data_size (SAVE_PROC);
if (data_length > 0)
{
palette_file = g_malloc (data_length);
gimp_get_data (SAVE_PROC, palette_file);
}
else
{
palette_file = g_strdup ("*.kcf");
data_length = strlen (palette_file) + 1;
}
}
if (run_mode == GIMP_RUN_NONINTERACTIVE)
{
palette_file = (gchar *) GIMP_VALUES_GET_STRING (args, 0);
if (palette_file)
data_length = strlen (palette_file) + 1;
else
data_length = 0;
}
else if (run_mode == GIMP_RUN_INTERACTIVE)
{
/* Let user choose KCF palette (cancel ignores) */
needs_palette = need_palette (file, &error);
if (! error)
{
if (needs_palette)
palette_dialog (_("Load KISS Palette"));
gimp_set_data (SAVE_PROC, palette_file, data_length);
}
1997-11-24 22:05:25 +00:00
}
if (! error)
{
image = load_image (file, &error);
}
if (! image)
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_EXECUTION_ERROR,
error);
return_vals = gimp_procedure_new_return_values (procedure,
GIMP_PDB_SUCCESS,
NULL);
GIMP_VALUES_SET_IMAGE (return_vals, 1, image);
return return_vals;
}
static GimpValueArray *
cel_save (GimpProcedure *procedure,
GimpRunMode run_mode,
GimpImage *image,
gint n_drawables,
GimpDrawable **drawables,
GFile *file,
const GimpValueArray *args,
gpointer run_data)
{
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpExportReturn export = GIMP_EXPORT_CANCEL;
GError *error = NULL;
gegl_init (NULL, NULL);
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
case GIMP_RUN_WITH_LAST_VALS:
gimp_ui_init (PLUG_IN_BINARY);
export = gimp_export_image (&image, &n_drawables, &drawables, "CEL",
GIMP_EXPORT_CAN_HANDLE_RGB |
GIMP_EXPORT_CAN_HANDLE_ALPHA |
GIMP_EXPORT_CAN_HANDLE_INDEXED);
if (export == GIMP_EXPORT_CANCEL)
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_CANCEL,
NULL);
break;
default:
break;
}
if (n_drawables != 1)
{
g_set_error (&error, G_FILE_ERROR, 0,
_("CEL format does not support multiple layers."));
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_CALLING_ERROR,
error);
}
if (save_image (file, image, drawables[0], &error))
{
if (data_length)
{
gimp_set_data (SAVE_PROC, palette_file, data_length);
}
}
else
{
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-25 17:46:56 +00:00
if (export == GIMP_EXPORT_EXPORT)
{
gimp_image_delete (image);
g_free (drawables);
}
return gimp_procedure_new_return_values (procedure, status, error);
1997-11-24 22:05:25 +00:00
}
/* Peek into the file to determine whether we need a palette */
static gboolean
need_palette (GFile *file,
GError **error)
{
FILE *fp;
guchar header[32];
size_t n_read;
fp = g_fopen (g_file_peek_path (file), "rb");
if (! fp)
{
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
_("Could not open '%s' for reading: %s"),
gimp_file_get_utf8_name (file), g_strerror (errno));
return FALSE;
}
n_read = fread (header, 32, 1, fp);
fclose (fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("EOF or error while reading image header"));
return FALSE;
}
return (header[5] < 32);
}
/* Load CEL image into GIMP */
1997-11-24 22:05:25 +00:00
static GimpImage *
load_image (GFile *file,
GError **error)
{
2012-11-19 18:43:35 +01:00
FILE *fp; /* Read file pointer */
guchar header[32], /* File header */
file_mark, /* KiSS file type */
bpp; /* Bits per pixel */
gint height, width, /* Dimensions of image */
offx, offy, /* Layer offsets */
colors; /* Number of colors */
2012-11-19 18:43:35 +01:00
GimpImage *image; /* Image */
GimpLayer *layer; /* Layer */
2012-11-19 18:43:35 +01:00
guchar *buf; /* Temporary buffer */
guchar *line; /* Pixel data */
GeglBuffer *buffer; /* Buffer for layer */
gint i, j, k; /* Counters */
size_t n_read; /* Number of items read from file */
1997-11-24 22:05:25 +00:00
gimp_progress_init_printf (_("Opening '%s'"),
gimp_file_get_utf8_name (file));
1997-11-24 22:05:25 +00:00
/* Open the file for reading */
fp = g_fopen (g_file_peek_path (file), "r");
1997-11-24 22:05:25 +00:00
if (fp == NULL)
{
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
_("Could not open '%s' for reading: %s"),
gimp_file_get_utf8_name (file), g_strerror (errno));
return NULL;
}
/* Get the image dimensions and create the image... */
n_read = fread (header, 4, 1, fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("EOF or error while reading image header"));
fclose (fp);
return NULL;
}
if (strncmp ((const gchar *) header, "KiSS", 4))
{
colors= 16;
bpp = 4;
width = header[0] + (256 * header[1]);
height = header[2] + (256 * header[3]);
offx= 0;
offy= 0;
1997-11-24 22:05:25 +00:00
}
else
{ /* New-style image file, read full header */
n_read = fread (header, 28, 1, fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("EOF or error while reading image header"));
fclose (fp);
return NULL;
}
file_mark = header[0];
if (file_mark != 0x20 && file_mark != 0x21)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("is not a CEL image file"));
fclose (fp);
return NULL;
}
bpp = header[1];
switch (bpp)
{
case 4:
case 8:
case 32:
colors = (1 << bpp);
break;
default:
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("illegal bpp value in image: %hhu"), bpp);
fclose (fp);
return NULL;
}
width = header[4] + (256 * header[5]);
height = header[6] + (256 * header[7]);
offx = header[8] + (256 * header[9]);
offy = header[10] + (256 * header[11]);
}
if ((width == 0) || (height == 0) || (width + offx > GIMP_MAX_IMAGE_SIZE) ||
(height + offy > GIMP_MAX_IMAGE_SIZE))
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("illegal image dimensions: width: %d, horizontal offset: "
"%d, height: %d, vertical offset: %d"),
width, offx, height, offy);
fclose (fp);
return NULL;
}
if (bpp == 32)
image = gimp_image_new (width + offx, height + offy, GIMP_RGB);
else
image = gimp_image_new (width + offx, height + offy, GIMP_INDEXED);
if (! image)
{
g_set_error (error, 0, 0, _("Can't create a new image"));
2010-11-09 16:03:47 -02:00
fclose (fp);
return NULL;
}
/* Create an indexed-alpha layer to hold the image... */
if (bpp == 32)
layer = gimp_layer_new (image, _("Background"), width, height,
GIMP_RGBA_IMAGE,
100,
gimp_image_get_default_new_layer_mode (image));
else
layer = gimp_layer_new (image, _("Background"), width, height,
GIMP_INDEXEDA_IMAGE,
100,
gimp_image_get_default_new_layer_mode (image));
gimp_image_insert_layer (image, layer, NULL, 0);
gimp_layer_set_offsets (layer, offx, offy);
/* Get the drawable and set the pixel region for our load... */
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
/* Read the image in and give it to GIMP a line at a time */
2012-11-19 18:43:35 +01:00
buf = g_new (guchar, width * 4);
line = g_new (guchar, (width + 1) * 4);
for (i = 0; i < height && !feof(fp); ++i)
{
switch (bpp)
{
case 4:
2012-11-19 18:43:35 +01:00
n_read = fread (buf, (width + 1) / 2, 1, fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("EOF or error while reading image data"));
fclose (fp);
return NULL;
}
2012-11-19 18:43:35 +01:00
for (j = 0, k = 0; j < width * 2; j+= 4, ++k)
{
2012-11-19 18:43:35 +01:00
if (buf[k] / 16 == 0)
{
2012-11-19 18:43:35 +01:00
line[j] = 16;
line[j+ 1 ] = 0;
}
else
{
2012-11-19 18:43:35 +01:00
line[j] = (buf[k] / 16) - 1;
line[j + 1] = 255;
}
2012-11-19 18:43:35 +01:00
if (buf[k] % 16 == 0)
{
2012-11-19 18:43:35 +01:00
line[j + 2] = 16;
line[j + 3] = 0;
}
else
{
2012-11-19 18:43:35 +01:00
line[j + 2] = (buf[k] % 16) - 1;
line[j + 3] = 255;
}
}
break;
case 8:
2012-11-19 18:43:35 +01:00
n_read = fread (buf, width, 1, fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("EOF or error while reading image data"));
fclose (fp);
return NULL;
}
2012-11-19 18:43:35 +01:00
for (j = 0, k = 0; j < width * 2; j+= 2, ++k)
{
2012-11-19 18:43:35 +01:00
if (buf[k] == 0)
{
2012-11-19 18:43:35 +01:00
line[j] = 255;
line[j + 1] = 0;
}
else
{
2012-11-19 18:43:35 +01:00
line[j] = buf[k] - 1;
line[j + 1] = 255;
}
}
break;
case 32:
2012-11-19 18:43:35 +01:00
n_read = fread (line, width * 4, 1, fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("EOF or error while reading image data"));
fclose (fp);
return NULL;
}
/* The CEL file order is BGR so we need to swap B and R
* to get the Gimp RGB order.
*/
for (j= 0; j < width; j++)
{
guint8 tmp = line[j*4];
line[j*4] = line[j*4+2];
line[j*4+2] = tmp;
}
break;
default:
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Unsupported bit depth (%d)!"), bpp);
fclose (fp);
return NULL;
}
plug-ins/FractalExplorer/Dialogs.c 2003-11-15 Michael Natterer <mitch@gimp.org> * plug-ins/FractalExplorer/Dialogs.c * plug-ins/FractalExplorer/FractalExplorer.c * plug-ins/bmp/bmpread.c * plug-ins/bmp/bmpwrite.c * plug-ins/common/CEL.c * plug-ins/common/CML_explorer.c * plug-ins/common/animoptimize.c * plug-ins/common/bz2.c * plug-ins/common/convmatrix.c * plug-ins/common/curve_bend.c * plug-ins/common/dicom.c * plug-ins/common/gauss_iir.c * plug-ins/common/gauss_rle.c * plug-ins/common/gbr.c * plug-ins/common/gif.c * plug-ins/common/gifload.c * plug-ins/common/gih.c * plug-ins/common/grid.c * plug-ins/common/gtm.c * plug-ins/common/gz.c * plug-ins/common/hrz.c * plug-ins/common/jpeg.c * plug-ins/common/mail.c * plug-ins/common/mapcolor.c * plug-ins/common/pat.c * plug-ins/common/pcx.c * plug-ins/common/pix.c * plug-ins/common/png.c * plug-ins/common/pnm.c * plug-ins/common/ps.c * plug-ins/common/psd.c * plug-ins/common/psd_save.c * plug-ins/common/psp.c * plug-ins/common/sel_gauss.c * plug-ins/common/spheredesigner.c * plug-ins/common/sunras.c * plug-ins/common/svg.c * plug-ins/common/tga.c * plug-ins/common/tiff.c * plug-ins/common/wmf.c * plug-ins/common/xbm.c * plug-ins/common/xwd.c * plug-ins/faxg3/faxg3.c * plug-ins/fits/fits.c * plug-ins/flame/flame.c * plug-ins/gfig/gfig.c * plug-ins/gflare/gflare.c * plug-ins/gfli/gfli.c * plug-ins/gimpressionist/brush.c * plug-ins/gimpressionist/ppmtool.c * plug-ins/helpbrowser/domain.c * plug-ins/ifscompose/ifscompose.c * plug-ins/sgi/sgi.c * plug-ins/twain/twain.c * plug-ins/winsnap/winsnap.c * plug-ins/xjt/xjt.c: removed explicit newlines from messages. Made file open/save messages the same all over the place. Reduced number of translatable strings by adding some more "standard" messages. Removed plug-in names from messages. Added some random mnemonics. Unmarked some strings for translation and added some that were forgotten. General message cleanup. Removed trailing whitespace.
2003-11-15 13:53:33 +00:00
2012-11-19 18:43:35 +01:00
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, i, width, 1), 0,
NULL, line, GEGL_AUTO_ROWSTRIDE);
gimp_progress_update ((float) i / (float) height);
}
/* Close image files, give back allocated memory */
fclose (fp);
2012-11-19 18:43:35 +01:00
g_free (buf);
g_free (line);
if (bpp != 32)
{
/* Use palette from file or otherwise default grey palette */
2012-11-19 18:43:35 +01:00
guchar palette[256 * 3];
/* Open the file for reading if user picked one */
if (palette_file == NULL)
{
fp = NULL;
}
else
{
fp = g_fopen (palette_file, "r");
if (fp == NULL)
{
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
_("Could not open '%s' for reading: %s"),
gimp_filename_to_utf8 (palette_file),
g_strerror (errno));
return NULL;
}
}
if (fp != NULL)
{
colors = load_palette (g_file_new_for_path (palette_file), fp, palette, error);
fclose (fp);
if (colors < 0 || *error)
return NULL;
}
else
{
for (i= 0; i < colors; ++i)
{
palette[i * 3] = palette[i * 3 + 1] = palette[i * 3 + 2]= i * 256 / colors;
}
}
gimp_image_set_colormap (image, palette + 3, colors - 1);
}
/* Now get everything redrawn and hand back the finished image */
2012-11-19 18:43:35 +01:00
g_object_unref (buffer);
gimp_progress_update (1.0);
1997-11-24 22:05:25 +00:00
return image;
1997-11-24 22:05:25 +00:00
}
static gint
load_palette (GFile *file,
FILE *fp,
guchar palette[],
GError **error)
{
guchar header[32]; /* File header */
guchar buffer[2];
guchar file_mark, bpp;
gint i, colors = 0;
size_t n_read;
n_read = fread (header, 4, 1, fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': EOF or error while reading palette header"),
gimp_file_get_utf8_name (file));
return -1;
}
if (!strncmp ((const gchar *) header, "KiSS", 4))
{
n_read = fread (header+4, 28, 1, fp);
if (n_read < 1)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': EOF or error while reading palette header"),
gimp_file_get_utf8_name (file));
return -1;
}
file_mark = header[4];
if (file_mark != 0x10)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': is not a KCF palette file"),
gimp_file_get_utf8_name (file));
return -1;
}
bpp = header[5];
if (bpp != 12 && bpp != 24)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': illegal bpp value in palette: %hhu"),
gimp_file_get_utf8_name (file), bpp);
return -1;
}
colors = header[8] + header[9] * 256;
if (colors != 16 && colors != 256)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': illegal number of colors: %u"),
gimp_file_get_utf8_name (file), colors);
return -1;
}
switch (bpp)
{
case 12:
for (i = 0; i < colors; ++i)
{
n_read = fread (buffer, 1, 2, fp);
if (n_read < 2)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': EOF or error while reading "
"palette data"),
gimp_file_get_utf8_name (file));
return -1;
}
palette[i*3]= buffer[0] & 0xf0;
palette[i*3+1]= (buffer[1] & 0x0f) * 16;
palette[i*3+2]= (buffer[0] & 0x0f) * 16;
}
break;
case 24:
n_read = fread (palette, colors, 3, fp);
if (n_read < 3)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': EOF or error while reading palette data"),
gimp_file_get_utf8_name (file));
return -1;
}
break;
default:
g_assert_not_reached ();
}
}
else
{
colors = 16;
fseek (fp, 0, SEEK_SET);
for (i= 0; i < colors; ++i)
{
n_read = fread (buffer, 1, 2, fp);
if (n_read < 2)
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("'%s': EOF or error while reading palette data"),
gimp_file_get_utf8_name (file));
return -1;
}
palette[i*3] = buffer[0] & 0xf0;
palette[i*3+1] = (buffer[1] & 0x0f) * 16;
palette[i*3+2] = (buffer[0] & 0x0f) * 16;
}
}
return colors;
}
static gboolean
save_image (GFile *file,
GimpImage *image,
GimpDrawable *drawable,
GError **error)
{
2014-10-27 23:08:41 +01:00
GOutputStream *output;
2012-11-19 18:43:35 +01:00
GeglBuffer *buffer;
const Babl *format;
GCancellable *cancellable;
2012-11-19 18:43:35 +01:00
gint width;
gint height;
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 14:37:00 +00:00
guchar header[32]; /* File header */
gint bpp; /* Bit per pixel */
2014-10-27 23:08:41 +01:00
gint colors; /* Number of colors */
gint type; /* type of layer */
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 14:37:00 +00:00
gint offx, offy; /* Layer offsets */
2014-10-27 23:08:41 +01:00
guchar *buf = NULL; /* Temporary buffer */
guchar *line = NULL; /* Pixel data */
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 14:37:00 +00:00
gint i, j, k; /* Counters */
1997-11-24 22:05:25 +00:00
/* Check that this is an indexed image, fail otherwise */
type = gimp_drawable_type (drawable);
2012-11-19 18:43:35 +01:00
if (type == GIMP_INDEXEDA_IMAGE)
{
bpp = 4;
format = NULL;
}
else
2012-11-19 18:43:35 +01:00
{
bpp = 32;
format = babl_format ("R'G'B'A u8");
}
/* Find out how offset this layer was */
gimp_drawable_get_offsets (drawable, &offx, &offy);
buffer = gimp_drawable_get_buffer (drawable);
2012-11-19 18:43:35 +01:00
width = gegl_buffer_get_width (buffer);
height = gegl_buffer_get_height (buffer);
1997-11-24 22:05:25 +00:00
gimp_progress_init_printf (_("Exporting '%s'"),
2014-10-27 23:08:41 +01:00
gimp_file_get_utf8_name (file));
output = G_OUTPUT_STREAM (g_file_replace (file,
NULL, FALSE, G_FILE_CREATE_NONE,
NULL, error));
if (output)
{
GOutputStream *buffered;
2014-10-27 23:08:41 +01:00
buffered = g_buffered_output_stream_new (output);
g_object_unref (output);
1997-11-24 22:05:25 +00:00
2014-10-27 23:08:41 +01:00
output = buffered;
}
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-25 17:46:56 +00:00
return FALSE;
}
/* Headers */
memset (header, 0, 32);
strcpy ((gchar *) header, "KiSS");
1997-11-24 22:05:25 +00:00
header[4]= 0x20;
/* Work out whether to save as 8bit or 4bit */
if (bpp < 32)
{
g_free (gimp_image_get_colormap (image, NULL, &colors));
2012-11-19 18:43:35 +01:00
if (colors > 15)
{
header[5] = 8;
}
else
{
header[5] = 4;
}
}
else
2012-11-19 18:43:35 +01:00
{
header[5] = 32;
}
1997-11-24 22:05:25 +00:00
/* Fill in the blanks ... */
2012-11-19 18:43:35 +01:00
header[8] = width % 256;
header[9] = width / 256;
header[10] = height % 256;
header[11] = height / 256;
header[12] = offx % 256;
header[13] = offx / 256;
header[14] = offy % 256;
header[15] = offy / 256;
2014-10-27 23:08:41 +01:00
if (! g_output_stream_write_all (output, header, 32, NULL,
NULL, error))
goto fail;
/* Arrange for memory etc. */
2012-11-19 18:43:35 +01:00
buf = g_new (guchar, width * 4);
line = g_new (guchar, (width + 1) * 4);
/* Get the image from GIMP one line at a time and write it out */
2012-11-19 18:43:35 +01:00
for (i = 0; i < height; ++i)
{
2012-11-19 18:43:35 +01:00
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, i, width, 1), 1.0,
format, line,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
memset (buf, 0, width);
if (bpp == 32)
{
2012-11-19 18:43:35 +01:00
for (j = 0; j < width; j++)
{
2012-11-19 18:43:35 +01:00
buf[4 * j] = line[4 * j + 2]; /* B */
buf[4 * j + 1] = line[4 * j + 1]; /* G */
buf[4 * j + 2] = line[4 * j + 0]; /* R */
buf[4 * j + 3] = line[4 * j + 3]; /* Alpha */
}
2012-11-19 18:43:35 +01:00
2014-10-27 23:08:41 +01:00
if (! g_output_stream_write_all (output, buf, width * 4, NULL,
NULL, error))
goto fail;
}
else if (colors > 16)
{
2012-11-19 18:43:35 +01:00
for (j = 0, k = 0; j < width * 2; j += 2, ++k)
{
2012-11-19 18:43:35 +01:00
if (line[j + 1] > 127)
{
2012-11-19 18:43:35 +01:00
buf[k]= line[j] + 1;
}
}
2012-11-19 18:43:35 +01:00
2014-10-27 23:08:41 +01:00
if (! g_output_stream_write_all (output, buf, width, NULL,
NULL, error))
goto fail;
}
else
{
2012-11-19 18:43:35 +01:00
for (j = 0, k = 0; j < width * 2; j+= 4, ++k)
{
2012-11-19 18:43:35 +01:00
buf[k] = 0;
if (line[j + 1] > 127)
{
2012-11-19 18:43:35 +01:00
buf[k] += (line[j] + 1)<< 4;
}
2012-11-19 18:43:35 +01:00
if (line[j + 3] > 127)
{
2012-11-19 18:43:35 +01:00
buf[k] += (line[j + 2] + 1);
}
}
2012-11-19 18:43:35 +01:00
2014-10-27 23:08:41 +01:00
if (! g_output_stream_write_all (output, buf, width + 1 / 2, NULL,
NULL, error))
goto fail;
}
2012-11-19 18:43:35 +01:00
gimp_progress_update ((float) i / (float) height);
}
1997-11-24 22:05:25 +00:00
2014-10-27 23:08:41 +01:00
if (! g_output_stream_close (output, NULL, error))
goto fail;
gimp_progress_update (1.0);
2012-11-19 18:43:35 +01:00
g_free (buf);
g_free (line);
2012-11-19 18:43:35 +01:00
g_object_unref (buffer);
2014-10-27 23:08:41 +01:00
g_object_unref (output);
1997-11-24 22:05:25 +00:00
return TRUE;
2014-10-27 23:08:41 +01:00
fail:
cancellable = g_cancellable_new ();
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
2014-10-27 23:08:41 +01:00
g_free (buf);
g_free (line);
g_object_unref (buffer);
g_object_unref (output);
return FALSE;
1997-11-24 22:05:25 +00: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-25 17:46:56 +00:00
static void
palette_dialog (const gchar *title)
{
GtkWidget *dialog;
gimp_ui_init (PLUG_IN_BINARY);
dialog = gtk_file_chooser_dialog_new (title, NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Open"), GTK_RESPONSE_OK,
NULL);
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
GTK_RESPONSE_OK,
GTK_RESPONSE_CANCEL,
-1);
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), palette_file);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_widget_show (dialog);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
{
g_free (palette_file);
palette_file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
data_length = strlen (palette_file) + 1;
}
gtk_widget_destroy (dialog);
}