1997-11-24 22:05:25 +00:00
|
|
|
/* tiff loading and saving for the GIMP
|
|
|
|
* -Peter Mattis
|
2003-12-02 22:32:42 +00:00
|
|
|
*
|
1998-05-18 00:54:11 +00:00
|
|
|
* The TIFF loading code has been completely revamped by Nick Lamb
|
|
|
|
* njl195@zepler.org.uk -- 18 May 1998
|
1999-09-17 22:28:25 +00:00
|
|
|
* And it now gains support for tiles (and doubtless a zillion bugs)
|
|
|
|
* njl195@zepler.org.uk -- 12 June 1999
|
2000-04-20 04:38:31 +00:00
|
|
|
* LZW patent fuss continues :(
|
|
|
|
* njl195@zepler.org.uk -- 20 April 2000
|
1997-11-24 22:05:25 +00:00
|
|
|
* The code for this filter is based on "tifftopnm" and "pnmtotiff",
|
|
|
|
* 2 programs that are a part of the netpbm package.
|
2000-06-18 01:07:13 +00:00
|
|
|
* khk@khk.net -- 13 May 2000
|
2003-07-15 12:35:39 +00:00
|
|
|
* Added support for ICCPROFILE tiff tag. If this tag is present in a
|
2000-06-18 01:07:13 +00:00
|
|
|
* TIFF file, then a parasite is created and vice versa.
|
2002-12-13 14:57:16 +00:00
|
|
|
* peter@kirchgessner.net -- 29 Oct 2002
|
|
|
|
* Progress bar only when run interactive
|
2004-01-09 19:48:07 +00:00
|
|
|
* Added support for layer offsets - pablo.dangelo@web.de -- 7 Jan 2004
|
2004-01-16 21:28:31 +00:00
|
|
|
* Honor EXTRASAMPLES tag while loading images with alphachannel
|
|
|
|
* pablo.dangelo@web.de -- 16 Jan 2004
|
1997-11-24 22:05:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2006-09-12 20:45:51 +00: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-24 22:05:25 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
#include <errno.h>
|
1997-11-24 22:05:25 +00:00
|
|
|
#include <string.h>
|
2003-06-13 14:37:00 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
#include <tiffio.h>
|
2000-01-08 20:00:10 +00:00
|
|
|
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2000-01-09 06:02:20 +00:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
1998-10-11 22:50:03 +00:00
|
|
|
|
2000-05-01 20:22:55 +00:00
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
#define LOAD_PROC "file-tiff-load"
|
|
|
|
#define SAVE_PROC "file-tiff-save"
|
|
|
|
#define SAVE2_PROC "file-tiff-save2"
|
|
|
|
#define PLUG_IN_BINARY "tiff"
|
|
|
|
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2003-07-15 12:35:39 +00:00
|
|
|
gint compression;
|
|
|
|
gint fillorder;
|
2004-01-16 21:28:31 +00:00
|
|
|
gboolean save_transp_pixels;
|
1997-11-24 22:05:25 +00:00
|
|
|
} TiffSaveVals;
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2002-12-13 14:57:16 +00:00
|
|
|
gint32 ID;
|
2000-08-22 01:26:57 +00:00
|
|
|
GimpDrawable *drawable;
|
|
|
|
GimpPixelRgn pixel_rgn;
|
2002-12-13 14:57:16 +00:00
|
|
|
guchar *pixels;
|
|
|
|
guchar *pixel;
|
1998-11-09 02:05:24 +00:00
|
|
|
} channel_data;
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* Declare some local functions.
|
|
|
|
*/
|
2003-12-02 22:32:42 +00:00
|
|
|
static void query (void);
|
|
|
|
static void run (const gchar *name,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2003-07-02 00:15:09 +00:00
|
|
|
static gint32 load_image (const gchar *filename);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
|
|
|
static void load_rgba (TIFF *tif,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel);
|
2000-01-25 17:46:56 +00:00
|
|
|
static void load_lines (TIFF *tif,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gboolean alpha,
|
2005-01-01 19:13:38 +00:00
|
|
|
gboolean is_bw,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint extra);
|
2000-01-25 17:46:56 +00:00
|
|
|
static void load_tiles (TIFF *tif,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gboolean alpha,
|
2005-01-01 19:13:38 +00:00
|
|
|
gboolean is_bw,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint extra);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2005-05-09 10:41:39 +00:00
|
|
|
static void read_separate (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
2000-01-25 17:46:56 +00:00
|
|
|
gushort bps,
|
2004-02-08 00:40:46 +00:00
|
|
|
gushort photomet,
|
2000-01-25 17:46:56 +00:00
|
|
|
gint startcol,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
2003-12-02 22:32:42 +00:00
|
|
|
gboolean alpha,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint extra,
|
|
|
|
gint sample);
|
2005-05-09 10:41:39 +00:00
|
|
|
static void read_16bit (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align);
|
2005-05-09 10:41:39 +00:00
|
|
|
static void read_8bit (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align);
|
2005-05-09 10:41:39 +00:00
|
|
|
static void read_bw (const guchar *source,
|
2005-01-01 19:13:38 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gint align);
|
2005-05-09 10:41:39 +00:00
|
|
|
static void read_default (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2005-05-09 10:41:39 +00:00
|
|
|
static gboolean save_image (const gchar *filename,
|
|
|
|
gint32 image,
|
|
|
|
gint32 drawable,
|
|
|
|
gint32 orig_image);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2005-05-09 10:41:39 +00:00
|
|
|
static gboolean save_dialog (gboolean alpha);
|
2000-01-25 17:46:56 +00:00
|
|
|
|
2005-05-09 10:41:39 +00:00
|
|
|
static void comment_entry_callback (GtkWidget *widget,
|
|
|
|
gpointer data);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-05-09 10:41:39 +00:00
|
|
|
static void byte2bit (const guchar *byteline,
|
|
|
|
gint width,
|
|
|
|
guchar *bitline,
|
|
|
|
gboolean invert);
|
2005-01-01 19:13:38 +00:00
|
|
|
static void fill_bit2byte (void);
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2006-05-16 12:26:20 +00:00
|
|
|
const GimpPlugInInfo PLUG_IN_INFO =
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2000-01-25 17:46:56 +00:00
|
|
|
NULL, /* init_proc */
|
|
|
|
NULL, /* quit_proc */
|
|
|
|
query, /* query_proc */
|
|
|
|
run, /* run_proc */
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static TiffSaveVals tsvals =
|
|
|
|
{
|
2000-04-20 04:38:31 +00:00
|
|
|
COMPRESSION_NONE, /* compression */
|
2004-01-28 12:30:00 +00:00
|
|
|
TRUE, /* alpha handling */
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
|
2002-12-13 14:57:16 +00:00
|
|
|
static gchar *image_comment = NULL;
|
|
|
|
static GimpRunMode run_mode = GIMP_RUN_INTERACTIVE;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
static guchar bit2byte[256 * 8];
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
MAIN ()
|
|
|
|
|
|
|
|
static void
|
2000-01-25 17:46:56 +00:00
|
|
|
query (void)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2006-05-16 12:26:20 +00:00
|
|
|
static const GimpParamDef load_args[] =
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2005-08-15 22:42:34 +00:00
|
|
|
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
|
|
|
|
{ GIMP_PDB_STRING, "filename", "The name of the file to load" },
|
|
|
|
{ GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
2006-05-16 12:26:20 +00:00
|
|
|
static const GimpParamDef load_return_vals[] =
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
{ GIMP_PDB_IMAGE, "image", "Output image" }
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
#define COMMON_SAVE_ARGS \
|
2005-08-15 22:42:34 +00:00
|
|
|
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },\
|
|
|
|
{ GIMP_PDB_IMAGE, "image", "Input image" },\
|
|
|
|
{ GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },\
|
|
|
|
{ GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },\
|
|
|
|
{ GIMP_PDB_STRING, "raw-filename", "The name of the file to save the image in" },\
|
|
|
|
{ GIMP_PDB_INT32, "compression", "Compression type: { NONE (0), LZW (1), PACKBITS (2), DEFLATE (3), JPEG (4)" }
|
2004-01-16 21:28:31 +00:00
|
|
|
|
2006-05-16 12:26:20 +00:00
|
|
|
static const GimpParamDef save_args_old[] =
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
|
|
|
COMMON_SAVE_ARGS
|
|
|
|
};
|
|
|
|
|
2006-05-16 12:26:20 +00:00
|
|
|
static const GimpParamDef save_args[] =
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
COMMON_SAVE_ARGS,
|
2005-08-15 22:42:34 +00:00
|
|
|
{ GIMP_PDB_INT32, "save-transp-pixels", "Keep the color data masked by an alpha channel intact" }
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_install_procedure (LOAD_PROC,
|
2000-01-31 02:32:30 +00:00
|
|
|
"loads files of the tiff file format",
|
1997-11-24 22:05:25 +00:00
|
|
|
"FIXME: write help for tiff_load",
|
1998-05-18 00:54:11 +00:00
|
|
|
"Spencer Kimball, Peter Mattis & Nick Lamb",
|
1998-05-31 06:49:20 +00:00
|
|
|
"Nick Lamb <njl195@zepler.org.uk>",
|
2003-12-02 22:32:42 +00:00
|
|
|
"1995-1996,1998-2003",
|
2004-11-01 14:29:29 +00:00
|
|
|
N_("TIFF image"),
|
2004-02-08 00:40:46 +00:00
|
|
|
NULL,
|
2000-08-22 01:26:57 +00:00
|
|
|
GIMP_PLUGIN,
|
2001-12-06 02:28:58 +00:00
|
|
|
G_N_ELEMENTS (load_args),
|
|
|
|
G_N_ELEMENTS (load_return_vals),
|
1997-11-24 22:05:25 +00:00
|
|
|
load_args, load_return_vals);
|
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_register_file_handler_mime (LOAD_PROC, "image/tiff");
|
|
|
|
gimp_register_magic_load_handler (LOAD_PROC,
|
2004-05-14 00:01:11 +00:00
|
|
|
"tif,tiff",
|
|
|
|
"",
|
|
|
|
"0,string,II*\\0,0,string,MM\\0*");
|
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_install_procedure (SAVE_PROC,
|
2004-01-16 21:28:31 +00:00
|
|
|
"saves files in the tiff file format",
|
|
|
|
"Saves files in the Tagged Image File Format. "
|
2004-02-08 00:40:46 +00:00
|
|
|
"The value for the saved comment is taken "
|
|
|
|
"from the 'gimp-comment' parasite.",
|
2004-01-16 21:28:31 +00:00
|
|
|
"Spencer Kimball & Peter Mattis",
|
|
|
|
"Spencer Kimball & Peter Mattis",
|
|
|
|
"1995-1996,2000-2003",
|
2004-05-14 00:01:11 +00:00
|
|
|
N_("TIFF image"),
|
2004-02-08 00:40:46 +00:00
|
|
|
"RGB*, GRAY*, INDEXED",
|
2004-01-16 21:28:31 +00:00
|
|
|
GIMP_PLUGIN,
|
|
|
|
G_N_ELEMENTS (save_args_old), 0,
|
|
|
|
save_args_old, NULL);
|
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_register_file_handler_mime (SAVE_PROC, "image/tiff");
|
|
|
|
gimp_register_save_handler (SAVE_PROC, "tif,tiff", "");
|
2004-05-14 00:01:11 +00:00
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_install_procedure (SAVE2_PROC,
|
2000-01-31 02:32:30 +00:00
|
|
|
"saves files in the tiff file format",
|
2000-10-20 03:38:15 +00:00
|
|
|
"Saves files in the Tagged Image File Format. "
|
2004-02-08 00:40:46 +00:00
|
|
|
"The value for the saved comment is taken "
|
|
|
|
"from the 'gimp-comment' parasite.",
|
1997-11-24 22:05:25 +00:00
|
|
|
"Spencer Kimball & Peter Mattis",
|
|
|
|
"Spencer Kimball & Peter Mattis",
|
2003-12-02 22:32:42 +00:00
|
|
|
"1995-1996,2000-2003",
|
2004-05-14 00:01:11 +00:00
|
|
|
N_("TIFF image"),
|
2004-02-08 00:40:46 +00:00
|
|
|
"RGB*, GRAY*, INDEXED",
|
2000-08-22 01:26:57 +00:00
|
|
|
GIMP_PLUGIN,
|
2001-12-06 02:28:58 +00:00
|
|
|
G_N_ELEMENTS (save_args), 0,
|
1997-11-24 22:05:25 +00:00
|
|
|
save_args, NULL);
|
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_register_file_handler_mime (SAVE2_PROC, "image/tiff");
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-07-02 00:15:09 +00:00
|
|
|
run (const gchar *name,
|
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2003-11-06 15:27:05 +00:00
|
|
|
static GimpParam values[2];
|
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
|
|
|
GimpParasite *parasite;
|
|
|
|
gint32 image;
|
|
|
|
gint32 drawable;
|
|
|
|
gint32 orig_image;
|
|
|
|
GimpExportReturn export = GIMP_EXPORT_CANCEL;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
run_mode = param[0].data.d_int32;
|
|
|
|
|
2003-03-25 16:38:19 +00:00
|
|
|
INIT_I18N ();
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
*nreturn_vals = 1;
|
2000-01-25 17:46:56 +00:00
|
|
|
*return_vals = values;
|
2002-01-08 09:20:02 +00:00
|
|
|
|
2000-08-22 01:26:57 +00:00
|
|
|
values[0].type = GIMP_PDB_STATUS;
|
|
|
|
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-08-15 22:42:34 +00:00
|
|
|
if (strcmp (name, LOAD_PROC) == 0)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1998-05-18 00:54:11 +00:00
|
|
|
image = load_image (param[1].data.d_string);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1998-05-18 00:54:11 +00:00
|
|
|
if (image != -1)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
*nreturn_vals = 2;
|
|
|
|
values[1].type = GIMP_PDB_IMAGE;
|
|
|
|
values[1].data.d_image = image;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
else
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2005-08-15 22:42:34 +00:00
|
|
|
else if (strcmp (name, SAVE_PROC) == 0 ||
|
|
|
|
strcmp (name, SAVE2_PROC) == 0)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
/* Plug-in is either file_tiff_save or file_tiff_save2 */
|
1999-10-03 18:54:54 +00:00
|
|
|
image = orig_image = param[1].data.d_int32;
|
1999-10-25 00:59:18 +00:00
|
|
|
drawable = param[2].data.d_int32;
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
/* Do this right this time, if POSSIBLE query for parasites, otherwise
|
2004-02-08 00:40:46 +00:00
|
|
|
or if there isn't one, choose the default comment from the gimprc. */
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
/* eventually export the image */
|
1999-10-03 18:54:54 +00:00
|
|
|
switch (run_mode)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
case GIMP_RUN_INTERACTIVE:
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY, FALSE);
|
2004-02-08 00:40:46 +00:00
|
|
|
export = gimp_export_image (&image, &drawable, "TIFF",
|
|
|
|
(GIMP_EXPORT_CAN_HANDLE_RGB |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_INDEXED |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_ALPHA ));
|
|
|
|
if (export == GIMP_EXPORT_CANCEL)
|
|
|
|
{
|
|
|
|
values[0].data.d_status = GIMP_PDB_CANCEL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
1999-10-03 18:54:54 +00:00
|
|
|
|
1999-10-17 00:07:55 +00:00
|
|
|
parasite = gimp_image_parasite_find (orig_image, "gimp-comment");
|
1998-11-13 04:00:54 +00:00
|
|
|
if (parasite)
|
2004-06-01 17:15:56 +00:00
|
|
|
{
|
2004-11-23 14:28:43 +00:00
|
|
|
image_comment = g_strndup (gimp_parasite_data (parasite),
|
|
|
|
gimp_parasite_data_size (parasite));
|
2004-06-01 17:15:56 +00:00
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
switch (run_mode)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
case GIMP_RUN_INTERACTIVE:
|
|
|
|
/* Possibly retrieve data */
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_get_data (SAVE_PROC, &tsvals);
|
2004-02-08 00:40:46 +00:00
|
|
|
|
|
|
|
parasite = gimp_image_parasite_find (orig_image, "tiff-save-options");
|
|
|
|
if (parasite)
|
|
|
|
{
|
2004-11-23 14:28:43 +00:00
|
|
|
const TiffSaveVals *pvals = gimp_parasite_data (parasite);
|
|
|
|
|
|
|
|
tsvals.compression = pvals->compression;
|
|
|
|
tsvals.save_transp_pixels = pvals->save_transp_pixels;
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
|
|
|
|
/* First acquire information with a dialog */
|
2004-07-12 07:41:23 +00:00
|
|
|
if (! save_dialog (gimp_drawable_has_alpha (drawable)))
|
2004-02-08 00:40:46 +00:00
|
|
|
status = GIMP_PDB_CANCEL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
|
|
|
/* Make sure all the arguments are there! */
|
2004-03-06 21:43:01 +00:00
|
|
|
if (nparams == 6 || nparams == 7)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
switch (param[5].data.d_int32)
|
|
|
|
{
|
|
|
|
case 0: tsvals.compression = COMPRESSION_NONE; break;
|
|
|
|
case 1: tsvals.compression = COMPRESSION_LZW; break;
|
|
|
|
case 2: tsvals.compression = COMPRESSION_PACKBITS; break;
|
|
|
|
case 3: tsvals.compression = COMPRESSION_DEFLATE; break;
|
|
|
|
case 4: tsvals.compression = COMPRESSION_JPEG; break;
|
|
|
|
default: status = GIMP_PDB_CALLING_ERROR; break;
|
|
|
|
}
|
2004-01-16 21:28:31 +00:00
|
|
|
|
|
|
|
if (nparams == 7)
|
|
|
|
tsvals.save_transp_pixels = param[6].data.d_int32;
|
|
|
|
else
|
2004-01-28 12:30:00 +00:00
|
|
|
tsvals.save_transp_pixels = TRUE;
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
2004-03-06 21:43:01 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
|
|
|
}
|
2004-02-08 00:40:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
|
|
/* Possibly retrieve data */
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_get_data (SAVE_PROC, &tsvals);
|
2004-02-08 00:40:46 +00:00
|
|
|
|
|
|
|
parasite = gimp_image_parasite_find (orig_image, "tiff-save-options");
|
|
|
|
if (parasite)
|
|
|
|
{
|
2004-11-23 14:28:43 +00:00
|
|
|
const TiffSaveVals *pvals = gimp_parasite_data (parasite);
|
|
|
|
|
|
|
|
tsvals.compression = pvals->compression;
|
|
|
|
tsvals.save_transp_pixels = pvals->save_transp_pixels;
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-08-22 01:26:57 +00:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
if (save_image (param[3].data.d_string, image, drawable, orig_image))
|
|
|
|
{
|
|
|
|
/* Store mvals data */
|
2005-08-15 22:42:34 +00:00
|
|
|
gimp_set_data (SAVE_PROC, &tsvals, sizeof (TiffSaveVals));
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
|
|
|
}
|
1999-10-03 18:54:54 +00:00
|
|
|
|
2000-08-24 14:17:34 +00:00
|
|
|
if (export == GIMP_EXPORT_EXPORT)
|
2004-02-08 00:40:46 +00:00
|
|
|
gimp_image_delete (image);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
2000-01-25 17:46:56 +00:00
|
|
|
else
|
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
2000-01-25 17:46:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
values[0].data.d_status = status;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
static void
|
2003-07-15 12:35:39 +00:00
|
|
|
tiff_warning(const gchar *module,
|
|
|
|
const gchar *fmt,
|
|
|
|
va_list ap)
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
{
|
2004-01-31 22:01:34 +00:00
|
|
|
va_list ap_test;
|
|
|
|
|
|
|
|
/* Workaround for: http://bugzilla.gnome.org/show_bug.cgi?id=131975 */
|
|
|
|
/* Ignore the warnings about unregistered private tags (>= 32768) */
|
|
|
|
if (! strcmp (fmt, "unknown field with tag %d (0x%x) ignored"))
|
|
|
|
{
|
2004-02-01 00:45:49 +00:00
|
|
|
G_VA_COPY (ap_test, ap);
|
2004-01-31 22:01:34 +00:00
|
|
|
if (va_arg (ap_test, int) >= 32768)
|
2004-02-08 00:40:46 +00:00
|
|
|
return;
|
2004-01-31 22:01:34 +00:00
|
|
|
}
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
static void
|
2003-07-15 12:35:39 +00:00
|
|
|
tiff_error (const gchar *module,
|
|
|
|
const gchar *fmt,
|
|
|
|
va_list ap)
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
{
|
2004-01-31 22:01:34 +00:00
|
|
|
/* Workaround for: http://bugzilla.gnome.org/show_bug.cgi?id=132297 */
|
|
|
|
/* Ignore the errors related to random access and JPEG compression */
|
|
|
|
if (! strcmp (fmt, "Compression algorithm does not support random access"))
|
|
|
|
return;
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
static gint32
|
2003-07-15 12:35:39 +00:00
|
|
|
load_image (const gchar *filename)
|
1999-10-03 18:54:54 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
TIFF *tif;
|
|
|
|
gushort bps, spp, photomet;
|
|
|
|
guint16 orientation;
|
|
|
|
gint cols, rows;
|
|
|
|
gboolean alpha;
|
|
|
|
gint image = 0, image_type = GIMP_RGB;
|
|
|
|
gint layer, layer_type = GIMP_RGB_IMAGE;
|
2004-01-09 19:48:07 +00:00
|
|
|
float layer_offset_x = 0.0;
|
|
|
|
float layer_offset_y = 0.0;
|
|
|
|
gint layer_offset_x_pixel = 0;
|
|
|
|
gint layer_offset_y_pixel = 0;
|
|
|
|
gint min_row = G_MAXINT;
|
|
|
|
gint min_col = G_MAXINT;
|
|
|
|
gint max_row = 0;
|
|
|
|
gint max_col = 0;
|
2003-12-02 22:32:42 +00:00
|
|
|
gushort extra, *extra_types;
|
|
|
|
channel_data *channel = NULL;
|
|
|
|
|
|
|
|
gushort *redmap, *greenmap, *bluemap;
|
|
|
|
GimpRGB color;
|
|
|
|
guchar cmap[768];
|
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
gboolean is_bw;
|
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
gint i, j;
|
|
|
|
gint ilayer;
|
|
|
|
gboolean worst_case = FALSE;
|
|
|
|
|
|
|
|
TiffSaveVals save_vals;
|
2000-05-26 22:28:40 +00:00
|
|
|
GimpParasite *parasite;
|
2003-12-02 22:32:42 +00:00
|
|
|
guint16 tmp;
|
|
|
|
|
2005-07-17 20:35:32 +00:00
|
|
|
gchar *name;
|
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
gboolean flip_horizontal = FALSE;
|
|
|
|
gboolean flip_vertical = FALSE;
|
|
|
|
|
2000-06-18 01:07:13 +00:00
|
|
|
#ifdef TIFFTAG_ICCPROFILE
|
2003-12-02 22:32:42 +00:00
|
|
|
uint32 profile_size;
|
|
|
|
guchar *icc_profile;
|
2000-06-18 01:07:13 +00:00
|
|
|
#endif
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
|
2001-01-25 01:20:05 +00:00
|
|
|
gimp_rgb_set (&color, 0.0, 0.0, 0.0);
|
|
|
|
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
TIFFSetWarningHandler (tiff_warning);
|
|
|
|
TIFFSetErrorHandler (tiff_error);
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
tif = TIFFOpen (filename, "r");
|
2003-07-15 12:35:39 +00:00
|
|
|
if (!tif)
|
|
|
|
{
|
2003-11-15 13:53:33 +00:00
|
|
|
g_message (_("Could not open '%s' for reading: %s"),
|
2004-01-19 03:06:04 +00:00
|
|
|
gimp_filename_to_utf8 (filename), g_strerror (errno));
|
2003-07-15 12:35:39 +00:00
|
|
|
gimp_quit ();
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-30 08:16:10 +00:00
|
|
|
gimp_progress_init_printf (_("Opening '%s'"),
|
2005-09-29 18:34:08 +00:00
|
|
|
gimp_filename_to_utf8 (filename));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* We will loop through the all pages in case of multipage TIFF
|
|
|
|
and load every page as a separate layer. */
|
|
|
|
ilayer = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, &bps);
|
1998-05-18 00:54:11 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (bps > 8 && bps != 16)
|
|
|
|
worst_case = TRUE; /* Wrong sample width => RGBA */
|
1998-05-18 00:54:11 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
|
|
|
|
extra = 0;
|
1998-05-18 00:54:11 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols))
|
|
|
|
{
|
2004-01-19 03:06:04 +00:00
|
|
|
g_message ("Could not get image width from '%s'",
|
|
|
|
gimp_filename_to_utf8 (filename));
|
2003-12-02 22:32:42 +00:00
|
|
|
gimp_quit ();
|
|
|
|
}
|
1998-05-18 00:54:11 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows))
|
|
|
|
{
|
2004-01-19 03:06:04 +00:00
|
|
|
g_message ("Could not get image length from '%s'",
|
|
|
|
gimp_filename_to_utf8 (filename));
|
2003-12-02 22:32:42 +00:00
|
|
|
gimp_quit ();
|
|
|
|
}
|
1998-05-18 00:54:11 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet))
|
|
|
|
{
|
2004-01-27 19:19:54 +00:00
|
|
|
uint16 compress;
|
|
|
|
if (TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress) &&
|
|
|
|
(compress == COMPRESSION_CCITTFAX3 ||
|
|
|
|
compress == COMPRESSION_CCITTFAX4 ||
|
|
|
|
compress == COMPRESSION_CCITTRLE ||
|
|
|
|
compress == COMPRESSION_CCITTRLEW))
|
|
|
|
{
|
|
|
|
g_message ("Could not get photometric from '%s'. "
|
|
|
|
"Image is CCITT compressed, assuming min-is-white",
|
|
|
|
filename);
|
|
|
|
photomet = PHOTOMETRIC_MINISWHITE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_message ("Could not get photometric from '%s'. "
|
|
|
|
"Assuming min-is-black",
|
|
|
|
filename);
|
|
|
|
/* 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;
|
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* test if the extrasample represents an associated alpha channel... */
|
|
|
|
if (extra > 0 && (extra_types[0] == EXTRASAMPLE_ASSOCALPHA))
|
|
|
|
{
|
|
|
|
alpha = TRUE;
|
2004-01-16 21:28:31 +00:00
|
|
|
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))
|
|
|
|
{
|
|
|
|
/* assuming unassociated alpha if unspecified */
|
|
|
|
g_message ("alpha channel type not defined for file %s. "
|
|
|
|
"Assuming alpha is not premultiplied",
|
2004-01-19 03:06:04 +00:00
|
|
|
gimp_filename_to_utf8 (filename));
|
2004-01-16 21:28:31 +00:00
|
|
|
alpha = TRUE;
|
|
|
|
tsvals.save_transp_pixels = TRUE;
|
2003-12-02 22:32:42 +00:00
|
|
|
--extra;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
alpha = FALSE;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (photomet == PHOTOMETRIC_RGB && spp > 3 + extra)
|
|
|
|
{
|
|
|
|
alpha = TRUE;
|
|
|
|
extra = spp - 4;
|
|
|
|
}
|
|
|
|
else if (photomet != PHOTOMETRIC_RGB && spp > 1 + extra)
|
|
|
|
{
|
|
|
|
alpha = TRUE;
|
|
|
|
extra = spp - 2;
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
is_bw = FALSE;
|
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
2005-01-01 19:13:38 +00:00
|
|
|
if (bps == 1 && !alpha && spp == 1)
|
|
|
|
{
|
|
|
|
image_type = GIMP_INDEXED;
|
2005-01-01 19:28:59 +00:00
|
|
|
layer_type = GIMP_INDEXED_IMAGE;
|
2005-01-01 19:13:38 +00:00
|
|
|
|
|
|
|
is_bw = TRUE;
|
|
|
|
fill_bit2byte ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
image_type = GIMP_GRAY;
|
|
|
|
layer_type = (alpha) ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
|
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
break;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
image_type = GIMP_RGB;
|
|
|
|
layer_type = (alpha) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
|
|
|
|
break;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
case PHOTOMETRIC_PALETTE:
|
|
|
|
image_type = GIMP_INDEXED;
|
|
|
|
layer_type = (alpha) ? GIMP_INDEXEDA_IMAGE : GIMP_INDEXED_IMAGE;
|
|
|
|
break;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
default:
|
|
|
|
worst_case = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (worst_case)
|
|
|
|
{
|
|
|
|
image_type = GIMP_RGB;
|
|
|
|
layer_type = GIMP_RGBA_IMAGE;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (!image)
|
|
|
|
{
|
|
|
|
if ((image = gimp_image_new (cols, rows, image_type)) == -1)
|
|
|
|
{
|
|
|
|
g_message ("Could not create a new image");
|
|
|
|
gimp_quit ();
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_image_undo_disable (image);
|
|
|
|
gimp_image_set_filename (image, filename);
|
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* attach a parasite containing an ICC profile - if found in the TIFF */
|
2000-06-18 01:07:13 +00:00
|
|
|
|
|
|
|
#ifdef TIFFTAG_ICCPROFILE
|
2003-12-02 22:32:42 +00:00
|
|
|
/* If TIFFTAG_ICCPROFILE is defined we are dealing with a libtiff version
|
|
|
|
* that can handle ICC profiles. Otherwise just ignore this section. */
|
|
|
|
if (TIFFGetField (tif, TIFFTAG_ICCPROFILE, &profile_size, &icc_profile))
|
|
|
|
{
|
|
|
|
parasite = gimp_parasite_new ("icc-profile", 0,
|
|
|
|
profile_size, icc_profile);
|
|
|
|
gimp_image_parasite_attach (image, parasite);
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
}
|
2000-06-18 01:07:13 +00:00
|
|
|
#endif
|
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* attach a parasite containing the compression */
|
|
|
|
if (!TIFFGetField (tif, TIFFTAG_COMPRESSION, &tmp))
|
2006-09-17 15:41:10 +00:00
|
|
|
{
|
|
|
|
save_vals.compression = COMPRESSION_NONE;
|
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
else
|
2005-04-25 07:42:52 +00:00
|
|
|
{
|
|
|
|
switch (tmp)
|
|
|
|
{
|
|
|
|
case COMPRESSION_NONE:
|
|
|
|
case COMPRESSION_LZW:
|
|
|
|
case COMPRESSION_PACKBITS:
|
|
|
|
case COMPRESSION_DEFLATE:
|
|
|
|
case COMPRESSION_JPEG:
|
|
|
|
save_vals.compression = tmp;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
save_vals.compression = COMPRESSION_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-10-05 10:05:29 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
parasite = gimp_parasite_new ("tiff-save-options", 0,
|
|
|
|
sizeof (save_vals), &save_vals);
|
|
|
|
gimp_image_parasite_attach (image, parasite);
|
|
|
|
gimp_parasite_free (parasite);
|
1998-10-11 22:50:03 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* 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. */
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
const gchar *img_desc;
|
1998-10-11 22:50:03 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
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_parasite_attach (image, parasite);
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
}
|
|
|
|
}
|
1998-10-05 10:05:29 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* any resolution info in the file? */
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
gfloat xres = 72.0, yres = 72.0;
|
|
|
|
gushort read_unit;
|
|
|
|
GimpUnit unit = GIMP_UNIT_PIXEL; /* invalid unit */
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (TIFFGetField (tif, TIFFTAG_XRESOLUTION, &xres))
|
|
|
|
{
|
|
|
|
if (TIFFGetField (tif, TIFFTAG_YRESOLUTION, &yres))
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
|
|
|
|
if (TIFFGetFieldDefaulted (tif, TIFFTAG_RESOLUTIONUNIT,
|
|
|
|
&read_unit))
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
switch (read_unit)
|
|
|
|
{
|
|
|
|
case RESUNIT_NONE:
|
|
|
|
/* ImageMagick writes files with this silly resunit */
|
|
|
|
g_message ("Warning: resolution units meaningless");
|
|
|
|
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");
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2003-12-02 22:32:42 +00:00
|
|
|
{ /* xres but no yres */
|
|
|
|
g_message ("Warning: no y resolution info, assuming same as x");
|
|
|
|
yres = xres;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
1998-10-05 10:05:29 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* now set the new image's resolution info */
|
2000-01-08 10:55:05 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
|
|
|
|
/* 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. */
|
2004-01-09 19:48:07 +00:00
|
|
|
|
|
|
|
/* 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);
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
1998-10-05 10:05:29 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* Install colormap for INDEXED images only */
|
|
|
|
if (image_type == GIMP_INDEXED)
|
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
if (is_bw)
|
2003-12-02 22:32:42 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
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;
|
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
else
|
2003-12-02 22:32:42 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_COLORMAP,
|
|
|
|
&redmap, &greenmap, &bluemap))
|
|
|
|
{
|
|
|
|
g_message ("Could not get colormaps from '%s'",
|
|
|
|
gimp_filename_to_utf8 (filename));
|
|
|
|
gimp_quit ();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, j = 0; i < (1 << bps); i++)
|
|
|
|
{
|
|
|
|
cmap[j++] = redmap[i] >> 8;
|
|
|
|
cmap[j++] = greenmap[i] >> 8;
|
|
|
|
cmap[j++] = bluemap[i] >> 8;
|
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-11-02 12:00:25 +00:00
|
|
|
gimp_image_set_colormap (image, cmap, (1 << bps));
|
2003-12-02 22:32:42 +00:00
|
|
|
}
|
1998-10-05 10:05:29 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
/* Allocate channel_data for all channels, even the background layer */
|
|
|
|
channel = g_new0 (channel_data, extra + 1);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
/* try and use layer name from tiff file */
|
2005-07-17 20:35:32 +00:00
|
|
|
if (! TIFFGetField (tif, TIFFTAG_PAGENAME, &name) ||
|
|
|
|
! g_utf8_validate (name, -1, NULL))
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
2005-07-17 20:35:32 +00:00
|
|
|
name = NULL;
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2005-07-17 20:35:32 +00:00
|
|
|
if (name)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
layer = gimp_layer_new (image, name,
|
2005-01-01 19:13:38 +00:00
|
|
|
cols, rows,
|
|
|
|
layer_type, 100, GIMP_NORMAL_MODE);
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
else
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
if (ilayer == 0)
|
|
|
|
name = g_strdup (_("Background"));
|
|
|
|
else
|
|
|
|
name = g_strdup_printf (_("Page %d"), ilayer);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
layer = gimp_layer_new (image, name,
|
2005-01-01 19:13:38 +00:00
|
|
|
cols, rows,
|
|
|
|
layer_type, 100, GIMP_NORMAL_MODE);
|
2004-02-08 00:40:46 +00:00
|
|
|
g_free (name);
|
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
channel[0].ID = layer;
|
|
|
|
channel[0].drawable = gimp_drawable_get (layer);
|
|
|
|
|
|
|
|
if (extra > 0 && !worst_case)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
/* Add alpha channels as appropriate */
|
|
|
|
for (i = 1; i <= extra; ++i)
|
|
|
|
{
|
|
|
|
channel[i].ID = gimp_channel_new (image, _("TIFF Channel"),
|
|
|
|
cols, rows,
|
|
|
|
100.0, &color);
|
|
|
|
gimp_image_add_channel (image, channel[i].ID, 0);
|
|
|
|
channel[i].drawable = gimp_drawable_get (channel[i].ID);
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (bps == 16)
|
|
|
|
g_message (_("Warning:\n"
|
|
|
|
"The image you are loading has 16 bits per channel. GIMP "
|
|
|
|
"can only handle 8 bit, so it will be converted for you. "
|
|
|
|
"Information will be lost because of this conversion."));
|
2003-01-10 21:44:54 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (worst_case)
|
|
|
|
{
|
|
|
|
load_rgba (tif, channel);
|
|
|
|
}
|
2004-11-02 13:44:13 +00:00
|
|
|
else if (TIFFIsTiled (tif))
|
2003-12-02 22:32:42 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
load_tiles (tif, channel, bps, photomet, alpha, is_bw, extra);
|
2003-12-02 22:32:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* Load scanlines in tile_height chunks */
|
2005-01-01 19:13:38 +00:00
|
|
|
load_lines (tif, channel, bps, photomet, alpha, is_bw, extra);
|
2003-12-02 22:32:42 +00:00
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (TIFFGetField (tif, TIFFTAG_ORIENTATION, &orientation))
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
switch (orientation)
|
|
|
|
{
|
|
|
|
case ORIENTATION_TOPLEFT:
|
|
|
|
flip_horizontal = FALSE;
|
|
|
|
flip_vertical = FALSE;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_TOPRIGHT:
|
|
|
|
flip_horizontal = TRUE;
|
|
|
|
flip_vertical = FALSE;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_BOTRIGHT:
|
|
|
|
flip_horizontal = TRUE;
|
|
|
|
flip_vertical = TRUE;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_BOTLEFT:
|
|
|
|
flip_horizontal = FALSE;
|
|
|
|
flip_vertical = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
flip_horizontal = FALSE;
|
|
|
|
flip_vertical = FALSE;
|
|
|
|
g_warning ("Orientation %d not handled yet!", orientation);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flip_horizontal)
|
2004-11-02 13:44:13 +00:00
|
|
|
gimp_drawable_transform_flip_simple (layer,
|
|
|
|
GIMP_ORIENTATION_HORIZONTAL,
|
|
|
|
TRUE, 0.0, TRUE);
|
2003-12-02 22:32:42 +00:00
|
|
|
|
|
|
|
if (flip_vertical)
|
2004-11-02 13:44:13 +00:00
|
|
|
gimp_drawable_transform_flip_simple (layer,
|
|
|
|
GIMP_ORIENTATION_VERTICAL,
|
|
|
|
TRUE, 0.0, TRUE);
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
2003-01-10 13:59:41 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
gimp_drawable_flush (channel[0].drawable);
|
|
|
|
gimp_drawable_detach (channel[0].drawable);
|
2003-01-10 13:59:41 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
for (i = 1; !worst_case && i < extra; ++i)
|
|
|
|
{
|
|
|
|
gimp_drawable_flush (channel[i].drawable);
|
|
|
|
gimp_drawable_detach (channel[i].drawable);
|
|
|
|
}
|
2003-01-10 20:14:30 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
g_free (channel);
|
|
|
|
channel = NULL;
|
2003-01-10 13:59:41 +00:00
|
|
|
|
2004-01-09 19:48:07 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (ilayer > 0 && !alpha)
|
|
|
|
gimp_layer_add_alpha (layer);
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
gimp_image_add_layer (image, layer, -1);
|
|
|
|
ilayer++;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
2003-12-02 22:32:42 +00:00
|
|
|
while (TIFFReadDirectory (tif));
|
|
|
|
|
2004-01-09 19:48:07 +00:00
|
|
|
/* resize image to bounding box of all layers */
|
|
|
|
gimp_image_resize (image,
|
|
|
|
max_col - min_col, max_row - min_row, -min_col, -min_row);
|
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
gimp_image_undo_enable (image);
|
1998-11-09 02:05:24 +00:00
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-07-15 12:35:39 +00:00
|
|
|
load_rgba (TIFF *tif,
|
|
|
|
channel_data *channel)
|
1998-11-09 02:05:24 +00:00
|
|
|
{
|
2003-07-15 12:35:39 +00:00
|
|
|
uint32 imageWidth, imageLength;
|
|
|
|
uint32 row;
|
2003-01-05 20:38:21 +00:00
|
|
|
uint32 *buffer;
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &imageLength);
|
|
|
|
|
2006-09-17 15:41:10 +00:00
|
|
|
gimp_tile_cache_ntiles (1 + imageWidth / gimp_tile_width ());
|
|
|
|
|
1999-09-17 22:28:25 +00:00
|
|
|
gimp_pixel_rgn_init (&(channel[0].pixel_rgn), channel[0].drawable,
|
2003-07-15 12:35:39 +00:00
|
|
|
0, 0, imageWidth, imageLength, TRUE, FALSE);
|
|
|
|
|
2003-01-11 01:31:22 +00:00
|
|
|
buffer = g_new (uint32, imageWidth * imageLength);
|
1999-09-17 22:28:25 +00:00
|
|
|
channel[0].pixels = (guchar*) buffer;
|
2003-01-11 01:31:22 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
if (!TIFFReadRGBAImage (tif, imageWidth, imageLength, buffer, 0))
|
2003-06-13 14:37:00 +00:00
|
|
|
g_message ("Unsupported layout, no RGBA loader");
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
for (row = 0; row < imageLength; ++row)
|
|
|
|
{
|
2004-07-14 10:57:13 +00:00
|
|
|
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
|
|
|
|
/* Make sure our channels are in the right order */
|
|
|
|
uint32 i;
|
|
|
|
uint32 rowStart = row * imageWidth;
|
|
|
|
uint32 rowEnd = rowStart + imageWidth;
|
|
|
|
|
|
|
|
for (i = rowStart; i < rowEnd; i++)
|
|
|
|
buffer[i] = GUINT32_TO_LE (buffer[i]);
|
|
|
|
#endif
|
2003-07-15 12:35:39 +00:00
|
|
|
gimp_pixel_rgn_set_rect (&(channel[0].pixel_rgn),
|
|
|
|
channel[0].pixels + row * imageWidth * 4,
|
|
|
|
0, imageLength -row -1, imageWidth, 1);
|
2003-06-13 14:37:00 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
gimp_progress_update ((gdouble) row / (gdouble) imageLength);
|
|
|
|
}
|
1999-09-17 22:28:25 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1999-09-17 22:28:25 +00:00
|
|
|
static void
|
2003-12-02 22:32:42 +00:00
|
|
|
load_tiles (TIFF *tif,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gboolean alpha,
|
2005-01-01 19:13:38 +00:00
|
|
|
gboolean is_bw,
|
2003-12-02 22:32:42 +00:00
|
|
|
gint extra)
|
1999-09-17 22:28:25 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
uint16 planar = PLANARCONFIG_CONTIG;
|
2003-07-15 12:35:39 +00:00
|
|
|
uint32 imageWidth, imageLength;
|
|
|
|
uint32 tileWidth, tileLength;
|
|
|
|
uint32 x, y, rows, cols;
|
1999-09-17 22:28:25 +00:00
|
|
|
guchar *buffer;
|
2005-01-01 19:13:38 +00:00
|
|
|
gdouble progress = 0.0, one_row;
|
2003-07-15 12:35:39 +00:00
|
|
|
gint i;
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &imageLength);
|
|
|
|
TIFFGetField (tif, TIFFTAG_TILEWIDTH, &tileWidth);
|
|
|
|
TIFFGetField (tif, TIFFTAG_TILELENGTH, &tileLength);
|
|
|
|
|
2006-09-17 15:41:10 +00:00
|
|
|
if (tileWidth > gimp_tile_width () || tileLength > gimp_tile_height ())
|
|
|
|
{
|
|
|
|
gimp_tile_cache_ntiles ((1 + tileWidth / gimp_tile_width ()) *
|
|
|
|
(1 + tileLength / gimp_tile_width ()));
|
|
|
|
}
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
one_row = (gdouble) tileLength / (gdouble) imageLength;
|
|
|
|
buffer = g_malloc (TIFFTileSize (tif));
|
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2003-08-16 22:17:04 +00:00
|
|
|
channel[i].pixels = g_new (guchar,
|
2004-02-08 00:40:46 +00:00
|
|
|
tileWidth * tileLength *
|
|
|
|
channel[i].drawable->bpp);
|
1998-11-09 02:05:24 +00:00
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
|
|
|
for (y = 0; y < imageLength; y += tileLength)
|
|
|
|
{
|
|
|
|
for (x = 0; x < imageWidth; x += tileWidth)
|
|
|
|
{
|
|
|
|
gimp_progress_update (progress + one_row *
|
|
|
|
( (gdouble) x / (gdouble) imageWidth));
|
|
|
|
|
|
|
|
TIFFReadTile (tif, buffer, x, y, 0, 0);
|
|
|
|
|
|
|
|
cols = MIN (imageWidth - x, tileWidth);
|
|
|
|
rows = MIN (imageLength - y, tileLength);
|
|
|
|
|
|
|
|
if (bps == 16)
|
|
|
|
{
|
|
|
|
read_16bit (buffer, channel, photomet, y, x, rows, cols, alpha,
|
|
|
|
extra, tileWidth - cols);
|
|
|
|
}
|
|
|
|
else if (bps == 8)
|
|
|
|
{
|
|
|
|
read_8bit (buffer, channel, photomet, y, x, rows, cols, alpha,
|
|
|
|
extra, tileWidth - cols);
|
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
else if (is_bw)
|
|
|
|
{
|
|
|
|
read_bw (buffer, channel, y, x, rows, cols, tileWidth - cols);
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
read_default (buffer, channel, bps, photomet, y, x, rows, cols,
|
|
|
|
alpha, extra, tileWidth - cols);
|
|
|
|
}
|
|
|
|
}
|
2006-09-17 15:41:10 +00:00
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
progress += one_row;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
1999-09-17 22:28:25 +00:00
|
|
|
g_free(channel[i].pixels);
|
2003-07-15 12:35:39 +00:00
|
|
|
|
1999-09-17 22:28:25 +00:00
|
|
|
g_free(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-12-02 22:32:42 +00:00
|
|
|
load_lines (TIFF *tif,
|
|
|
|
channel_data *channel,
|
2004-02-08 00:40:46 +00:00
|
|
|
gushort bps,
|
2003-12-02 22:32:42 +00:00
|
|
|
gushort photomet,
|
2004-02-08 00:40:46 +00:00
|
|
|
gboolean alpha,
|
2005-01-01 19:13:38 +00:00
|
|
|
gboolean is_bw,
|
2003-12-02 22:32:42 +00:00
|
|
|
gint extra)
|
1999-09-17 22:28:25 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
uint16 planar = PLANARCONFIG_CONTIG;
|
2003-07-15 12:35:39 +00:00
|
|
|
uint32 imageLength, lineSize, cols, rows;
|
1999-09-17 22:28:25 +00:00
|
|
|
guchar *buffer;
|
2003-07-15 12:35:39 +00:00
|
|
|
gint i, y;
|
|
|
|
gint tile_height = gimp_tile_height ();
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &imageLength);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols);
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
lineSize = TIFFScanlineSize (tif);
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
channel[i].pixels = g_new (guchar,
|
|
|
|
tile_height * cols * channel[i].drawable->bpp);
|
1998-11-09 02:05:24 +00:00
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2006-09-17 15:41:10 +00:00
|
|
|
gimp_tile_cache_ntiles (1 + cols / gimp_tile_width ());
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
buffer = g_malloc (lineSize * tile_height);
|
|
|
|
|
|
|
|
if (planar == PLANARCONFIG_CONTIG)
|
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
for (y = 0; y < imageLength; y += tile_height )
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
gimp_progress_update ((gdouble) y / (gdouble) imageLength);
|
|
|
|
|
|
|
|
rows = MIN (tile_height, imageLength - y);
|
|
|
|
|
|
|
|
for (i = 0; i < rows; ++i)
|
|
|
|
TIFFReadScanline (tif, buffer + i * lineSize, y + i, 0);
|
|
|
|
|
|
|
|
if (bps == 16)
|
|
|
|
{
|
|
|
|
read_16bit (buffer, channel, photomet, y, 0, rows, cols,
|
|
|
|
alpha, extra, 0);
|
|
|
|
}
|
|
|
|
else if (bps == 8)
|
|
|
|
{
|
|
|
|
read_8bit (buffer, channel, photomet, y, 0, rows, cols,
|
|
|
|
alpha, extra, 0);
|
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
else if (is_bw)
|
|
|
|
{
|
|
|
|
read_bw (buffer, channel, y, 0, rows, cols, 0);
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
read_default (buffer, channel, bps, photomet, y, 0, rows, cols,
|
|
|
|
alpha, extra, 0);
|
|
|
|
}
|
|
|
|
}
|
1999-09-17 22:28:25 +00:00
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
|
|
|
{ /* PLANARCONFIG_SEPARATE -- Just say "No" */
|
|
|
|
uint16 s, samples;
|
|
|
|
|
|
|
|
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples);
|
|
|
|
|
|
|
|
for (s = 0; s < samples; ++s)
|
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
for (y = 0; y < imageLength; y += tile_height )
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
gimp_progress_update ((gdouble) y / (gdouble) imageLength);
|
|
|
|
|
|
|
|
rows = MIN (tile_height, imageLength - y);
|
|
|
|
for (i = 0; i < rows; ++i)
|
|
|
|
TIFFReadScanline(tif, buffer + i * lineSize, y + i, s);
|
|
|
|
|
|
|
|
read_separate (buffer, channel, bps, photomet,
|
|
|
|
y, 0, rows, cols, alpha, extra, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
1999-09-17 22:28:25 +00:00
|
|
|
g_free(channel[i].pixels);
|
2003-07-15 12:35:39 +00:00
|
|
|
|
1999-09-17 22:28:25 +00:00
|
|
|
g_free(buffer);
|
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
|
1999-09-17 22:28:25 +00:00
|
|
|
static void
|
2005-05-09 10:41:39 +00:00
|
|
|
read_16bit (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startrow,
|
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
2000-10-25 23:49:30 +00:00
|
|
|
gint extra,
|
|
|
|
gint align)
|
1999-09-17 22:28:25 +00:00
|
|
|
{
|
|
|
|
guchar *dest;
|
2000-05-01 20:22:55 +00:00
|
|
|
gint gray_val, red_val, green_val, blue_val, alpha_val;
|
|
|
|
gint col, row, i;
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
|
|
|
}
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2000-11-19 23:54:46 +00:00
|
|
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
|
|
source++; /* offset source once, to look at the high byte */
|
|
|
|
#endif
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
dest = channel[0].pixels + row * cols * channel[0].drawable->bpp;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2005-01-01 19:13:38 +00:00
|
|
|
channel[i].pixel = channel[i].pixels + row * cols;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
|
|
|
for (col = 0; col < cols; col++)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
|
|
|
gray_val = *source; source += 2;
|
|
|
|
alpha_val = *source; source += 2;
|
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
|
|
|
|
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = gray_val * 255 / alpha_val;
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-08-16 22:17:04 +00:00
|
|
|
*dest++ = *source; source += 2;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-20 17:10:16 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
}
|
2004-01-20 17:10:16 +00:00
|
|
|
else
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
|
|
|
gray_val = *source; source += 2;
|
|
|
|
alpha_val = *source; source += 2;
|
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
2004-01-20 17:10:16 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = ((alpha_val - gray_val) * 255) / alpha_val;
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
2004-01-20 17:10:16 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-08-16 22:17:04 +00:00
|
|
|
*dest++ = ~(*source); source += 2;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
2003-08-16 22:17:04 +00:00
|
|
|
*dest++= *source; source += 2;
|
|
|
|
if (alpha) *dest++= *source; source += 2;
|
2003-07-15 12:35:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
red_val = *source; source += 2;
|
|
|
|
green_val = *source; source += 2;
|
|
|
|
blue_val = *source; source += 2;
|
|
|
|
alpha_val = *source; source += 2;
|
|
|
|
red_val = MIN (red_val, alpha_val);
|
|
|
|
green_val = MIN (green_val, alpha_val);
|
|
|
|
blue_val = MIN (blue_val, alpha_val);
|
|
|
|
if (alpha_val)
|
|
|
|
{
|
|
|
|
*dest++ = (red_val * 255) / alpha_val;
|
|
|
|
*dest++ = (green_val * 255) / alpha_val;
|
|
|
|
*dest++ = (blue_val * 255) / alpha_val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = 0;
|
|
|
|
}
|
|
|
|
*dest++ = alpha_val;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-08-16 22:17:04 +00:00
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* This case was handled earlier */
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
*channel[i].pixel++ = *source; source += 2;
|
|
|
|
}
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
|
|
|
if (align)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
2003-08-16 22:17:04 +00:00
|
|
|
source += align * (1 + alpha + extra) * 2;
|
2003-07-15 12:35:39 +00:00
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_RGB:
|
2003-08-16 22:17:04 +00:00
|
|
|
source += align * (3 + alpha + extra) * 2;
|
2003-07-15 12:35:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-09-17 22:28:25 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
|
|
|
gimp_pixel_rgn_set_rect (&(channel[i].pixel_rgn), channel[i].pixels,
|
2004-02-08 00:40:46 +00:00
|
|
|
startcol, startrow, cols, rows);
|
1999-09-17 22:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-05-09 10:41:39 +00:00
|
|
|
read_8bit (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startrow,
|
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align)
|
1999-09-17 22:28:25 +00:00
|
|
|
{
|
|
|
|
guchar *dest;
|
2000-05-01 20:22:55 +00:00
|
|
|
gint gray_val, red_val, green_val, blue_val, alpha_val;
|
|
|
|
gint col, row, i;
|
1999-09-17 22:28:25 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
1999-09-17 22:28:25 +00:00
|
|
|
}
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
dest = channel[0].pixels + row * cols * channel[0].drawable->bpp;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 1; i <= extra; ++i)
|
|
|
|
channel[i].pixel = channel[i].pixels + row * cols;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
|
|
|
for (col = 0; col < cols; col++)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
gray_val = *source++;
|
|
|
|
alpha_val = *source++;
|
|
|
|
gray_val = MIN(gray_val, alpha_val);
|
2004-01-16 21:28:31 +00:00
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = gray_val * 255 / alpha_val;
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = *source++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
|
|
|
gray_val = *source++;
|
|
|
|
alpha_val = *source++;
|
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
|
|
|
|
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = ((alpha_val - gray_val) * 255) / alpha_val;
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = ~(*source++);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
|
|
|
*dest++= *source++;
|
2003-12-02 22:32:42 +00:00
|
|
|
if (alpha)
|
|
|
|
*dest++= *source++;
|
2003-07-15 12:35:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
red_val = *source++;
|
|
|
|
green_val = *source++;
|
|
|
|
blue_val = *source++;
|
|
|
|
alpha_val = *source++;
|
|
|
|
red_val = MIN (red_val, alpha_val);
|
|
|
|
blue_val = MIN (blue_val, alpha_val);
|
|
|
|
green_val = MIN (green_val, alpha_val);
|
|
|
|
|
|
|
|
if (alpha_val)
|
|
|
|
{
|
|
|
|
*dest++ = (red_val * 255) / alpha_val;
|
|
|
|
*dest++ = (green_val * 255) / alpha_val;
|
|
|
|
*dest++ = (blue_val * 255) / alpha_val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = 0;
|
|
|
|
}
|
|
|
|
*dest++ = alpha_val;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = *source++;
|
|
|
|
*dest++ = *source++;
|
|
|
|
*dest++ = *source++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* This case was handled earlier */
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
*channel[i].pixel++ = *source++;
|
|
|
|
}
|
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
if (align)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
|
|
|
source += align * (1 + alpha + extra);
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
source += align * (3 + alpha + extra);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
1999-09-17 22:28:25 +00:00
|
|
|
gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
|
2003-07-15 12:35:39 +00:00
|
|
|
startcol, startrow, cols, rows);
|
1998-11-09 02:05:24 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
static void
|
2005-05-09 10:41:39 +00:00
|
|
|
read_bw (const guchar *source,
|
2005-01-01 19:13:38 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gint startrow,
|
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gint align)
|
|
|
|
{
|
|
|
|
guchar *dest;
|
|
|
|
gint col, row;
|
|
|
|
|
|
|
|
gimp_pixel_rgn_init (&(channel[0].pixel_rgn), channel[0].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
|
|
|
|
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
|
|
|
dest = channel[0].pixels + row * cols * channel[0].drawable->bpp;
|
|
|
|
|
|
|
|
col = cols;
|
|
|
|
|
|
|
|
while (col >= 8)
|
|
|
|
{
|
|
|
|
memcpy (dest, bit2byte + *source * 8, 8);
|
|
|
|
dest += 8;
|
|
|
|
col -= 8;
|
|
|
|
source++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (col > 0)
|
|
|
|
{
|
|
|
|
memcpy (dest, bit2byte + *source * 8, col);
|
2005-01-01 19:28:59 +00:00
|
|
|
dest += col;
|
|
|
|
source++;
|
2005-01-01 19:13:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
source += align;
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_pixel_rgn_set_rect(&(channel[0].pixel_rgn), channel[0].pixels,
|
|
|
|
startcol, startrow, cols, rows);
|
|
|
|
}
|
|
|
|
|
1998-05-18 00:54:11 +00:00
|
|
|
/* Step through all <= 8-bit samples in an image */
|
|
|
|
|
|
|
|
#define NEXTSAMPLE(var) \
|
1997-11-24 22:05:25 +00:00
|
|
|
{ \
|
1998-05-18 00:54:11 +00:00
|
|
|
if (bitsleft == 0) \
|
1997-11-24 22:05:25 +00:00
|
|
|
{ \
|
2004-02-08 00:40:46 +00:00
|
|
|
source++; \
|
|
|
|
bitsleft = 8; \
|
1997-11-24 22:05:25 +00:00
|
|
|
} \
|
|
|
|
bitsleft -= bps; \
|
1999-09-17 22:28:25 +00:00
|
|
|
var = ( *source >> bitsleft ) & maxval; \
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
1998-11-09 02:05:24 +00:00
|
|
|
static void
|
2005-05-09 10:41:39 +00:00
|
|
|
read_default (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gint startrow,
|
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
2000-10-25 23:49:30 +00:00
|
|
|
gint align)
|
1998-11-09 02:05:24 +00:00
|
|
|
{
|
1999-09-17 22:28:25 +00:00
|
|
|
guchar *dest;
|
2000-05-01 20:22:55 +00:00
|
|
|
gint gray_val, red_val, green_val, blue_val, alpha_val;
|
|
|
|
gint col, row, i;
|
|
|
|
gint bitsleft = 8, maxval = (1 << bps) - 1;
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
1998-11-09 02:05:24 +00:00
|
|
|
}
|
1998-05-18 00:54:11 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
dest = channel[0].pixels + row * cols * channel[0].drawable->bpp;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2005-01-01 19:13:38 +00:00
|
|
|
channel[i].pixel = channel[i].pixels + row * cols;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
|
|
|
for (col = 0; col < cols; col++)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
NEXTSAMPLE (gray_val);
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
NEXTSAMPLE (alpha_val);
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = (gray_val * 255) / maxval;
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = (gray_val * 65025) / (alpha_val * maxval);
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
|
|
|
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = (gray_val * 255) / maxval;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
NEXTSAMPLE (gray_val);
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
NEXTSAMPLE (alpha_val);
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = ((maxval - gray_val) * 255) / maxval;
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
else
|
2004-01-16 21:28:31 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
2004-01-20 17:10:16 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
if (alpha_val)
|
2005-01-01 19:13:38 +00:00
|
|
|
*dest++ = ((maxval - gray_val) * 65025) /
|
|
|
|
(alpha_val * maxval);
|
2004-01-16 21:28:31 +00:00
|
|
|
else
|
|
|
|
*dest++ = 0;
|
|
|
|
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = ((maxval - gray_val) * 255) / maxval;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
|
|
|
NEXTSAMPLE (*dest++);
|
|
|
|
if (alpha)
|
|
|
|
NEXTSAMPLE (*dest++);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
NEXTSAMPLE (red_val);
|
|
|
|
NEXTSAMPLE (green_val);
|
|
|
|
NEXTSAMPLE (blue_val);
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
NEXTSAMPLE (alpha_val);
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
*dest++ = red_val;
|
|
|
|
*dest++ = green_val;
|
|
|
|
*dest++ = blue_val;
|
|
|
|
*dest++ = alpha_val;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
red_val = MIN (red_val, alpha_val);
|
|
|
|
blue_val = MIN (blue_val, alpha_val);
|
|
|
|
green_val = MIN (green_val, alpha_val);
|
|
|
|
|
|
|
|
if (alpha_val)
|
|
|
|
{
|
|
|
|
*dest++ = (red_val * 255) / alpha_val;
|
|
|
|
*dest++ = (green_val * 255) / alpha_val;
|
|
|
|
*dest++ = (blue_val * 255) / alpha_val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = 0;
|
|
|
|
}
|
2004-01-20 17:10:16 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
*dest++ = alpha_val;
|
2003-07-15 12:35:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = red_val;
|
|
|
|
*dest++ = green_val;
|
|
|
|
*dest++ = blue_val;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* This case was handled earlier */
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
NEXTSAMPLE(alpha_val);
|
|
|
|
*channel[i].pixel++ = alpha_val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (align)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i < align * (1 + alpha + extra); ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
NEXTSAMPLE (alpha_val);
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_RGB:
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i < align * (3 + alpha + extra); ++i)
|
|
|
|
NEXTSAMPLE (alpha_val);
|
2003-07-15 12:35:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
bitsleft = 0;
|
2000-10-25 23:49:30 +00:00
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
2003-08-16 22:17:04 +00:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 12:35:39 +00:00
|
|
|
gimp_pixel_rgn_set_rect (&(channel[i].pixel_rgn), channel[i].pixels,
|
|
|
|
startcol, startrow, cols, rows);
|
1998-11-09 02:05:24 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1998-11-09 02:05:24 +00:00
|
|
|
static void
|
2005-05-09 10:41:39 +00:00
|
|
|
read_separate (const guchar *source,
|
2004-02-08 00:40:46 +00:00
|
|
|
channel_data *channel,
|
2000-05-01 20:22:55 +00:00
|
|
|
gushort bps,
|
2004-02-08 00:40:46 +00:00
|
|
|
gushort photomet,
|
2000-05-01 20:22:55 +00:00
|
|
|
gint startrow,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
2003-12-02 22:32:42 +00:00
|
|
|
gboolean alpha,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint extra,
|
|
|
|
gint sample)
|
1998-11-09 02:05:24 +00:00
|
|
|
{
|
1999-09-17 22:28:25 +00:00
|
|
|
guchar *dest;
|
2000-05-01 20:22:55 +00:00
|
|
|
gint col, row, c;
|
|
|
|
gint bitsleft = 8, maxval = (1 << bps) - 1;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
if (bps > 8)
|
|
|
|
{
|
|
|
|
g_message ("Unsupported layout");
|
|
|
|
gimp_quit ();
|
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
if (sample < channel[0].drawable->bpp)
|
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = (sample - channel[0].drawable->bpp) + 4;
|
|
|
|
photomet = PHOTOMETRIC_MINISBLACK;
|
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
|
1999-09-17 22:28:25 +00:00
|
|
|
gimp_pixel_rgn_init (&(channel[c].pixel_rgn), channel[c].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
1998-11-09 02:05:24 +00:00
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
gimp_pixel_rgn_get_rect (&(channel[c].pixel_rgn), channel[c].pixels,
|
|
|
|
startcol, startrow, cols, rows);
|
|
|
|
|
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
|
|
|
dest = channel[c].pixels + row * cols * channel[c].drawable->bpp;
|
|
|
|
|
|
|
|
if (c == 0)
|
|
|
|
{
|
|
|
|
for (col = 0; col < cols; ++col)
|
|
|
|
NEXTSAMPLE(dest[col * channel[0].drawable->bpp + sample]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (col = 0; col < cols; ++col)
|
|
|
|
NEXTSAMPLE(dest[col]);
|
|
|
|
}
|
1998-11-09 02:05:24 +00:00
|
|
|
}
|
2003-07-15 12:35:39 +00:00
|
|
|
|
|
|
|
gimp_pixel_rgn_set_rect (&(channel[c].pixel_rgn), channel[c].pixels,
|
|
|
|
startcol, startrow, cols, rows);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** pnmtotiff.c - converts a portable anymap to a Tagged Image File
|
|
|
|
**
|
|
|
|
** Derived by Jef Poskanzer from ras2tif.c, which is:
|
|
|
|
**
|
|
|
|
** Copyright (c) 1990 by Sun Microsystems, Inc.
|
|
|
|
**
|
|
|
|
** Author: Patrick J. Naughton
|
|
|
|
** naughton@wind.sun.com
|
|
|
|
**
|
|
|
|
** 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.
|
|
|
|
*/
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
static gboolean
|
|
|
|
save_image (const gchar *filename,
|
2004-02-08 00:40:46 +00:00
|
|
|
gint32 image,
|
|
|
|
gint32 layer,
|
|
|
|
gint32 orig_image) /* the export function might have created a duplicate */
|
1999-10-03 18:54:54 +00:00
|
|
|
{
|
2000-05-01 20:22:55 +00:00
|
|
|
TIFF *tif;
|
|
|
|
gushort red[256];
|
|
|
|
gushort grn[256];
|
|
|
|
gushort blu[256];
|
|
|
|
gint cols, col, rows, row, i;
|
|
|
|
glong rowsperstrip;
|
|
|
|
gushort compression;
|
|
|
|
gushort extra_samples[1];
|
2003-12-02 22:32:42 +00:00
|
|
|
gboolean alpha;
|
2000-05-01 20:22:55 +00:00
|
|
|
gshort predictor;
|
|
|
|
gshort photometric;
|
|
|
|
gshort samplesperpixel;
|
|
|
|
gshort bitspersample;
|
|
|
|
gint bytesperrow;
|
|
|
|
guchar *t, *src, *data;
|
|
|
|
guchar *cmap;
|
|
|
|
gint colors;
|
|
|
|
gint success;
|
2003-12-02 22:32:42 +00:00
|
|
|
GimpDrawable *drawable;
|
2000-08-22 01:26:57 +00:00
|
|
|
GimpImageType drawable_type;
|
2003-12-02 22:32:42 +00:00
|
|
|
GimpPixelRgn pixel_rgn;
|
2000-05-01 20:22:55 +00:00
|
|
|
gint tile_height;
|
|
|
|
gint y, yend;
|
2005-01-01 19:13:38 +00:00
|
|
|
gboolean is_bw = FALSE, invert = TRUE;
|
|
|
|
guchar bw_map[] = { 0, 0, 0, 255, 255, 255 };
|
|
|
|
guchar wb_map[] = { 255, 255, 255, 0, 0, 0 };
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
compression = tsvals.compression;
|
2000-05-12 06:53:15 +00:00
|
|
|
|
|
|
|
/* Disabled because this isn't in older releases of libtiff, and it
|
|
|
|
wasn't helping much anyway */
|
|
|
|
#if 0
|
2000-04-20 04:38:31 +00:00
|
|
|
if (TIFFFindCODEC((uint16) compression) == NULL)
|
|
|
|
compression = COMPRESSION_NONE; /* CODEC not available */
|
2000-05-12 06:53:15 +00:00
|
|
|
#endif
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
predictor = 0;
|
2000-04-20 04:38:31 +00:00
|
|
|
tile_height = gimp_tile_height ();
|
|
|
|
rowsperstrip = tile_height;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
libgimp/gimp.def libgimp/gimpui.def libgimp/makefile.{cygwin,msc}
2000-02-15 Tor Lillqvist <tml@iki.fi>
* libgimp/gimp.def
* libgimp/gimpui.def
* libgimp/makefile.{cygwin,msc}
* app/makefile.{cygwin,msc}
* plug-ins/makefile.{cygwin,msc}: Updates.
* app/datafiles.c (is_script): New Win32-only function, which
tests if a file's extension matches one of the extensions in the
PATHEXT environment variable (which the cmd.exe command
interpreter also uses). This is to avoid starting applications
associated with any random data file the user might have dropped
in the plug-ins folder, while still supporting plug-ins written in
scripting languages.
* app/gimpparasite.c (gimp_parasiterc_save): (Win32:) Cannot
rename to an existing file.
* plug-ins/Lighting/lighting_image.c
* plug-ins/Lighting/lighting_share.c
* plug-ins/MapObject/mapobject_preview.c
* plug-ins/MapObject/mapobject_shade.c: Use G_PI.
* plug-ins/common/gz.c: #ifdef G_OS_WIN32 was used before its
potential definition via glib.h.
* plug-ins/common/jpeg.c: Also recognize Exif files, which are
typically produced by digital cameras. The usually have a .jpg
file name extension, and would thus already match this plug-in,
but add the magic string just in case. They are loaded just fine
by libjpeg even if they don't have the JFIF signature.
* plug-ins/common/tiff.c: Set TIFF warning and error handler, so
we get to pass libtiff's messages through the normal channels.
2000-02-14 22:44:06 +00:00
|
|
|
TIFFSetWarningHandler (tiff_warning);
|
|
|
|
TIFFSetErrorHandler (tiff_error);
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
tif = TIFFOpen (filename, "w");
|
2003-07-15 12:35:39 +00:00
|
|
|
if (!tif)
|
1999-10-03 18:54:54 +00:00
|
|
|
{
|
2003-11-15 13:53:33 +00:00
|
|
|
g_message (_("Could not open '%s' for writing: %s"),
|
2004-01-19 03:06:04 +00:00
|
|
|
gimp_filename_to_utf8 (filename), g_strerror (errno));
|
2003-07-15 12:35:39 +00:00
|
|
|
return FALSE;
|
1999-10-03 18:54:54 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-30 08:16:10 +00:00
|
|
|
gimp_progress_init_printf (_("Saving '%s'"),
|
2005-09-29 18:34:08 +00:00
|
|
|
gimp_filename_to_utf8 (filename));
|
1997-11-24 22:05:25 +00:00
|
|
|
|
1998-05-18 00:54:11 +00:00
|
|
|
drawable = gimp_drawable_get (layer);
|
|
|
|
drawable_type = gimp_drawable_type (layer);
|
2000-05-01 20:22:55 +00:00
|
|
|
gimp_pixel_rgn_init (&pixel_rgn, drawable,
|
2004-02-08 00:40:46 +00:00
|
|
|
0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
cols = drawable->width;
|
|
|
|
rows = drawable->height;
|
|
|
|
|
2006-09-17 15:41:10 +00:00
|
|
|
gimp_tile_cache_ntiles (1 + drawable->width / gimp_tile_width ());
|
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
switch (drawable_type)
|
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_RGB_IMAGE:
|
2003-12-02 22:32:42 +00:00
|
|
|
predictor = 2;
|
1997-11-24 22:05:25 +00:00
|
|
|
samplesperpixel = 3;
|
2003-12-02 22:32:42 +00:00
|
|
|
bitspersample = 8;
|
|
|
|
photometric = PHOTOMETRIC_RGB;
|
|
|
|
bytesperrow = cols * 3;
|
|
|
|
alpha = FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_GRAY_IMAGE:
|
1997-11-24 22:05:25 +00:00
|
|
|
samplesperpixel = 1;
|
2003-12-02 22:32:42 +00:00
|
|
|
bitspersample = 8;
|
|
|
|
photometric = PHOTOMETRIC_MINISBLACK;
|
|
|
|
bytesperrow = cols;
|
|
|
|
alpha = FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_RGBA_IMAGE:
|
2003-12-02 22:32:42 +00:00
|
|
|
predictor = 2;
|
1997-11-24 22:05:25 +00:00
|
|
|
samplesperpixel = 4;
|
2003-12-02 22:32:42 +00:00
|
|
|
bitspersample = 8;
|
|
|
|
photometric = PHOTOMETRIC_RGB;
|
|
|
|
bytesperrow = cols * 4;
|
|
|
|
alpha = TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_GRAYA_IMAGE:
|
1997-11-24 22:05:25 +00:00
|
|
|
samplesperpixel = 2;
|
2003-12-02 22:32:42 +00:00
|
|
|
bitspersample = 8;
|
|
|
|
photometric = PHOTOMETRIC_MINISBLACK;
|
|
|
|
bytesperrow = cols * 2;
|
|
|
|
alpha = TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_INDEXED_IMAGE:
|
2004-11-02 12:00:25 +00:00
|
|
|
cmap = gimp_image_get_colormap (image, &colors);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
if (colors == 2)
|
|
|
|
{
|
|
|
|
is_bw = (memcmp (cmap, bw_map, 6) == 0);
|
|
|
|
photometric = PHOTOMETRIC_MINISWHITE;
|
2005-05-09 10:41:39 +00:00
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
if (!is_bw)
|
|
|
|
{
|
|
|
|
is_bw = (memcmp (cmap, wb_map, 6) == 0);
|
|
|
|
|
|
|
|
if (is_bw)
|
|
|
|
invert = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_bw)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
2005-01-01 19:13:38 +00:00
|
|
|
bitspersample = 1;
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
bitspersample = 8;
|
|
|
|
photometric = PHOTOMETRIC_PALETTE;
|
|
|
|
|
|
|
|
for (i = 0; i < colors; i++)
|
|
|
|
{
|
|
|
|
red[i] = *cmap++ * 65535 / 255;
|
|
|
|
grn[i] = *cmap++ * 65535 / 255;
|
|
|
|
blu[i] = *cmap++ * 65535 / 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
samplesperpixel = 1;
|
|
|
|
bytesperrow = cols;
|
|
|
|
alpha = FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
break;
|
2000-08-22 01:26:57 +00:00
|
|
|
case GIMP_INDEXEDA_IMAGE:
|
2004-11-27 12:39:08 +00:00
|
|
|
g_message ("TIFF save cannot handle indexed images with alpha channel.");
|
2003-07-15 12:35:39 +00:00
|
|
|
default:
|
|
|
|
return FALSE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set TIFF parameters. */
|
2000-01-30 05:01:58 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_SUBFILETYPE, 0);
|
1997-11-24 22:05:25 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, cols);
|
|
|
|
TIFFSetField (tif, TIFFTAG_IMAGELENGTH, rows);
|
|
|
|
TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
|
|
|
|
TIFFSetField (tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
|
|
|
TIFFSetField (tif, TIFFTAG_COMPRESSION, compression);
|
2004-11-02 13:44:13 +00:00
|
|
|
|
2000-04-20 04:38:31 +00:00
|
|
|
if ((compression == COMPRESSION_LZW || compression == COMPRESSION_DEFLATE)
|
2004-11-02 13:44:13 +00:00
|
|
|
&& (predictor != 0))
|
2003-12-02 22:32:42 +00:00
|
|
|
{
|
|
|
|
TIFFSetField (tif, TIFFTAG_PREDICTOR, predictor);
|
|
|
|
}
|
2004-11-02 13:44:13 +00:00
|
|
|
|
2003-12-02 22:32:42 +00:00
|
|
|
if (alpha)
|
|
|
|
{
|
2004-06-05 10:27:47 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
extra_samples [0] = EXTRASAMPLE_UNASSALPHA;
|
|
|
|
else
|
|
|
|
extra_samples [0] = EXTRASAMPLE_ASSOCALPHA;
|
2004-11-02 12:00:25 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
|
2003-12-02 22:32:42 +00:00
|
|
|
}
|
2004-11-02 13:44:13 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, photometric);
|
|
|
|
TIFFSetField (tif, TIFFTAG_DOCUMENTNAME, filename);
|
|
|
|
TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
|
|
|
|
TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
|
|
|
/* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, rows / rowsperstrip ); */
|
|
|
|
TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
|
|
|
|
1998-10-05 10:05:29 +00:00
|
|
|
/* resolution fields */
|
|
|
|
{
|
2000-02-07 20:35:13 +00:00
|
|
|
gdouble xresolution;
|
|
|
|
gdouble yresolution;
|
|
|
|
gushort save_unit = RESUNIT_INCH;
|
|
|
|
GimpUnit unit;
|
|
|
|
gfloat factor;
|
1999-05-22 17:56:35 +00:00
|
|
|
|
1999-10-03 18:54:54 +00:00
|
|
|
gimp_image_get_resolution (orig_image, &xresolution, &yresolution);
|
|
|
|
unit = gimp_image_get_unit (orig_image);
|
1999-05-22 17:56:35 +00:00
|
|
|
factor = gimp_unit_get_factor (unit);
|
|
|
|
|
|
|
|
/* if we have a metric unit, save the resolution as centimeters
|
|
|
|
*/
|
2000-02-07 20:35:13 +00:00
|
|
|
if ((ABS (factor - 0.0254) < 1e-5) || /* m */
|
2004-02-08 00:40:46 +00:00
|
|
|
(ABS (factor - 0.254) < 1e-5) || /* dm */
|
|
|
|
(ABS (factor - 2.54) < 1e-5) || /* cm */
|
|
|
|
(ABS (factor - 25.4) < 1e-5)) /* mm */
|
1999-05-22 17:56:35 +00:00
|
|
|
{
|
2004-02-08 00:40:46 +00:00
|
|
|
save_unit = RESUNIT_CENTIMETER;
|
|
|
|
xresolution /= 2.54;
|
|
|
|
yresolution /= 2.54;
|
1999-05-22 17:56:35 +00:00
|
|
|
}
|
1998-11-14 23:28:47 +00:00
|
|
|
|
1999-05-22 17:56:35 +00:00
|
|
|
if (xresolution > 1e-5 && yresolution > 1e-5)
|
1998-10-05 10:05:29 +00:00
|
|
|
{
|
2004-02-08 00:40:46 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_XRESOLUTION, xresolution);
|
|
|
|
TIFFSetField (tif, TIFFTAG_YRESOLUTION, yresolution);
|
|
|
|
TIFFSetField (tif, TIFFTAG_RESOLUTIONUNIT, save_unit);
|
1998-10-05 10:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
/* The TIFF spec explicitely says ASCII for the image description. */
|
|
|
|
if (image_comment)
|
|
|
|
{
|
|
|
|
const gchar *c = image_comment;
|
|
|
|
gint len;
|
|
|
|
|
|
|
|
for (len = strlen (c); len; c++, len--)
|
|
|
|
{
|
2003-10-06 21:22:09 +00:00
|
|
|
if ((guchar) *c > 127)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
g_message (_("The TIFF format only supports comments in\n"
|
|
|
|
"7bit ASCII encoding. No comment is saved."));
|
|
|
|
|
|
|
|
g_free (image_comment);
|
|
|
|
image_comment = NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-11 22:50:03 +00:00
|
|
|
/* do we have a comment? If so, create a new parasite to hold it,
|
|
|
|
* and attach it to the image. The attach function automatically
|
|
|
|
* detaches a previous incarnation of the parasite. */
|
2001-09-17 18:11:15 +00:00
|
|
|
if (image_comment && *image_comment)
|
1999-10-03 18:54:54 +00:00
|
|
|
{
|
2000-05-26 22:28:40 +00:00
|
|
|
GimpParasite *parasite;
|
2003-07-15 12:35:39 +00:00
|
|
|
|
1999-10-03 18:54:54 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_IMAGEDESCRIPTION, image_comment);
|
2000-05-26 22:28:40 +00:00
|
|
|
parasite = gimp_parasite_new ("gimp-comment",
|
2004-02-08 00:40:46 +00:00
|
|
|
GIMP_PARASITE_PERSISTENT,
|
|
|
|
strlen (image_comment) + 1, image_comment);
|
1999-10-17 00:07:55 +00:00
|
|
|
gimp_image_parasite_attach (orig_image, parasite);
|
2000-05-26 22:28:40 +00:00
|
|
|
gimp_parasite_free (parasite);
|
1999-10-03 18:54:54 +00:00
|
|
|
}
|
1998-10-11 22:50:03 +00:00
|
|
|
|
2000-06-18 01:07:13 +00:00
|
|
|
/* do we have an ICC profile? If so, write it to the TIFF file */
|
|
|
|
#ifdef TIFFTAG_ICCPROFILE
|
|
|
|
{
|
2000-08-22 01:26:57 +00:00
|
|
|
GimpParasite *parasite;
|
2003-07-02 00:15:09 +00:00
|
|
|
uint32 profile_size;
|
|
|
|
const guchar *icc_profile;
|
2000-06-18 01:07:13 +00:00
|
|
|
|
|
|
|
parasite = gimp_image_parasite_find (orig_image, "icc-profile");
|
|
|
|
if (parasite)
|
|
|
|
{
|
2003-07-02 00:15:09 +00:00
|
|
|
profile_size = gimp_parasite_data_size (parasite);
|
2004-02-08 00:40:46 +00:00
|
|
|
icc_profile = gimp_parasite_data (parasite);
|
2000-06-18 01:07:13 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_ICCPROFILE, profile_size, icc_profile);
|
2003-07-02 00:15:09 +00:00
|
|
|
gimp_parasite_free (parasite);
|
2000-06-18 01:07:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
if (!is_bw && drawable_type == GIMP_INDEXED_IMAGE)
|
1997-11-24 22:05:25 +00:00
|
|
|
TIFFSetField (tif, TIFFTAG_COLORMAP, red, grn, blu);
|
|
|
|
|
|
|
|
/* array to rearrange data */
|
|
|
|
src = g_new (guchar, bytesperrow * tile_height);
|
|
|
|
data = g_new (guchar, bytesperrow);
|
|
|
|
|
|
|
|
/* Now write the TIFF data. */
|
|
|
|
for (y = 0; y < rows; y = yend)
|
|
|
|
{
|
|
|
|
yend = y + tile_height;
|
|
|
|
yend = MIN (yend, rows);
|
|
|
|
|
|
|
|
gimp_pixel_rgn_get_rect (&pixel_rgn, src, 0, y, cols, yend - y);
|
|
|
|
|
|
|
|
for (row = y; row < yend; row++)
|
2004-02-08 00:40:46 +00:00
|
|
|
{
|
|
|
|
t = src + bytesperrow * (row - y);
|
|
|
|
|
|
|
|
switch (drawable_type)
|
|
|
|
{
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
2005-01-01 19:13:38 +00:00
|
|
|
if (is_bw)
|
|
|
|
{
|
|
|
|
byte2bit (t, bytesperrow, data, invert);
|
|
|
|
success = (TIFFWriteScanline (tif, data, row, 0) >= 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
|
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
break;
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
|
|
|
|
break;
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
case GIMP_GRAYA_IMAGE:
|
|
|
|
for (col = 0; col < cols*samplesperpixel; col+=samplesperpixel)
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
data[col + 0] = t[col + 0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* pre-multiply gray by alpha */
|
|
|
|
data[col + 0] = (t[col + 0] * t[col + 1]) / 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
data[col + 1] = t[col + 1]; /* alpha channel */
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
success = (TIFFWriteScanline (tif, data, row, 0) >= 0);
|
|
|
|
break;
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
case GIMP_RGB_IMAGE:
|
|
|
|
success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
|
|
|
|
break;
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
case GIMP_RGBA_IMAGE:
|
|
|
|
for (col = 0; col < cols*samplesperpixel; col+=samplesperpixel)
|
|
|
|
{
|
2004-01-16 21:28:31 +00:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
data[col+0] = t[col + 0];
|
|
|
|
data[col+1] = t[col + 1];
|
|
|
|
data[col+2] = t[col + 2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* pre-multiply rgb by alpha */
|
|
|
|
data[col+0] = t[col + 0] * t[col + 3] / 255;
|
|
|
|
data[col+1] = t[col + 1] * t[col + 3] / 255;
|
|
|
|
data[col+2] = t[col + 2] * t[col + 3] / 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
data[col+3] = t[col + 3]; /* alpha channel */
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
success = (TIFFWriteScanline (tif, data, row, 0) >= 0);
|
|
|
|
break;
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2004-02-08 00:40:46 +00:00
|
|
|
default:
|
|
|
|
success = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!success)
|
2003-07-15 12:35:39 +00:00
|
|
|
{
|
|
|
|
g_message ("Failed a scanline write on row %d", row);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-02-08 00:40:46 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-06-13 14:37:00 +00:00
|
|
|
gimp_progress_update ((gdouble) row / (gdouble) rows);
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TIFFFlushData (tif);
|
|
|
|
TIFFClose (tif);
|
|
|
|
|
|
|
|
gimp_drawable_detach (drawable);
|
|
|
|
g_free (data);
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
return TRUE;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2003-07-15 12:35:39 +00:00
|
|
|
static gboolean
|
2004-07-12 07:41:23 +00:00
|
|
|
save_dialog (gboolean alpha)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2005-09-09 18:38:00 +00:00
|
|
|
GtkWidget *dialog;
|
2000-01-25 17:46:56 +00:00
|
|
|
GtkWidget *vbox;
|
1997-11-24 22:05:25 +00:00
|
|
|
GtkWidget *frame;
|
1998-10-11 22:50:03 +00:00
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *label;
|
|
|
|
GtkWidget *entry;
|
2004-01-16 21:28:31 +00:00
|
|
|
GtkWidget *toggle;
|
2003-11-06 15:27:05 +00:00
|
|
|
gboolean run;
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
dialog = gimp_dialog_new (_("Save as TIFF"), PLUG_IN_BINARY,
|
|
|
|
NULL, 0,
|
|
|
|
gimp_standard_help_func, SAVE_PROC,
|
2000-01-08 20:00:10 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
GTK_STOCK_SAVE, GTK_RESPONSE_OK,
|
2000-01-08 20:00:10 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
2005-08-15 22:42:34 +00:00
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
2005-02-08 20:40:33 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
gimp_window_set_transient (GTK_WINDOW (dialog));
|
|
|
|
|
2004-05-20 00:50:05 +00:00
|
|
|
vbox = gtk_vbox_new (FALSE, 12);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
|
2005-09-09 18:38:00 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
|
|
|
|
vbox, FALSE, TRUE, 0);
|
1998-10-11 22:50:03 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/* compression */
|
2003-11-14 18:05:39 +00:00
|
|
|
frame = gimp_int_radio_group_new (TRUE, _("Compression"),
|
|
|
|
G_CALLBACK (gimp_radio_button_update),
|
|
|
|
&tsvals.compression, tsvals.compression,
|
2002-01-08 09:20:02 +00:00
|
|
|
|
2003-11-14 18:05:39 +00:00
|
|
|
_("_None"), COMPRESSION_NONE, NULL,
|
|
|
|
_("_LZW"), COMPRESSION_LZW, NULL,
|
|
|
|
_("_Pack Bits"), COMPRESSION_PACKBITS, NULL,
|
|
|
|
_("_Deflate"), COMPRESSION_DEFLATE, NULL,
|
|
|
|
_("_JPEG"), COMPRESSION_JPEG, NULL,
|
2002-01-08 09:20:02 +00:00
|
|
|
|
2003-11-14 18:05:39 +00:00
|
|
|
NULL);
|
2002-01-08 09:20:02 +00:00
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (frame);
|
1998-10-11 22:50:03 +00:00
|
|
|
|
2004-01-16 21:28:31 +00:00
|
|
|
/* Keep colors behind alpha mask */
|
2004-01-20 17:10:16 +00:00
|
|
|
toggle = gtk_check_button_new_with_mnemonic
|
2004-01-16 21:28:31 +00:00
|
|
|
( _("Save _color values from transparent pixels"));
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
|
2004-07-12 07:41:23 +00:00
|
|
|
alpha && tsvals.save_transp_pixels);
|
|
|
|
gtk_widget_set_sensitive (toggle, alpha);
|
2004-01-16 21:28:31 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
|
|
|
g_signal_connect (toggle, "toggled",
|
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&tsvals.save_transp_pixels);
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
/* comment entry */
|
2004-05-20 00:50:05 +00:00
|
|
|
hbox = gtk_hbox_new (FALSE, 6);
|
2000-01-25 17:46:56 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
2000-01-08 20:00:10 +00:00
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
2000-01-09 06:02:20 +00:00
|
|
|
label = gtk_label_new ( _("Comment:"));
|
2000-01-08 20:00:10 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
1998-10-11 22:50:03 +00:00
|
|
|
gtk_widget_show (label);
|
2000-01-08 20:00:10 +00:00
|
|
|
|
1998-10-11 22:50:03 +00:00
|
|
|
entry = gtk_entry_new ();
|
|
|
|
gtk_widget_show (entry);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
2004-06-01 17:15:56 +00:00
|
|
|
gtk_entry_set_text (GTK_ENTRY (entry), image_comment ? image_comment : "");
|
2002-01-08 09:20:02 +00:00
|
|
|
|
2003-01-07 06:16:02 +00:00
|
|
|
g_signal_connect (entry, "changed",
|
2002-01-08 09:20:02 +00:00
|
|
|
G_CALLBACK (comment_entry_callback),
|
|
|
|
NULL);
|
1998-10-11 22:50:03 +00:00
|
|
|
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
2000-01-25 17:46:56 +00:00
|
|
|
gtk_widget_show (vbox);
|
2005-09-09 18:38:00 +00:00
|
|
|
gtk_widget_show (dialog);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-09-09 18:38:00 +00:00
|
|
|
gtk_widget_destroy (dialog);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
return run;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
1998-10-11 22:50:03 +00:00
|
|
|
static void
|
|
|
|
comment_entry_callback (GtkWidget *widget,
|
2004-02-08 00:40:46 +00:00
|
|
|
gpointer data)
|
1998-10-11 22:50:03 +00:00
|
|
|
{
|
2003-12-02 22:32:42 +00:00
|
|
|
const gchar *text = gtk_entry_get_text (GTK_ENTRY (widget));
|
1998-10-11 22:50:03 +00:00
|
|
|
|
1999-10-03 18:54:54 +00:00
|
|
|
g_free (image_comment);
|
|
|
|
image_comment = g_strdup (text);
|
1998-10-11 22:50:03 +00:00
|
|
|
}
|
2005-01-01 19:13:38 +00:00
|
|
|
|
2005-05-09 10:41:39 +00:00
|
|
|
/* Convert n bytes of 0/1 to a line of bits */
|
|
|
|
static void
|
|
|
|
byte2bit (const guchar *byteline,
|
|
|
|
gint width,
|
|
|
|
guchar *bitline,
|
|
|
|
gboolean invert)
|
|
|
|
{
|
|
|
|
guchar bitval;
|
|
|
|
guchar rest[8];
|
|
|
|
|
|
|
|
while (width >= 8)
|
|
|
|
{
|
|
|
|
bitval = 0;
|
|
|
|
if (*(byteline++)) bitval |= 0x80;
|
|
|
|
if (*(byteline++)) bitval |= 0x40;
|
|
|
|
if (*(byteline++)) bitval |= 0x20;
|
|
|
|
if (*(byteline++)) bitval |= 0x10;
|
|
|
|
if (*(byteline++)) bitval |= 0x08;
|
|
|
|
if (*(byteline++)) bitval |= 0x04;
|
|
|
|
if (*(byteline++)) bitval |= 0x02;
|
|
|
|
if (*(byteline++)) bitval |= 0x01;
|
|
|
|
*(bitline++) = invert ? ~bitval : bitval;
|
|
|
|
width -= 8;
|
|
|
|
}
|
|
|
|
if (width > 0)
|
|
|
|
{
|
|
|
|
memset (rest, 0, 8);
|
|
|
|
memcpy (rest, byteline, width);
|
|
|
|
bitval = 0;
|
|
|
|
byteline = rest;
|
|
|
|
if (*(byteline++)) bitval |= 0x80;
|
|
|
|
if (*(byteline++)) bitval |= 0x40;
|
|
|
|
if (*(byteline++)) bitval |= 0x20;
|
|
|
|
if (*(byteline++)) bitval |= 0x10;
|
|
|
|
if (*(byteline++)) bitval |= 0x08;
|
|
|
|
if (*(byteline++)) bitval |= 0x04;
|
|
|
|
if (*(byteline++)) bitval |= 0x02;
|
|
|
|
*bitline = invert ? ~bitval & (0xff << (8 - width)) : bitval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-01 19:13:38 +00:00
|
|
|
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;
|
|
|
|
}
|