gimp/plug-ins/file-tiff/file-tiff-load.c

1982 lines
65 KiB
C
Raw Normal View History

/* tiff loading for GIMP
1997-11-25 06:05:25 +08:00
* -Peter Mattis
*
* The TIFF loading code has been completely revamped by Nick Lamb
* njl195@zepler.org.uk -- 18 May 1998
* And it now gains support for tiles (and doubtless a zillion bugs)
* njl195@zepler.org.uk -- 12 June 1999
* LZW patent fuss continues :(
* njl195@zepler.org.uk -- 20 April 2000
1997-11-25 06:05:25 +08:00
* The code for this filter is based on "tifftopnm" and "pnmtotiff",
* 2 programs that are a part of the netpbm package.
* khk@khk.net -- 13 May 2000
* Added support for ICCPROFILE tiff tag. If this tag is present in a
* TIFF file, then a parasite is created and vice versa.
* peter@kirchgessner.net -- 29 Oct 2002
* Progress bar only when run interactive
* Added support for layer offsets - pablo.dangelo@web.de -- 7 Jan 2004
* Honor EXTRASAMPLES tag while loading images with alphachannel
* pablo.dangelo@web.de -- 16 Jan 2004
1997-11-25 06:05:25 +08:00
*/
/*
* tifftopnm.c - converts a Tagged Image File to a portable anymap
*
* Derived by Jef Poskanzer from tif2ras.c, which is:
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Author: Patrick J. Naughton
* naughton@wind.sun.com
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* This file is provided AS IS with no warranties of any kind. The author
* shall have no liability with respect to the infringement of copyrights,
* trade secrets or any patents by this file or any part thereof. In no
* event will the author be liable for any lost revenue or profits or
* other special, indirect and consequential damages.
*/
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
#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 <string.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
1997-11-25 06:05:25 +08:00
#include <tiffio.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
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
#include "file-tiff-io.h"
#include "file-tiff-load.h"
#include "libgimp/stdplugins-intl.h"
#define PLUG_IN_ROLE "gimp-file-tiff-load"
1997-11-25 06:05:25 +08:00
typedef struct
{
gint compression;
gint fillorder;
gboolean save_transp_pixels;
1997-11-25 06:05:25 +08:00
} TiffSaveVals;
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
typedef struct
{
gint32 ID;
GeglBuffer *buffer;
const Babl *format;
guchar *pixels;
guchar *pixel;
} ChannelData;
typedef enum
{
GIMP_TIFF_LOAD_ASSOCALPHA,
GIMP_TIFF_LOAD_UNASSALPHA,
GIMP_TIFF_LOAD_CHANNEL
} DefaultExtra;
/* Declare some local functions */
static GimpColorProfile * load_profile (TIFF *tif);
static void load_rgba (TIFF *tif,
ChannelData *channel);
static void load_contiguous (TIFF *tif,
ChannelData *channel,
const Babl *type,
gushort bps,
gushort spp,
gboolean is_bw,
gint extra);
static void load_separate (TIFF *tif,
ChannelData *channel,
const Babl *type,
gushort bps,
gushort spp,
gboolean is_bw,
gint extra);
static void load_paths (TIFF *tif,
gint image,
gint width,
gint height,
gint offset_x,
gint offset_y);
static void fill_bit2byte (void);
static void convert_bit2byte (const guchar *src,
guchar *dest,
gint width,
gint height);
static gboolean load_dialog (TIFF *tif,
const gchar *help_id,
TiffSelectedPages *pages,
const gchar *extra_message,
DefaultExtra *default_extra);
1997-11-25 06:05:25 +08:00
static TiffSaveVals tsvals =
{
COMPRESSION_NONE, /* compression */
TRUE, /* alpha handling */
1997-11-25 06:05:25 +08:00
};
/* returns a pointer into the TIFF */
static const gchar *
tiff_get_page_name (TIFF *tif)
{
static gchar *name;
if (TIFFGetField (tif, TIFFTAG_PAGENAME, &name) &&
g_utf8_validate (name, -1, NULL))
{
return name;
}
return NULL;
}
GimpPDBStatusType
load_image (GFile *file,
GimpRunMode run_mode,
gint32 *image,
gboolean *resolution_loaded,
gboolean *profile_loaded,
GError **error)
{
TIFF *tif;
TiffSelectedPages pages;
GList *images_list = NULL;
DefaultExtra default_extra = GIMP_TIFF_LOAD_UNASSALPHA;
gint first_image_type = GIMP_RGB;
gint min_row = G_MAXINT;
gint min_col = G_MAXINT;
gint max_row = 0;
gint max_col = 0;
gint li;
*image = 0;
gimp_progress_init_printf (_("Opening '%s'"),
gimp_file_get_utf8_name (file));
tif = tiff_open (file, "r", error);
if (! tif)
return GIMP_PDB_EXECUTION_ERROR;
pages.target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
gimp_get_data (LOAD_PROC "-target", &pages.target);
pages.keep_empty_space = TRUE;
gimp_get_data (LOAD_PROC "-keep-empty-space",
&pages.keep_empty_space);
pages.n_pages = pages.o_pages = TIFFNumberOfDirectories (tif);
if (pages.n_pages == 0)
{
TIFFClose (tif);
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("TIFF '%s' does not contain any directories"),
gimp_file_get_utf8_name (file));
return GIMP_PDB_EXECUTION_ERROR;
}
pages.pages = NULL;
if (run_mode != GIMP_RUN_INTERACTIVE)
{
pages.pages = g_new (gint, pages.n_pages);
for (li = 0; li < pages.n_pages; li++)
pages.pages[li] = li;
}
else
{
const gchar *extra_message = NULL;
if (pages.n_pages == 1)
{
pages.pages = g_new0 (gint, pages.n_pages);
pages.target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
}
/* Check all pages if any has an unspecified or unset channel. */
for (li = 0; li < pages.n_pages; li++)
{
gushort spp;
gushort photomet;
gushort extra;
gushort *extra_types;
TIFFSetDirectory (tif, li);
TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
if (! TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet))
{
guint16 compression;
if (TIFFGetField (tif, TIFFTAG_COMPRESSION, &compression) &&
(compression == COMPRESSION_CCITTFAX3 ||
compression == COMPRESSION_CCITTFAX4 ||
compression == COMPRESSION_CCITTRLE ||
compression == COMPRESSION_CCITTRLEW))
{
photomet = PHOTOMETRIC_MINISWHITE;
}
else
{
/* old AppleScan software misses out the photometric tag
* (and incidentally assumes min-is-white, but xv
* assumes min-is-black, so we follow xv's lead. It's
* not much hardship to invert the image later).
*/
photomet = PHOTOMETRIC_MINISBLACK;
}
}
if (! TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
extra = 0;
/* TODO: current code always assumes that the alpha channel
* will be the first extra channel, though the TIFF spec does
* not mandate such assumption. A future improvement should be
* to actually loop through the extra channels and save the
* alpha channel index.
* Of course, this is an edge case, as most image would likely
* have only a single extra channel anyway. But still we could
* be more accurate.
*/
if (extra > 0 && (extra_types[0] == EXTRASAMPLE_UNSPECIFIED))
{
extra_message = _("Extra channels with unspecified data.");
break;
}
else if (extra == 0 &&
((photomet == PHOTOMETRIC_RGB && spp > 3) ||
/* All other color space expect 1 channel (grayscale,
* palette, mask). */
(photomet != PHOTOMETRIC_RGB && spp > 1)))
{
/* ExtraSamples field not set, yet we have more channels than
* the PhotometricInterpretation field suggests.
* This should not happen as the spec clearly says "This field
* must be present if there are extra samples". So the files
* can be considered non-conformant.
* Let's ask what to do with the channel.
*/
extra_message = _("Non-conformant TIFF: extra channels without 'ExtraSamples' field.");
break;
}
}
TIFFSetDirectory (tif, 0);
if ((pages.n_pages > 1 || extra_message) &&
! load_dialog (tif, LOAD_PROC, &pages,
extra_message, &default_extra))
{
TIFFClose (tif);
g_clear_pointer (&pages.pages, g_free);
return GIMP_PDB_CANCEL;
}
}
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_set_data (LOAD_PROC "-target",
&pages.target, sizeof (pages.target));
gimp_set_data (LOAD_PROC "-keep-empty-space",
&pages.keep_empty_space,
sizeof (pages.keep_empty_space));
/* We will loop through the all pages in case of multipage TIFF
* and load every page as a separate layer.
*/
for (li = 0; li < pages.n_pages; li++)
{
gint ilayer;
gushort bps;
gushort spp;
gushort photomet;
gshort sampleformat;
GimpColorProfile *profile;
gboolean profile_linear = FALSE;
GimpPrecision image_precision;
const Babl *type;
const Babl *base_format = NULL;
guint16 orientation;
gint cols;
gint rows;
gboolean alpha;
gint image_type = GIMP_RGB;
gint layer;
gint layer_type = GIMP_RGB_IMAGE;
float layer_offset_x = 0.0;
float layer_offset_y = 0.0;
gint layer_offset_x_pixel = 0;
gint layer_offset_y_pixel = 0;
gushort extra;
gushort *extra_types;
ChannelData *channel = NULL;
uint16 planar = PLANARCONFIG_CONTIG;
gboolean is_bw;
gint i;
gboolean worst_case = FALSE;
TiffSaveVals save_vals;
const gchar *name;
TIFFSetDirectory (tif, pages.pages[li]);
ilayer = pages.pages[li];
gimp_progress_update (0.0);
TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, &bps);
TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLEFORMAT, &sampleformat);
profile = load_profile (tif);
if (profile)
{
if (! *image)
*profile_loaded = TRUE;
profile_linear = gimp_color_profile_is_linear (profile);
}
if (bps > 8 && bps != 8 && bps != 16 && bps != 32 && bps != 64)
worst_case = TRUE; /* Wrong sample width => RGBA */
switch (bps)
{
case 1:
case 8:
if (profile_linear)
image_precision = GIMP_PRECISION_U8_LINEAR;
else
Initial space invasion commit in GIMP All babl formats now have a space equivalent to a color profile, determining the format's primaries and TRCs. This commit makes GIMP aware of this. libgimp: - enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA as deprecated aliases, add PERCEPTUAL values so we now have LINEAR, NON_LINEAR and PERCPTUAL for each encoding, matching the babl encoding variants RGB, R'G'B' and R~G~B~. - gimp_color_transform_can_gegl_copy() now returns TRUE if both profiles can return a babl space, increasing the amount of fast babl color conversions significantly. - TODO: no solution yet for getting libgimp drawable proxy buffers in the right format with space. plug-ins: - follow the GimpPrecision change. - TODO: everything else unchanged and partly broken or sub-optimal, like setting a new image's color profile too late. app: - add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as replacement for all "linear" booleans. - change gimp-babl functions to take babl spaces and GimpTRCType parameters and support all sorts of new perceptual ~ formats. - a lot of places changed in the early days of goat invasion didn't take advantage of gimp-babl utility functions and constructed formats manually. They all needed revisiting and many now use much simpler code calling gimp-babl API. - change gimp_babl_format_get_color_profile() to really extract a newly allocated color profile from the format, and add gimp_babl_get_builtin_color_profile() which does the same as gimp_babl_format_get_color_profile() did before. Visited all callers to decide whether they are looking for the format's actual profile, or for one of the builtin profiles, simplifying code that only needs builtin profiles. - drawables have a new get_space_api(), get_linear() is now get_trc(). - images now have a "layer space" and an API to get it, gimp_image_get_layer_format() returns formats in that space. - an image's layer space is created from the image's color profile, change gimpimage-color-profile to deal with that correctly - change many babl_format() calls to babl_format_with_space() and take the space from passed formats or drawables - add function gimp_layer_fix_format_space() which replaces the layer's buffer with one that has the image's layer format, but doesn't change pixel values - use gimp_layer_fix_format_space() to make sure layers loaded from XCF and created by plug-ins have the right space when added to the image, because it's impossible to always assign the right space upon layer creation - "assign color profile" and "discard color profile" now require use of gimp_layer_fix_format_space() too because the profile is now embedded in all formats via the space. Add gimp_image_assign_color_profile() which does all that and call it instead of a simple gimp_image_set_color_profile(), also from the PDB set-color-profile functions, which are essentially "assign" and "discard" calls. - generally, make sure a new image's color profile is set before adding layers to it, gimp_image_set_color_profile() is more than before considered know-what-you-are-doing API. - take special precaution in all places that call gimp_drawable_convert_type(), we now must pass a new_profile from all callers that convert layers within the same image (such as image_convert_type, image_convert_precision), because the layer's new space can't be determined from the image's layer format during the call. - change all "linear" properties to "trc", in all config objects like for levels and curves, in the histogram, in the widgets. This results in some GUI that now has three choices instead of two. TODO: we might want to reduce that back to two later. - keep "linear" boolean properties around as compat if needed for file pasring, but always convert the parsed parsed boolean to GimpTRCType. - TODO: the image's "enable color management" switch is currently broken, will fix that in another commit.
2018-07-21 20:23:01 +08:00
image_precision = GIMP_PRECISION_U8_NON_LINEAR;
type = babl_type ("u8");
break;
case 16:
if (sampleformat == SAMPLEFORMAT_IEEEFP)
{
if (profile_linear)
image_precision = GIMP_PRECISION_HALF_LINEAR;
else
Initial space invasion commit in GIMP All babl formats now have a space equivalent to a color profile, determining the format's primaries and TRCs. This commit makes GIMP aware of this. libgimp: - enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA as deprecated aliases, add PERCEPTUAL values so we now have LINEAR, NON_LINEAR and PERCPTUAL for each encoding, matching the babl encoding variants RGB, R'G'B' and R~G~B~. - gimp_color_transform_can_gegl_copy() now returns TRUE if both profiles can return a babl space, increasing the amount of fast babl color conversions significantly. - TODO: no solution yet for getting libgimp drawable proxy buffers in the right format with space. plug-ins: - follow the GimpPrecision change. - TODO: everything else unchanged and partly broken or sub-optimal, like setting a new image's color profile too late. app: - add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as replacement for all "linear" booleans. - change gimp-babl functions to take babl spaces and GimpTRCType parameters and support all sorts of new perceptual ~ formats. - a lot of places changed in the early days of goat invasion didn't take advantage of gimp-babl utility functions and constructed formats manually. They all needed revisiting and many now use much simpler code calling gimp-babl API. - change gimp_babl_format_get_color_profile() to really extract a newly allocated color profile from the format, and add gimp_babl_get_builtin_color_profile() which does the same as gimp_babl_format_get_color_profile() did before. Visited all callers to decide whether they are looking for the format's actual profile, or for one of the builtin profiles, simplifying code that only needs builtin profiles. - drawables have a new get_space_api(), get_linear() is now get_trc(). - images now have a "layer space" and an API to get it, gimp_image_get_layer_format() returns formats in that space. - an image's layer space is created from the image's color profile, change gimpimage-color-profile to deal with that correctly - change many babl_format() calls to babl_format_with_space() and take the space from passed formats or drawables - add function gimp_layer_fix_format_space() which replaces the layer's buffer with one that has the image's layer format, but doesn't change pixel values - use gimp_layer_fix_format_space() to make sure layers loaded from XCF and created by plug-ins have the right space when added to the image, because it's impossible to always assign the right space upon layer creation - "assign color profile" and "discard color profile" now require use of gimp_layer_fix_format_space() too because the profile is now embedded in all formats via the space. Add gimp_image_assign_color_profile() which does all that and call it instead of a simple gimp_image_set_color_profile(), also from the PDB set-color-profile functions, which are essentially "assign" and "discard" calls. - generally, make sure a new image's color profile is set before adding layers to it, gimp_image_set_color_profile() is more than before considered know-what-you-are-doing API. - take special precaution in all places that call gimp_drawable_convert_type(), we now must pass a new_profile from all callers that convert layers within the same image (such as image_convert_type, image_convert_precision), because the layer's new space can't be determined from the image's layer format during the call. - change all "linear" properties to "trc", in all config objects like for levels and curves, in the histogram, in the widgets. This results in some GUI that now has three choices instead of two. TODO: we might want to reduce that back to two later. - keep "linear" boolean properties around as compat if needed for file pasring, but always convert the parsed parsed boolean to GimpTRCType. - TODO: the image's "enable color management" switch is currently broken, will fix that in another commit.
2018-07-21 20:23:01 +08:00
image_precision = GIMP_PRECISION_HALF_NON_LINEAR;
type = babl_type ("half");
}
else
{
if (profile_linear)
image_precision = GIMP_PRECISION_U16_LINEAR;
else
Initial space invasion commit in GIMP All babl formats now have a space equivalent to a color profile, determining the format's primaries and TRCs. This commit makes GIMP aware of this. libgimp: - enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA as deprecated aliases, add PERCEPTUAL values so we now have LINEAR, NON_LINEAR and PERCPTUAL for each encoding, matching the babl encoding variants RGB, R'G'B' and R~G~B~. - gimp_color_transform_can_gegl_copy() now returns TRUE if both profiles can return a babl space, increasing the amount of fast babl color conversions significantly. - TODO: no solution yet for getting libgimp drawable proxy buffers in the right format with space. plug-ins: - follow the GimpPrecision change. - TODO: everything else unchanged and partly broken or sub-optimal, like setting a new image's color profile too late. app: - add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as replacement for all "linear" booleans. - change gimp-babl functions to take babl spaces and GimpTRCType parameters and support all sorts of new perceptual ~ formats. - a lot of places changed in the early days of goat invasion didn't take advantage of gimp-babl utility functions and constructed formats manually. They all needed revisiting and many now use much simpler code calling gimp-babl API. - change gimp_babl_format_get_color_profile() to really extract a newly allocated color profile from the format, and add gimp_babl_get_builtin_color_profile() which does the same as gimp_babl_format_get_color_profile() did before. Visited all callers to decide whether they are looking for the format's actual profile, or for one of the builtin profiles, simplifying code that only needs builtin profiles. - drawables have a new get_space_api(), get_linear() is now get_trc(). - images now have a "layer space" and an API to get it, gimp_image_get_layer_format() returns formats in that space. - an image's layer space is created from the image's color profile, change gimpimage-color-profile to deal with that correctly - change many babl_format() calls to babl_format_with_space() and take the space from passed formats or drawables - add function gimp_layer_fix_format_space() which replaces the layer's buffer with one that has the image's layer format, but doesn't change pixel values - use gimp_layer_fix_format_space() to make sure layers loaded from XCF and created by plug-ins have the right space when added to the image, because it's impossible to always assign the right space upon layer creation - "assign color profile" and "discard color profile" now require use of gimp_layer_fix_format_space() too because the profile is now embedded in all formats via the space. Add gimp_image_assign_color_profile() which does all that and call it instead of a simple gimp_image_set_color_profile(), also from the PDB set-color-profile functions, which are essentially "assign" and "discard" calls. - generally, make sure a new image's color profile is set before adding layers to it, gimp_image_set_color_profile() is more than before considered know-what-you-are-doing API. - take special precaution in all places that call gimp_drawable_convert_type(), we now must pass a new_profile from all callers that convert layers within the same image (such as image_convert_type, image_convert_precision), because the layer's new space can't be determined from the image's layer format during the call. - change all "linear" properties to "trc", in all config objects like for levels and curves, in the histogram, in the widgets. This results in some GUI that now has three choices instead of two. TODO: we might want to reduce that back to two later. - keep "linear" boolean properties around as compat if needed for file pasring, but always convert the parsed parsed boolean to GimpTRCType. - TODO: the image's "enable color management" switch is currently broken, will fix that in another commit.
2018-07-21 20:23:01 +08:00
image_precision = GIMP_PRECISION_U16_NON_LINEAR;
type = babl_type ("u16");
}
break;
case 32:
if (sampleformat == SAMPLEFORMAT_IEEEFP)
{
if (profile_linear)
image_precision = GIMP_PRECISION_FLOAT_LINEAR;
else
Initial space invasion commit in GIMP All babl formats now have a space equivalent to a color profile, determining the format's primaries and TRCs. This commit makes GIMP aware of this. libgimp: - enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA as deprecated aliases, add PERCEPTUAL values so we now have LINEAR, NON_LINEAR and PERCPTUAL for each encoding, matching the babl encoding variants RGB, R'G'B' and R~G~B~. - gimp_color_transform_can_gegl_copy() now returns TRUE if both profiles can return a babl space, increasing the amount of fast babl color conversions significantly. - TODO: no solution yet for getting libgimp drawable proxy buffers in the right format with space. plug-ins: - follow the GimpPrecision change. - TODO: everything else unchanged and partly broken or sub-optimal, like setting a new image's color profile too late. app: - add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as replacement for all "linear" booleans. - change gimp-babl functions to take babl spaces and GimpTRCType parameters and support all sorts of new perceptual ~ formats. - a lot of places changed in the early days of goat invasion didn't take advantage of gimp-babl utility functions and constructed formats manually. They all needed revisiting and many now use much simpler code calling gimp-babl API. - change gimp_babl_format_get_color_profile() to really extract a newly allocated color profile from the format, and add gimp_babl_get_builtin_color_profile() which does the same as gimp_babl_format_get_color_profile() did before. Visited all callers to decide whether they are looking for the format's actual profile, or for one of the builtin profiles, simplifying code that only needs builtin profiles. - drawables have a new get_space_api(), get_linear() is now get_trc(). - images now have a "layer space" and an API to get it, gimp_image_get_layer_format() returns formats in that space. - an image's layer space is created from the image's color profile, change gimpimage-color-profile to deal with that correctly - change many babl_format() calls to babl_format_with_space() and take the space from passed formats or drawables - add function gimp_layer_fix_format_space() which replaces the layer's buffer with one that has the image's layer format, but doesn't change pixel values - use gimp_layer_fix_format_space() to make sure layers loaded from XCF and created by plug-ins have the right space when added to the image, because it's impossible to always assign the right space upon layer creation - "assign color profile" and "discard color profile" now require use of gimp_layer_fix_format_space() too because the profile is now embedded in all formats via the space. Add gimp_image_assign_color_profile() which does all that and call it instead of a simple gimp_image_set_color_profile(), also from the PDB set-color-profile functions, which are essentially "assign" and "discard" calls. - generally, make sure a new image's color profile is set before adding layers to it, gimp_image_set_color_profile() is more than before considered know-what-you-are-doing API. - take special precaution in all places that call gimp_drawable_convert_type(), we now must pass a new_profile from all callers that convert layers within the same image (such as image_convert_type, image_convert_precision), because the layer's new space can't be determined from the image's layer format during the call. - change all "linear" properties to "trc", in all config objects like for levels and curves, in the histogram, in the widgets. This results in some GUI that now has three choices instead of two. TODO: we might want to reduce that back to two later. - keep "linear" boolean properties around as compat if needed for file pasring, but always convert the parsed parsed boolean to GimpTRCType. - TODO: the image's "enable color management" switch is currently broken, will fix that in another commit.
2018-07-21 20:23:01 +08:00
image_precision = GIMP_PRECISION_FLOAT_NON_LINEAR;
type = babl_type ("float");
}
else
{
if (profile_linear)
image_precision = GIMP_PRECISION_U32_LINEAR;
else
Initial space invasion commit in GIMP All babl formats now have a space equivalent to a color profile, determining the format's primaries and TRCs. This commit makes GIMP aware of this. libgimp: - enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA as deprecated aliases, add PERCEPTUAL values so we now have LINEAR, NON_LINEAR and PERCPTUAL for each encoding, matching the babl encoding variants RGB, R'G'B' and R~G~B~. - gimp_color_transform_can_gegl_copy() now returns TRUE if both profiles can return a babl space, increasing the amount of fast babl color conversions significantly. - TODO: no solution yet for getting libgimp drawable proxy buffers in the right format with space. plug-ins: - follow the GimpPrecision change. - TODO: everything else unchanged and partly broken or sub-optimal, like setting a new image's color profile too late. app: - add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as replacement for all "linear" booleans. - change gimp-babl functions to take babl spaces and GimpTRCType parameters and support all sorts of new perceptual ~ formats. - a lot of places changed in the early days of goat invasion didn't take advantage of gimp-babl utility functions and constructed formats manually. They all needed revisiting and many now use much simpler code calling gimp-babl API. - change gimp_babl_format_get_color_profile() to really extract a newly allocated color profile from the format, and add gimp_babl_get_builtin_color_profile() which does the same as gimp_babl_format_get_color_profile() did before. Visited all callers to decide whether they are looking for the format's actual profile, or for one of the builtin profiles, simplifying code that only needs builtin profiles. - drawables have a new get_space_api(), get_linear() is now get_trc(). - images now have a "layer space" and an API to get it, gimp_image_get_layer_format() returns formats in that space. - an image's layer space is created from the image's color profile, change gimpimage-color-profile to deal with that correctly - change many babl_format() calls to babl_format_with_space() and take the space from passed formats or drawables - add function gimp_layer_fix_format_space() which replaces the layer's buffer with one that has the image's layer format, but doesn't change pixel values - use gimp_layer_fix_format_space() to make sure layers loaded from XCF and created by plug-ins have the right space when added to the image, because it's impossible to always assign the right space upon layer creation - "assign color profile" and "discard color profile" now require use of gimp_layer_fix_format_space() too because the profile is now embedded in all formats via the space. Add gimp_image_assign_color_profile() which does all that and call it instead of a simple gimp_image_set_color_profile(), also from the PDB set-color-profile functions, which are essentially "assign" and "discard" calls. - generally, make sure a new image's color profile is set before adding layers to it, gimp_image_set_color_profile() is more than before considered know-what-you-are-doing API. - take special precaution in all places that call gimp_drawable_convert_type(), we now must pass a new_profile from all callers that convert layers within the same image (such as image_convert_type, image_convert_precision), because the layer's new space can't be determined from the image's layer format during the call. - change all "linear" properties to "trc", in all config objects like for levels and curves, in the histogram, in the widgets. This results in some GUI that now has three choices instead of two. TODO: we might want to reduce that back to two later. - keep "linear" boolean properties around as compat if needed for file pasring, but always convert the parsed parsed boolean to GimpTRCType. - TODO: the image's "enable color management" switch is currently broken, will fix that in another commit.
2018-07-21 20:23:01 +08:00
image_precision = GIMP_PRECISION_U32_NON_LINEAR;
type = babl_type ("u32");
}
break;
case 64:
if (profile_linear)
image_precision = GIMP_PRECISION_DOUBLE_LINEAR;
else
Initial space invasion commit in GIMP All babl formats now have a space equivalent to a color profile, determining the format's primaries and TRCs. This commit makes GIMP aware of this. libgimp: - enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA as deprecated aliases, add PERCEPTUAL values so we now have LINEAR, NON_LINEAR and PERCPTUAL for each encoding, matching the babl encoding variants RGB, R'G'B' and R~G~B~. - gimp_color_transform_can_gegl_copy() now returns TRUE if both profiles can return a babl space, increasing the amount of fast babl color conversions significantly. - TODO: no solution yet for getting libgimp drawable proxy buffers in the right format with space. plug-ins: - follow the GimpPrecision change. - TODO: everything else unchanged and partly broken or sub-optimal, like setting a new image's color profile too late. app: - add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as replacement for all "linear" booleans. - change gimp-babl functions to take babl spaces and GimpTRCType parameters and support all sorts of new perceptual ~ formats. - a lot of places changed in the early days of goat invasion didn't take advantage of gimp-babl utility functions and constructed formats manually. They all needed revisiting and many now use much simpler code calling gimp-babl API. - change gimp_babl_format_get_color_profile() to really extract a newly allocated color profile from the format, and add gimp_babl_get_builtin_color_profile() which does the same as gimp_babl_format_get_color_profile() did before. Visited all callers to decide whether they are looking for the format's actual profile, or for one of the builtin profiles, simplifying code that only needs builtin profiles. - drawables have a new get_space_api(), get_linear() is now get_trc(). - images now have a "layer space" and an API to get it, gimp_image_get_layer_format() returns formats in that space. - an image's layer space is created from the image's color profile, change gimpimage-color-profile to deal with that correctly - change many babl_format() calls to babl_format_with_space() and take the space from passed formats or drawables - add function gimp_layer_fix_format_space() which replaces the layer's buffer with one that has the image's layer format, but doesn't change pixel values - use gimp_layer_fix_format_space() to make sure layers loaded from XCF and created by plug-ins have the right space when added to the image, because it's impossible to always assign the right space upon layer creation - "assign color profile" and "discard color profile" now require use of gimp_layer_fix_format_space() too because the profile is now embedded in all formats via the space. Add gimp_image_assign_color_profile() which does all that and call it instead of a simple gimp_image_set_color_profile(), also from the PDB set-color-profile functions, which are essentially "assign" and "discard" calls. - generally, make sure a new image's color profile is set before adding layers to it, gimp_image_set_color_profile() is more than before considered know-what-you-are-doing API. - take special precaution in all places that call gimp_drawable_convert_type(), we now must pass a new_profile from all callers that convert layers within the same image (such as image_convert_type, image_convert_precision), because the layer's new space can't be determined from the image's layer format during the call. - change all "linear" properties to "trc", in all config objects like for levels and curves, in the histogram, in the widgets. This results in some GUI that now has three choices instead of two. TODO: we might want to reduce that back to two later. - keep "linear" boolean properties around as compat if needed for file pasring, but always convert the parsed parsed boolean to GimpTRCType. - TODO: the image's "enable color management" switch is currently broken, will fix that in another commit.
2018-07-21 20:23:01 +08:00
image_precision = GIMP_PRECISION_DOUBLE_NON_LINEAR;
type = babl_type ("double");
break;
default:
if (profile_linear)
image_precision = GIMP_PRECISION_U16_LINEAR;
else
Initial space invasion commit in GIMP All babl formats now have a space equivalent to a color profile, determining the format's primaries and TRCs. This commit makes GIMP aware of this. libgimp: - enum GimpPrecision: rename GAMMA values to NON_LINEAR and keep GAMMA as deprecated aliases, add PERCEPTUAL values so we now have LINEAR, NON_LINEAR and PERCPTUAL for each encoding, matching the babl encoding variants RGB, R'G'B' and R~G~B~. - gimp_color_transform_can_gegl_copy() now returns TRUE if both profiles can return a babl space, increasing the amount of fast babl color conversions significantly. - TODO: no solution yet for getting libgimp drawable proxy buffers in the right format with space. plug-ins: - follow the GimpPrecision change. - TODO: everything else unchanged and partly broken or sub-optimal, like setting a new image's color profile too late. app: - add enum GimpTRCType { LINEAR, NON_LINEAR, PERCEPTUAL } as replacement for all "linear" booleans. - change gimp-babl functions to take babl spaces and GimpTRCType parameters and support all sorts of new perceptual ~ formats. - a lot of places changed in the early days of goat invasion didn't take advantage of gimp-babl utility functions and constructed formats manually. They all needed revisiting and many now use much simpler code calling gimp-babl API. - change gimp_babl_format_get_color_profile() to really extract a newly allocated color profile from the format, and add gimp_babl_get_builtin_color_profile() which does the same as gimp_babl_format_get_color_profile() did before. Visited all callers to decide whether they are looking for the format's actual profile, or for one of the builtin profiles, simplifying code that only needs builtin profiles. - drawables have a new get_space_api(), get_linear() is now get_trc(). - images now have a "layer space" and an API to get it, gimp_image_get_layer_format() returns formats in that space. - an image's layer space is created from the image's color profile, change gimpimage-color-profile to deal with that correctly - change many babl_format() calls to babl_format_with_space() and take the space from passed formats or drawables - add function gimp_layer_fix_format_space() which replaces the layer's buffer with one that has the image's layer format, but doesn't change pixel values - use gimp_layer_fix_format_space() to make sure layers loaded from XCF and created by plug-ins have the right space when added to the image, because it's impossible to always assign the right space upon layer creation - "assign color profile" and "discard color profile" now require use of gimp_layer_fix_format_space() too because the profile is now embedded in all formats via the space. Add gimp_image_assign_color_profile() which does all that and call it instead of a simple gimp_image_set_color_profile(), also from the PDB set-color-profile functions, which are essentially "assign" and "discard" calls. - generally, make sure a new image's color profile is set before adding layers to it, gimp_image_set_color_profile() is more than before considered know-what-you-are-doing API. - take special precaution in all places that call gimp_drawable_convert_type(), we now must pass a new_profile from all callers that convert layers within the same image (such as image_convert_type, image_convert_precision), because the layer's new space can't be determined from the image's layer format during the call. - change all "linear" properties to "trc", in all config objects like for levels and curves, in the histogram, in the widgets. This results in some GUI that now has three choices instead of two. TODO: we might want to reduce that back to two later. - keep "linear" boolean properties around as compat if needed for file pasring, but always convert the parsed parsed boolean to GimpTRCType. - TODO: the image's "enable color management" switch is currently broken, will fix that in another commit.
2018-07-21 20:23:01 +08:00
image_precision = GIMP_PRECISION_U16_NON_LINEAR;
type = babl_type ("u16");
}
2012-06-07 06:06:06 +08:00
g_printerr ("bps: %d\n", bps);
TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
if (! TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
extra = 0;
if (! TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols))
{
TIFFClose (tif);
2004-01-19 11:06:04 +08:00
g_message ("Could not get image width from '%s'",
gimp_file_get_utf8_name (file));
return GIMP_PDB_EXECUTION_ERROR;
}
if (! TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows))
{
TIFFClose (tif);
2004-01-19 11:06:04 +08:00
g_message ("Could not get image length from '%s'",
gimp_file_get_utf8_name (file));
return GIMP_PDB_EXECUTION_ERROR;
}
if (! TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet))
{
guint16 compression;
if (TIFFGetField (tif, TIFFTAG_COMPRESSION, &compression) &&
(compression == COMPRESSION_CCITTFAX3 ||
compression == COMPRESSION_CCITTFAX4 ||
compression == COMPRESSION_CCITTRLE ||
compression == COMPRESSION_CCITTRLEW))
{
g_message ("Could not get photometric from '%s'. "
"Image is CCITT compressed, assuming min-is-white",
gimp_file_get_utf8_name (file));
photomet = PHOTOMETRIC_MINISWHITE;
}
else
{
g_message ("Could not get photometric from '%s'. "
"Assuming min-is-black",
gimp_file_get_utf8_name (file));
/* old AppleScan software misses out the photometric tag
* (and incidentally assumes min-is-white, but xv
* assumes min-is-black, so we follow xv's lead. It's
* not much hardship to invert the image later).
*/
photomet = PHOTOMETRIC_MINISBLACK;
}
}
1997-11-25 06:05:25 +08:00
/* test if the extrasample represents an associated alpha channel... */
if (extra > 0 && (extra_types[0] == EXTRASAMPLE_ASSOCALPHA))
{
alpha = TRUE;
tsvals.save_transp_pixels = FALSE;
extra--;
}
else if (extra > 0 && (extra_types[0] == EXTRASAMPLE_UNASSALPHA))
{
alpha = TRUE;
tsvals.save_transp_pixels = TRUE;
extra--;
}
else if (extra > 0 && (extra_types[0] == EXTRASAMPLE_UNSPECIFIED))
{
if (run_mode != GIMP_RUN_INTERACTIVE)
/* In non-interactive mode, we assume unassociated alpha if unspecified.
* We don't output messages in interactive mode as the user
* has already the ability to choose through a dialog. */
g_message ("alpha channel type not defined for file %s. "
"Assuming alpha is not premultiplied",
gimp_file_get_utf8_name (file));
switch (default_extra)
{
case GIMP_TIFF_LOAD_ASSOCALPHA:
alpha = TRUE;
tsvals.save_transp_pixels = FALSE;
break;
case GIMP_TIFF_LOAD_UNASSALPHA:
alpha = TRUE;
tsvals.save_transp_pixels = TRUE;
break;
default: /* GIMP_TIFF_LOAD_CHANNEL */
alpha = FALSE;
break;
}
extra--;
}
else /* extra == 0 */
{
if ((photomet == PHOTOMETRIC_RGB && spp > 3) ||
(photomet != PHOTOMETRIC_RGB && spp > 1))
{
if (run_mode != GIMP_RUN_INTERACTIVE)
g_message ("File '%s' does not conform to TIFF specification: "
"ExtraSamples field is not set while extra channels are present. "
"Assuming the first extra channel as non-premultiplied alpha.",
gimp_file_get_utf8_name (file));
switch (default_extra)
{
case GIMP_TIFF_LOAD_ASSOCALPHA:
alpha = TRUE;
tsvals.save_transp_pixels = FALSE;
break;
case GIMP_TIFF_LOAD_UNASSALPHA:
alpha = TRUE;
tsvals.save_transp_pixels = TRUE;
break;
default: /* GIMP_TIFF_LOAD_CHANNEL */
alpha = FALSE;
break;
}
}
else
{
alpha = FALSE;
}
}
1997-11-25 06:05:25 +08:00
if (photomet == PHOTOMETRIC_RGB && spp > 3 + (alpha ? 1 : 0) + extra)
extra = spp - 3 - (alpha ? 1 : 0);
else if (photomet != PHOTOMETRIC_RGB && spp > 1 + (alpha ? 1 : 0) + extra)
extra = spp - 1 - (alpha ? 1 : 0);
1997-11-25 06:05:25 +08:00
is_bw = FALSE;
switch (photomet)
{
case PHOTOMETRIC_MINISBLACK:
case PHOTOMETRIC_MINISWHITE:
if (bps == 1 && ! alpha && spp == 1)
{
image_type = GIMP_INDEXED;
2005-01-02 03:28:59 +08:00
layer_type = GIMP_INDEXED_IMAGE;
is_bw = TRUE;
fill_bit2byte ();
}
else
{
image_type = GIMP_GRAY;
layer_type = alpha ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
if (alpha)
{
if (tsvals.save_transp_pixels)
{
if (profile_linear)
{
base_format = babl_format_new (babl_model ("YA"),
type,
babl_component ("Y"),
babl_component ("A"),
NULL);
}
else
{
base_format = babl_format_new (babl_model ("Y'A"),
type,
babl_component ("Y'"),
babl_component ("A"),
NULL);
}
}
else
{
if (profile_linear)
{
base_format = babl_format_new (babl_model ("YaA"),
type,
babl_component ("Ya"),
babl_component ("A"),
NULL);
}
else
{
base_format = babl_format_new (babl_model ("Y'aA"),
type,
babl_component ("Y'a"),
babl_component ("A"),
NULL);
}
}
}
else
{
if (profile_linear)
{
base_format = babl_format_new (babl_model ("Y"),
type,
babl_component ("Y"),
NULL);
}
else
{
base_format = babl_format_new (babl_model ("Y'"),
type,
babl_component ("Y'"),
NULL);
}
}
}
break;
1997-11-25 06:05:25 +08:00
case PHOTOMETRIC_RGB:
image_type = GIMP_RGB;
layer_type = alpha ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
if (alpha)
{
if (tsvals.save_transp_pixels)
{
if (profile_linear)
{
base_format = babl_format_new (babl_model ("RGBA"),
type,
babl_component ("R"),
babl_component ("G"),
babl_component ("B"),
babl_component ("A"),
NULL);
}
else
{
base_format = babl_format_new (babl_model ("R'G'B'A"),
type,
babl_component ("R'"),
babl_component ("G'"),
babl_component ("B'"),
babl_component ("A"),
NULL);
}
}
else
{
if (profile_linear)
{
base_format = babl_format_new (babl_model ("RaGaBaA"),
type,
babl_component ("Ra"),
babl_component ("Ga"),
babl_component ("Ba"),
babl_component ("A"),
NULL);
}
else
{
base_format = babl_format_new (babl_model ("R'aG'aB'aA"),
type,
babl_component ("R'a"),
babl_component ("G'a"),
babl_component ("B'a"),
babl_component ("A"),
NULL);
}
}
}
else
{
if (profile_linear)
{
base_format = babl_format_new (babl_model ("RGB"),
type,
babl_component ("R"),
babl_component ("G"),
babl_component ("B"),
NULL);
}
else
{
base_format = babl_format_new (babl_model ("R'G'B'"),
type,
babl_component ("R'"),
babl_component ("G'"),
babl_component ("B'"),
NULL);
}
}
break;
1997-11-25 06:05:25 +08:00
case PHOTOMETRIC_PALETTE:
image_type = GIMP_INDEXED;
layer_type = alpha ? GIMP_INDEXEDA_IMAGE : GIMP_INDEXED_IMAGE;
break;
1997-11-25 06:05:25 +08:00
default:
2012-06-07 06:06:06 +08:00
g_printerr ("photomet: %d (%d)\n", photomet, PHOTOMETRIC_PALETTE);
worst_case = TRUE;
break;
}
/* attach a parasite containing the compression */
{
guint16 compression = COMPRESSION_NONE;
if (TIFFGetField (tif, TIFFTAG_COMPRESSION, &compression))
{
switch (compression)
{
case COMPRESSION_NONE:
case COMPRESSION_LZW:
case COMPRESSION_PACKBITS:
case COMPRESSION_DEFLATE:
case COMPRESSION_ADOBE_DEFLATE:
case COMPRESSION_JPEG:
case COMPRESSION_CCITTFAX3:
case COMPRESSION_CCITTFAX4:
break;
case COMPRESSION_OJPEG:
worst_case = TRUE;
compression = COMPRESSION_JPEG;
break;
default:
compression = COMPRESSION_NONE;
break;
}
}
save_vals.compression = compression;
}
if (worst_case)
{
image_type = GIMP_RGB;
layer_type = GIMP_RGBA_IMAGE;
if (profile_linear)
{
base_format = babl_format_new (babl_model ("RaGaBaA"),
type,
babl_component ("Ra"),
babl_component ("Ga"),
babl_component ("Ba"),
babl_component ("A"),
NULL);
}
else
{
base_format = babl_format_new (babl_model ("R'aG'aB'aA"),
type,
babl_component ("R'a"),
babl_component ("G'a"),
babl_component ("B'a"),
babl_component ("A"),
NULL);
}
}
if (pages.target == GIMP_PAGE_SELECTOR_TARGET_LAYERS)
{
if (li == 0)
{
first_image_type = image_type;
}
else if (image_type != first_image_type)
{
continue;
}
}
if ((pages.target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) || (! *image))
{
*image = gimp_image_new_with_precision (cols, rows, image_type,
image_precision);
if (*image < 1)
{
TIFFClose (tif);
g_message ("Could not create a new image: %s",
2019-08-17 04:55:16 +08:00
gimp_pdb_get_last_error (gimp_get_pdb ()));
return GIMP_PDB_EXECUTION_ERROR;
}
gimp_image_undo_disable (*image);
if (pages.target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
{
gchar *fname = g_strdup_printf ("%s-%d", g_file_get_uri (file),
ilayer);
gimp_image_set_filename (*image, fname);
g_free (fname);
images_list = g_list_prepend (images_list,
GINT_TO_POINTER (*image));
}
else if (pages.o_pages != pages.n_pages)
{
gchar *fname = g_strdup_printf (_("%s-%d-of-%d-pages"),
g_file_get_uri (file),
pages.n_pages, pages.o_pages);
gimp_image_set_filename (*image, fname);
g_free (fname);
}
else
{
gimp_image_set_filename (*image, g_file_get_uri (file));
}
}
1997-11-25 06:05:25 +08:00
/* attach color profile */
if (profile)
{
gimp_image_set_color_profile (*image, profile);
g_object_unref (profile);
}
/* attach parasites */
{
GimpParasite *parasite;
const gchar *img_desc;
parasite = gimp_parasite_new ("tiff-save-options", 0,
sizeof (save_vals), &save_vals);
gimp_image_attach_parasite (*image, parasite);
gimp_parasite_free (parasite);
/* Attach a parasite containing the image description.
* Pretend to be a gimp comment so other plugins will use this
* description as an image comment where appropriate.
*/
if (TIFFGetField (tif, TIFFTAG_IMAGEDESCRIPTION, &img_desc) &&
g_utf8_validate (img_desc, -1, NULL))
{
parasite = gimp_parasite_new ("gimp-comment",
GIMP_PARASITE_PERSISTENT,
strlen (img_desc) + 1, img_desc);
gimp_image_attach_parasite (*image, parasite);
gimp_parasite_free (parasite);
}
}
/* any resolution info in the file? */
{
gfloat xres = 72.0;
gfloat yres = 72.0;
gushort read_unit;
GimpUnit unit = GIMP_UNIT_PIXEL; /* invalid unit */
if (TIFFGetField (tif, TIFFTAG_XRESOLUTION, &xres))
{
if (TIFFGetField (tif, TIFFTAG_YRESOLUTION, &yres))
{
if (TIFFGetFieldDefaulted (tif, TIFFTAG_RESOLUTIONUNIT,
&read_unit))
{
switch (read_unit)
{
case RESUNIT_NONE:
/* ImageMagick writes files with this silly resunit */
break;
case RESUNIT_INCH:
unit = GIMP_UNIT_INCH;
break;
case RESUNIT_CENTIMETER:
xres *= 2.54;
yres *= 2.54;
unit = GIMP_UNIT_MM; /* this is our default metric unit */
break;
default:
g_message ("File error: unknown resolution "
"unit type %d, assuming dpi", read_unit);
break;
}
}
else
{
/* no res unit tag */
/* old AppleScan software produces these */
g_message ("Warning: resolution specified without "
"any units tag, assuming dpi");
}
}
else
{
/* xres but no yres */
g_message ("Warning: no y resolution info, assuming same as x");
yres = xres;
}
/* now set the new image's resolution info */
/* If it is invalid, instead of forcing 72dpi, do not set
* the resolution at all. Gimp will then use the default
* set by the user
*/
if (read_unit != RESUNIT_NONE)
{
gimp_image_set_resolution (*image, xres, yres);
if (unit != GIMP_UNIT_PIXEL)
gimp_image_set_unit (*image, unit);
*resolution_loaded = TRUE;
}
}
/* no x res tag => we assume we have no resolution info, so we
* don't care. Older versions of this plugin used to write
* files with no resolution tags at all.
*/
/* TODO: haven't caught the case where yres tag is present,
* but not xres. This is left as an exercise for the reader -
* they should feel free to shoot the author of the broken
* program that produced the damaged TIFF file in the first
* place.
*/
/* handle layer offset */
if (! TIFFGetField (tif, TIFFTAG_XPOSITION, &layer_offset_x))
layer_offset_x = 0.0;
if (! TIFFGetField (tif, TIFFTAG_YPOSITION, &layer_offset_y))
layer_offset_y = 0.0;
/* round floating point position to integer position required
* by GIMP
*/
layer_offset_x_pixel = ROUND (layer_offset_x * xres);
layer_offset_y_pixel = ROUND (layer_offset_y * yres);
}
/* Install colormap for INDEXED images only */
if (image_type == GIMP_INDEXED)
{
guchar cmap[768];
if (is_bw)
{
if (photomet == PHOTOMETRIC_MINISWHITE)
{
cmap[0] = cmap[1] = cmap[2] = 255;
cmap[3] = cmap[4] = cmap[5] = 0;
}
else
{
cmap[0] = cmap[1] = cmap[2] = 0;
cmap[3] = cmap[4] = cmap[5] = 255;
}
}
else
{
gushort *redmap;
gushort *greenmap;
gushort *bluemap;
gint i, j;
if (! TIFFGetField (tif, TIFFTAG_COLORMAP,
&redmap, &greenmap, &bluemap))
{
TIFFClose (tif);
g_message ("Could not get colormaps from '%s'",
gimp_file_get_utf8_name (file));
return GIMP_PDB_EXECUTION_ERROR;
}
for (i = 0, j = 0; i < (1 << bps); i++)
{
cmap[j++] = redmap[i] >> 8;
cmap[j++] = greenmap[i] >> 8;
cmap[j++] = bluemap[i] >> 8;
}
}
gimp_image_set_colormap (*image, cmap, (1 << bps));
}
if (pages.target != GIMP_PAGE_SELECTOR_TARGET_IMAGES)
load_paths (tif, *image, cols, rows,
layer_offset_x_pixel, layer_offset_y_pixel);
else
load_paths (tif, *image, cols, rows, 0, 0);
/* Allocate ChannelData for all channels, even the background layer */
channel = g_new0 (ChannelData, extra + 1);
1997-11-25 06:05:25 +08:00
/* try and use layer name from tiff file */
name = tiff_get_page_name (tif);
if (name)
{
layer = gimp_layer_new (*image, name,
cols, rows,
layer_type,
100,
gimp_image_get_default_new_layer_mode (*image));
}
else
{
gchar *name;
if (ilayer == 0)
name = g_strdup (_("Background"));
else
name = g_strdup_printf (_("Page %d"), ilayer);
1997-11-25 06:05:25 +08:00
layer = gimp_layer_new (*image, name,
cols, rows,
layer_type,
100,
gimp_image_get_default_new_layer_mode (*image));
g_free (name);
}
if (! base_format && image_type == GIMP_INDEXED)
{
/* can't create the palette format here, need to get it from
* an existing layer
*/
base_format = gimp_drawable_get_format (layer);
}
else
{
base_format =
babl_format_with_space (babl_format_get_encoding (base_format),
gimp_drawable_get_format (layer));
}
channel[0].ID = layer;
channel[0].buffer = gimp_drawable_get_buffer (layer);
channel[0].format = base_format;
if (extra > 0 && ! worst_case)
{
/* Add extra channels as appropriate */
for (i = 1; i <= extra; i++)
{
GimpRGB color;
gimp_rgb_set (&color, 0.0, 0.0, 0.0);
channel[i].ID = gimp_channel_new (*image, _("TIFF Channel"),
cols, rows,
100.0, &color);
gimp_image_insert_channel (*image, channel[i].ID, -1, 0);
channel[i].buffer = gimp_drawable_get_buffer (channel[i].ID);
/* Unlike color channels, we don't care about the source
* TRC for extra channels. We just want to import them
* as-is without any value conversion. Since extra
* channels are always linear in GIMP, we consider TIFF
* extra channels with unspecified data to be linear too.
* Only exception are 8-bit non-linear images whose
* channel are Y' for legacy/compatibility reasons.
*/
if (image_precision == GIMP_PRECISION_U8_NON_LINEAR)
channel[i].format = babl_format_new (babl_model ("Y'"),
type,
babl_component ("Y'"),
NULL);
else
channel[i].format = babl_format_new (babl_model ("Y"),
type,
babl_component ("Y"),
NULL);
}
}
2012-06-07 06:06:06 +08:00
TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar);
if (worst_case)
{
2012-05-19 08:51:50 +08:00
load_rgba (tif, channel);
}
2012-06-07 06:06:06 +08:00
else if (planar == PLANARCONFIG_CONTIG)
{
load_contiguous (tif, channel, type, bps, spp, is_bw, extra);
2012-06-07 06:06:06 +08:00
}
else
2012-05-19 21:31:44 +08:00
{
load_separate (tif, channel, type, bps, spp, is_bw, extra);
}
if (TIFFGetField (tif, TIFFTAG_ORIENTATION, &orientation))
{
gboolean flip_horizontal = FALSE;
gboolean flip_vertical = FALSE;
switch (orientation)
{
case ORIENTATION_TOPLEFT:
break;
case ORIENTATION_TOPRIGHT:
flip_horizontal = TRUE;
break;
case ORIENTATION_BOTRIGHT:
flip_horizontal = TRUE;
flip_vertical = TRUE;
break;
case ORIENTATION_BOTLEFT:
flip_vertical = TRUE;
break;
default:
g_warning ("Orientation %d not handled yet!", orientation);
break;
}
if (flip_horizontal)
gimp_item_transform_flip_simple (layer,
GIMP_ORIENTATION_HORIZONTAL,
TRUE /* auto_center */,
-1.0 /* axis */);
if (flip_vertical)
gimp_item_transform_flip_simple (layer,
GIMP_ORIENTATION_VERTICAL,
TRUE /* auto_center */,
-1.0 /* axis */);
}
2003-01-10 21:59:41 +08:00
for (i = 0; i <= extra; i++)
{
if (channel[i].buffer)
g_object_unref (channel[i].buffer);
}
2003-01-11 04:14:30 +08:00
g_free (channel);
channel = NULL;
2003-01-10 21:59:41 +08:00
if (pages.target != GIMP_PAGE_SELECTOR_TARGET_IMAGES)
{
/* compute bounding box of all layers read so far */
if (min_col > layer_offset_x_pixel)
min_col = layer_offset_x_pixel;
if (min_row > layer_offset_y_pixel)
min_row = layer_offset_y_pixel;
if (max_col < layer_offset_x_pixel + cols)
max_col = layer_offset_x_pixel + cols;
if (max_row < layer_offset_y_pixel + rows)
max_row = layer_offset_y_pixel + rows;
/* position the layer */
if (layer_offset_x_pixel > 0 ||
layer_offset_y_pixel > 0)
{
gimp_layer_set_offsets (layer,
layer_offset_x_pixel,
layer_offset_y_pixel);
}
}
gimp_image_insert_layer (*image, layer, -1, -1);
if (pages.target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
{
gimp_image_undo_enable (*image);
gimp_image_clean_all (*image);
}
gimp_progress_update (1.0);
}
if (pages.target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
{
GList *list = images_list;
if (list)
{
*image = GPOINTER_TO_INT (list->data);
list = g_list_next (list);
}
for (; list; list = g_list_next (list))
{
gimp_display_new (GPOINTER_TO_INT (list->data));
}
g_list_free (images_list);
}
else
{
if (pages.keep_empty_space)
{
/* unfortunately we have no idea about empty space
at the bottom/right of layers */
min_col = 0;
min_row = 0;
}
/* resize image to bounding box of all layers */
gimp_image_resize (*image,
max_col - min_col, max_row - min_row,
-min_col, -min_row);
gimp_image_undo_enable (*image);
}
g_free (pages.pages);
TIFFClose (tif);
return GIMP_PDB_SUCCESS;
}
static GimpColorProfile *
load_profile (TIFF *tif)
{
GimpColorProfile *profile = NULL;
#ifdef TIFFTAG_ICCPROFILE
/* If TIFFTAG_ICCPROFILE is defined we are dealing with a
* libtiff version that can handle ICC profiles. Otherwise just
* return a NULL profile.
*/
uint32 profile_size;
guchar *icc_profile;
/* set the ICC profile - if found in the TIFF */
if (TIFFGetField (tif, TIFFTAG_ICCPROFILE, &profile_size, &icc_profile))
{
profile = gimp_color_profile_new_from_icc_profile (icc_profile,
profile_size,
NULL);
}
#endif
return profile;
}
static void
load_rgba (TIFF *tif,
ChannelData *channel)
{
guint32 image_width;
guint32 image_height;
guint32 row;
guint32 *buffer;
2012-05-19 08:51:50 +08:00
g_printerr ("%s\n", __func__);
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &image_width);
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &image_height);
buffer = g_new (uint32, image_width * image_height);
if (! TIFFReadRGBAImage (tif, image_width, image_height, buffer, 0))
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 ("Unsupported layout, no RGBA loader");
for (row = 0; row < image_height; row++)
{
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
/* Make sure our channels are in the right order */
guint32 row_start = row * image_width;
guint32 row_end = row_start + image_width;
guint32 i;
for (i = row_start; i < row_end; i++)
buffer[i] = GUINT32_TO_LE (buffer[i]);
#endif
2012-05-19 08:51:50 +08:00
gegl_buffer_set (channel[0].buffer,
GEGL_RECTANGLE (0, image_height - row - 1,
image_width, 1),
2012-05-19 08:51:50 +08:00
0, channel[0].format,
((guchar *) buffer) + row * image_width * 4,
2012-05-19 08:51:50 +08:00
GEGL_AUTO_ROWSTRIDE);
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
if ((row % 32) == 0)
gimp_progress_update ((gdouble) row / (gdouble) image_height);
}
2012-05-19 21:31:44 +08:00
g_free (buffer);
}
1997-11-25 06:05:25 +08:00
static void
load_paths (TIFF *tif,
gint image,
gint width,
gint height,
gint offset_x,
gint offset_y)
{
gsize n_bytes;
gchar *bytes;
gint path_index;
gsize pos;
if (! TIFFGetField (tif, TIFFTAG_PHOTOSHOP, &n_bytes, &bytes))
return;
path_index = 0;
pos = 0;
while (pos < n_bytes)
{
guint16 id;
gsize len;
gchar *name;
guint32 *val32;
guint16 *val16;
if (n_bytes-pos < 7 ||
strncmp (bytes + pos, "8BIM", 4) != 0)
break;
pos += 4;
val16 = (guint16 *) (bytes + pos);
id = GUINT16_FROM_BE (*val16);
pos += 2;
2006-11-15 07:21:53 +08:00
/* g_printerr ("id: %x\n", id); */
len = (guchar) bytes[pos];
if (n_bytes - pos < len + 1)
break; /* block not big enough */
/* do we have the UTF-marker? is it valid UTF-8?
* if so, we assume an utf-8 encoded name, otherwise we
* assume iso8859-1
*/
name = bytes + pos + 1;
if (len >= 3 &&
name[0] == '\xEF' && name[1] == '\xBB' && name[2] == '\xBF' &&
g_utf8_validate (name, len, NULL))
{
name = g_strndup (name + 3, len - 3);
}
else
{
name = g_convert (name, len, "utf-8", "iso8859-1", NULL, NULL, NULL);
}
if (! name)
name = g_strdup ("(imported path)");
pos += len + 1;
if (pos % 2) /* padding */
pos++;
if (n_bytes - pos < 4)
break; /* block not big enough */
val32 = (guint32 *) (bytes + pos);
len = GUINT32_FROM_BE (*val32);
pos += 4;
if (n_bytes - pos < len)
break; /* block not big enough */
if (id >= 2000 && id <= 2998)
{
/* path information */
guint16 type;
gint rec = pos;
gint32 vectors;
gdouble *points = NULL;
gint expected_points = 0;
gint pointcount = 0;
gboolean closed = FALSE;
vectors = gimp_vectors_new (image, name);
gimp_image_insert_vectors (image, vectors, -1, path_index);
path_index++;
while (rec < pos + len)
{
/* path records */
val16 = (guint16 *) (bytes + rec);
type = GUINT16_FROM_BE (*val16);
switch (type)
{
case 0: /* new closed subpath */
case 3: /* new open subpath */
val16 = (guint16 *) (bytes + rec + 2);
expected_points = GUINT16_FROM_BE (*val16);
pointcount = 0;
closed = (type == 0);
if (n_bytes - rec < (expected_points + 1) * 26)
{
g_printerr ("not enough point records\n");
rec = pos + len;
continue;
}
if (points)
g_free (points);
points = g_new (gdouble, expected_points * 6);
break;
case 1: /* closed subpath bezier knot, linked */
case 2: /* closed subpath bezier knot, unlinked */
case 4: /* open subpath bezier knot, linked */
case 5: /* open subpath bezier knot, unlinked */
/* since we already know if the subpath is open
* or closed and since we don't differentiate between
* linked and unlinked, just treat all the same... */
if (pointcount < expected_points)
{
gint j;
for (j = 0; j < 6; j++)
{
gdouble f;
guint32 coord;
const gint size = j % 2 ? width : height;
const gint offset = j % 2 ? offset_x : offset_y;
val32 = (guint32 *) (bytes + rec + 2 + j * 4);
coord = GUINT32_FROM_BE (*val32);
f = (double) ((gchar) ((coord >> 24) & 0xFF)) +
(double) (coord & 0x00FFFFFF) /
(double) 0xFFFFFF;
/* coords are stored with vertical component
* first, gimp expects the horizontal
* component first. Sigh.
*/
points[pointcount * 6 + (j ^ 1)] = f * size + offset;
}
pointcount++;
if (pointcount == expected_points)
{
gimp_vectors_stroke_new_from_points (vectors,
GIMP_VECTORS_STROKE_TYPE_BEZIER,
pointcount * 6,
points,
closed);
}
}
else
{
g_printerr ("Oops - unexpected point record\n");
}
break;
case 6: /* path fill rule record */
case 7: /* clipboard record (?) */
case 8: /* initial fill rule record (?) */
/* we cannot use this information */
default:
break;
}
rec += 26;
}
if (points)
g_free (points);
}
pos += len;
if (pos % 2) /* padding */
pos++;
g_free (name);
}
}
static void
load_contiguous (TIFF *tif,
ChannelData *channel,
const Babl *type,
gushort bps,
gushort spp,
gboolean is_bw,
gint extra)
{
guint32 image_width;
guint32 image_height;
guint32 tile_width;
guint32 tile_height;
gint bytes_per_pixel;
const Babl *src_format;
guchar *buffer;
guchar *bw_buffer = NULL;
gdouble progress = 0.0;
gdouble one_row;
guint32 y;
gint i;
g_printerr ("%s\n", __func__);
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &image_width);
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &image_height);
2012-05-19 21:31:44 +08:00
tile_width = image_width;
2012-05-19 21:31:44 +08:00
if (TIFFIsTiled (tif))
{
TIFFGetField (tif, TIFFTAG_TILEWIDTH, &tile_width);
TIFFGetField (tif, TIFFTAG_TILELENGTH, &tile_height);
2012-05-19 21:31:44 +08:00
buffer = g_malloc (TIFFTileSize (tif));
}
else
{
tile_width = image_width;
tile_height = 1;
2012-05-19 21:31:44 +08:00
buffer = g_malloc (TIFFScanlineSize (tif));
}
if (is_bw)
bw_buffer = g_malloc (tile_width * tile_height);
one_row = (gdouble) tile_height / (gdouble) image_height;
src_format = babl_format_n (type, spp);
/* consistency check */
bytes_per_pixel = 0;
for (i = 0; i <= extra; i++)
bytes_per_pixel += babl_format_get_bytes_per_pixel (channel[i].format);
g_printerr ("bytes_per_pixel: %d, format: %d\n",
bytes_per_pixel,
babl_format_get_bytes_per_pixel (src_format));
for (y = 0; y < image_height; y += tile_height)
{
guint32 x;
for (x = 0; x < image_width; x += tile_width)
{
GeglBuffer *src_buf;
guint32 rows;
guint32 cols;
gint offset;
gimp_progress_update (progress + one_row *
((gdouble) x / (gdouble) image_width));
2012-05-19 21:31:44 +08:00
if (TIFFIsTiled (tif))
TIFFReadTile (tif, buffer, x, y, 0, 0);
else
2012-06-07 06:06:06 +08:00
TIFFReadScanline (tif, buffer, y, 0);
cols = MIN (image_width - x, tile_width);
rows = MIN (image_height - y, tile_height);
if (is_bw)
convert_bit2byte (buffer, bw_buffer, cols, rows);
src_buf = gegl_buffer_linear_new_from_data (is_bw ? bw_buffer : buffer,
2012-06-07 06:06:06 +08:00
src_format,
GEGL_RECTANGLE (0, 0, cols, rows),
tile_width * bytes_per_pixel,
2012-06-07 06:06:06 +08:00
NULL, NULL);
2012-06-07 06:06:06 +08:00
offset = 0;
2012-06-07 06:06:06 +08:00
for (i = 0; i <= extra; i++)
{
GeglBufferIterator *iter;
gint src_bpp;
gint dest_bpp;
src_bpp = babl_format_get_bytes_per_pixel (src_format);
2012-06-07 06:06:06 +08:00
dest_bpp = babl_format_get_bytes_per_pixel (channel[i].format);
2012-06-07 06:06:06 +08:00
iter = gegl_buffer_iterator_new (src_buf,
GEGL_RECTANGLE (0, 0, cols, rows),
0, NULL,
GEGL_ACCESS_READ,
GEGL_ABYSS_NONE, 2);
2012-06-07 06:06:06 +08:00
gegl_buffer_iterator_add (iter, channel[i].buffer,
GEGL_RECTANGLE (x, y, cols, rows),
2012-08-30 01:04:13 +08:00
0, channel[i].format,
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
2012-06-07 06:06:06 +08:00
while (gegl_buffer_iterator_next (iter))
{
guchar *s = iter->items[0].data;
guchar *d = iter->items[1].data;
gint length = iter->length;
2012-06-07 06:06:06 +08:00
s += offset;
while (length--)
{
memcpy (d, s, dest_bpp);
d += dest_bpp;
s += src_bpp;
}
}
2012-06-07 06:06:06 +08:00
offset += dest_bpp;
}
g_object_unref (src_buf);
}
progress += one_row;
}
g_free (buffer);
g_free (bw_buffer);
2012-06-07 06:06:06 +08:00
}
static void
load_separate (TIFF *tif,
ChannelData *channel,
const Babl *type,
gushort bps,
gushort spp,
gboolean is_bw,
gint extra)
2012-06-07 06:06:06 +08:00
{
guint32 image_width;
guint32 image_height;
guint32 tile_width;
guint32 tile_height;
gint bytes_per_pixel;
const Babl *src_format;
guchar *buffer;
guchar *bw_buffer = NULL;
gdouble progress = 0.0;
gdouble one_row;
gint i, compindex;
2012-06-07 06:06:06 +08:00
g_printerr ("%s\n", __func__);
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &image_width);
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &image_height);
2012-06-07 06:06:06 +08:00
tile_width = image_width;
2012-06-07 06:06:06 +08:00
if (TIFFIsTiled (tif))
{
TIFFGetField (tif, TIFFTAG_TILEWIDTH, &tile_width);
TIFFGetField (tif, TIFFTAG_TILELENGTH, &tile_height);
2012-06-07 06:06:06 +08:00
buffer = g_malloc (TIFFTileSize (tif));
}
else
{
tile_width = image_width;
tile_height = 1;
2012-06-07 06:06:06 +08:00
buffer = g_malloc (TIFFScanlineSize (tif));
}
if (is_bw)
bw_buffer = g_malloc (tile_width * tile_height);
one_row = (gdouble) tile_height / (gdouble) image_height;
2012-06-07 06:06:06 +08:00
src_format = babl_format_n (type, 1);
2012-06-07 06:06:06 +08:00
/* consistency check */
bytes_per_pixel = 0;
for (i = 0; i <= extra; i++)
bytes_per_pixel += babl_format_get_bytes_per_pixel (channel[i].format);
g_printerr ("bytes_per_pixel: %d, format: %d\n",
bytes_per_pixel,
2012-06-07 06:06:06 +08:00
babl_format_get_bytes_per_pixel (src_format));
compindex = 0;
2012-06-07 06:06:06 +08:00
for (i = 0; i <= extra; i++)
{
gint n_comps;
gint src_bpp;
gint dest_bpp;
gint offset;
gint j;
2012-06-07 06:06:06 +08:00
n_comps = babl_format_get_n_components (channel[i].format);
src_bpp = babl_format_get_bytes_per_pixel (src_format);
2012-06-07 06:06:06 +08:00
dest_bpp = babl_format_get_bytes_per_pixel (channel[i].format);
offset = 0;
2012-06-07 06:06:06 +08:00
for (j = 0; j < n_comps; j++)
{
guint32 y;
for (y = 0; y < image_height; y += tile_height)
2012-06-07 06:06:06 +08:00
{
guint32 x;
for (x = 0; x < image_width; x += tile_width)
2012-06-07 06:06:06 +08:00
{
GeglBuffer *src_buf;
GeglBufferIterator *iter;
guint32 rows;
guint32 cols;
2012-06-07 06:06:06 +08:00
gimp_progress_update (progress + one_row *
((gdouble) x / (gdouble) image_width));
2012-06-07 06:06:06 +08:00
if (TIFFIsTiled (tif))
TIFFReadTile (tif, buffer, x, y, 0, compindex);
2012-06-07 06:06:06 +08:00
else
TIFFReadScanline (tif, buffer, y, compindex);
cols = MIN (image_width - x, tile_width);
rows = MIN (image_height - y, tile_height);
if (is_bw)
convert_bit2byte (buffer, bw_buffer, cols, rows);
src_buf = gegl_buffer_linear_new_from_data (is_bw ? bw_buffer : buffer,
2012-06-07 06:06:06 +08:00
src_format,
GEGL_RECTANGLE (0, 0, cols, rows),
GEGL_AUTO_ROWSTRIDE,
NULL, NULL);
2012-05-19 21:31:44 +08:00
iter = gegl_buffer_iterator_new (src_buf,
GEGL_RECTANGLE (0, 0, cols, rows),
0, NULL,
GEGL_ACCESS_READ,
GEGL_ABYSS_NONE, 2);
2012-05-19 21:31:44 +08:00
gegl_buffer_iterator_add (iter, channel[i].buffer,
GEGL_RECTANGLE (x, y, cols, rows),
2012-08-30 01:04:13 +08:00
0, channel[i].format,
GEGL_ACCESS_READWRITE,
2012-06-07 06:06:06 +08:00
GEGL_ABYSS_NONE);
2012-05-19 21:31:44 +08:00
while (gegl_buffer_iterator_next (iter))
{
guchar *s = iter->items[0].data;
guchar *d = iter->items[1].data;
gint length = iter->length;
2012-06-07 06:06:06 +08:00
d += offset;
2012-05-19 21:31:44 +08:00
while (length--)
{
2012-06-07 06:06:06 +08:00
memcpy (d, s, src_bpp);
2012-05-19 21:31:44 +08:00
d += dest_bpp;
s += src_bpp;
}
}
2012-06-07 06:06:06 +08:00
g_object_unref (src_buf);
}
}
2012-06-07 06:06:06 +08:00
offset += src_bpp;
compindex++;
}
2012-05-19 21:31:44 +08:00
progress += one_row;
}
g_free (buffer);
g_free (bw_buffer);
}
2012-05-19 21:31:44 +08:00
static guchar bit2byte[256 * 8];
static void
fill_bit2byte (void)
{
static gboolean filled = FALSE;
guchar *dest;
gint i, j;
if (filled)
return;
dest = bit2byte;
for (j = 0; j < 256; j++)
for (i = 7; i >= 0; i--)
*(dest++) = ((j & (1 << i)) != 0);
filled = TRUE;
}
static void
convert_bit2byte (const guchar *src,
guchar *dest,
gint width,
gint height)
{
gint y;
for (y = 0; y < height; y++)
{
gint x = width;
while (x >= 8)
{
memcpy (dest, bit2byte + *src * 8, 8);
dest += 8;
x -= 8;
src++;
}
if (x > 0)
{
memcpy (dest, bit2byte + *src * 8, x);
dest += x;
src++;
}
}
}
static gboolean
load_dialog (TIFF *tif,
const gchar *help_id,
TiffSelectedPages *pages,
const gchar *extra_message,
DefaultExtra *default_extra)
{
GtkWidget *dialog;
GtkWidget *vbox;
GtkWidget *selector = NULL;
GtkWidget *crop_option = NULL;
GtkWidget *extra_radio = NULL;
gboolean run;
dialog = gimp_dialog_new (_("Import from TIFF"), PLUG_IN_ROLE,
NULL, 0,
gimp_standard_help_func, help_id,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Import"), GTK_RESPONSE_OK,
NULL);
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
GTK_RESPONSE_OK,
GTK_RESPONSE_CANCEL,
-1);
gimp_window_set_transient (GTK_WINDOW (dialog));
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
vbox, TRUE, TRUE, 0);
if (pages->n_pages > 1)
{
gint i;
/* Page Selector */
selector = gimp_page_selector_new ();
gtk_widget_set_size_request (selector, 300, 200);
gtk_box_pack_start (GTK_BOX (vbox), selector, TRUE, TRUE, 0);
gimp_page_selector_set_n_pages (GIMP_PAGE_SELECTOR (selector),
pages->n_pages);
gimp_page_selector_set_target (GIMP_PAGE_SELECTOR (selector), pages->target);
for (i = 0; i < pages->n_pages; i++)
{
const gchar *name = tiff_get_page_name (tif);
if (name)
gimp_page_selector_set_page_label (GIMP_PAGE_SELECTOR (selector),
i, name);
TIFFReadDirectory (tif);
}
g_signal_connect_swapped (selector, "activate",
G_CALLBACK (gtk_window_activate_default),
dialog);
/* Option to shrink the loaded image to its bounding box
or keep as much empty space as possible.
Note that there seems to be no way to keep the empty
space on the right and bottom. */
crop_option = gtk_check_button_new_with_label (_("Keep empty space around imported layers"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (crop_option),
pages->keep_empty_space);
gtk_box_pack_start (GTK_BOX (vbox), crop_option, TRUE, TRUE, 0);
}
if (extra_message)
{
GtkWidget *warning;
warning = g_object_new (GIMP_TYPE_HINT_BOX,
"icon-name", GIMP_ICON_DIALOG_WARNING,
"hint", extra_message,
NULL);
gtk_box_pack_start (GTK_BOX (vbox), warning, TRUE, TRUE, 0);
gtk_widget_show (warning);
extra_radio = gimp_int_radio_group_new (TRUE, _("Process extra channel as:"),
(GCallback) gimp_radio_button_update,
default_extra, GIMP_TIFF_LOAD_UNASSALPHA,
_("Non-premultiplied alpha"), GIMP_TIFF_LOAD_UNASSALPHA, NULL,
_("Premultiplied alpha"), GIMP_TIFF_LOAD_ASSOCALPHA, NULL,
_("Channel"), GIMP_TIFF_LOAD_CHANNEL, NULL,
NULL);
gtk_box_pack_start (GTK_BOX (vbox), extra_radio, TRUE, TRUE, 0);
gtk_widget_show (extra_radio);
}
/* Setup done; display the dialog */
gtk_widget_show_all (dialog);
/* run the dialog */
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
if (run)
{
if (pages->n_pages > 1)
{
pages->target =
gimp_page_selector_get_target (GIMP_PAGE_SELECTOR (selector));
pages->pages =
gimp_page_selector_get_selected_pages (GIMP_PAGE_SELECTOR (selector),
&pages->n_pages);
pages->keep_empty_space =
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (crop_option));
/* select all if none selected */
if (pages->n_pages == 0)
{
gimp_page_selector_select_all (GIMP_PAGE_SELECTOR (selector));
pages->pages =
gimp_page_selector_get_selected_pages (GIMP_PAGE_SELECTOR (selector),
&pages->n_pages);
}
}
}
return run;
}