2007-06-06 16:44:52 +08:00
|
|
|
/* tiff loading for GIMP
|
1997-11-25 06:05:25 +08:00
|
|
|
* -Peter Mattis
|
2003-12-03 06:32:42 +08:00
|
|
|
*
|
1998-05-18 08:54:11 +08:00
|
|
|
* The TIFF loading code has been completely revamped by Nick Lamb
|
|
|
|
* njl195@zepler.org.uk -- 18 May 1998
|
1999-09-18 06:28:25 +08:00
|
|
|
* And it now gains support for tiles (and doubtless a zillion bugs)
|
|
|
|
* njl195@zepler.org.uk -- 12 June 1999
|
2000-04-20 12:38:31 +08:00
|
|
|
* LZW patent fuss continues :(
|
|
|
|
* njl195@zepler.org.uk -- 20 April 2000
|
1997-11-25 06:05:25 +08:00
|
|
|
* The code for this filter is based on "tifftopnm" and "pnmtotiff",
|
|
|
|
* 2 programs that are a part of the netpbm package.
|
2000-06-18 09:07:13 +08:00
|
|
|
* khk@khk.net -- 13 May 2000
|
2003-07-15 20:35:39 +08:00
|
|
|
* Added support for ICCPROFILE tiff tag. If this tag is present in a
|
2000-06-18 09:07:13 +08:00
|
|
|
* TIFF file, then a parasite is created and vice versa.
|
2002-12-13 22:57:16 +08:00
|
|
|
* peter@kirchgessner.net -- 29 Oct 2002
|
|
|
|
* Progress bar only when run interactive
|
2004-01-10 03:48:07 +08:00
|
|
|
* Added support for layer offsets - pablo.dangelo@web.de -- 7 Jan 2004
|
2004-01-17 05:28:31 +08:00
|
|
|
* Honor EXTRASAMPLES tag while loading images with alphachannel
|
|
|
|
* pablo.dangelo@web.de -- 16 Jan 2004
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2006-09-13 04:45:51 +08:00
|
|
|
* tifftopnm.c - converts a Tagged Image File to a portable anymap
|
|
|
|
*
|
|
|
|
* Derived by Jef Poskanzer from tif2ras.c, which is:
|
|
|
|
*
|
|
|
|
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* Author: Patrick J. Naughton
|
|
|
|
* naughton@wind.sun.com
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
|
|
* documentation for any purpose and without fee is hereby granted,
|
|
|
|
* provided that the above copyright notice appear in all copies and that
|
|
|
|
* both that copyright notice and this permission notice appear in
|
|
|
|
* supporting documentation.
|
|
|
|
*
|
|
|
|
* This file is provided AS IS with no warranties of any kind. The author
|
|
|
|
* shall have no liability with respect to the infringement of copyrights,
|
|
|
|
* trade secrets or any patents by this file or any part thereof. In no
|
|
|
|
* event will the author be liable for any lost revenue or profits or
|
|
|
|
* other special, indirect and consequential damages.
|
|
|
|
*/
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
2003-06-13 22:37:00 +08:00
|
|
|
#include <errno.h>
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <string.h>
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2007-07-29 19:26:36 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <glib/gstdio.h>
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
#include <libgimpbase/gimpwin32-io.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef _O_BINARY
|
|
|
|
#define _O_BINARY 0
|
|
|
|
#endif
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <tiffio.h>
|
2000-01-09 04:00:10 +08:00
|
|
|
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2000-01-09 14:02:20 +08:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
1998-10-12 06:50:03 +08:00
|
|
|
|
2000-05-02 04:22:55 +08:00
|
|
|
|
2005-08-16 06:42:34 +08:00
|
|
|
#define LOAD_PROC "file-tiff-load"
|
2007-04-25 21:45:10 +08:00
|
|
|
#define PLUG_IN_BINARY "tiff-load"
|
2005-08-16 06:42:34 +08:00
|
|
|
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2003-07-15 20:35:39 +08:00
|
|
|
gint compression;
|
|
|
|
gint fillorder;
|
2004-01-17 05:28:31 +08:00
|
|
|
gboolean save_transp_pixels;
|
1997-11-25 06:05:25 +08:00
|
|
|
} TiffSaveVals;
|
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2002-12-13 22:57:16 +08:00
|
|
|
gint32 ID;
|
2000-08-22 09:26:57 +08:00
|
|
|
GimpDrawable *drawable;
|
|
|
|
GimpPixelRgn pixel_rgn;
|
2002-12-13 22:57:16 +08:00
|
|
|
guchar *pixels;
|
|
|
|
guchar *pixel;
|
1998-11-09 10:05:24 +08:00
|
|
|
} channel_data;
|
|
|
|
|
2007-04-25 02:36:35 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2007-04-25 23:14:52 +08:00
|
|
|
gint o_pages;
|
2007-04-25 02:36:35 +08:00
|
|
|
gint n_pages;
|
|
|
|
gint *pages;
|
|
|
|
} TiffSelectedPages;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Declare some local functions.
|
|
|
|
*/
|
2003-12-03 06:32:42 +08:00
|
|
|
static void query (void);
|
|
|
|
static void run (const gchar *name,
|
2004-02-08 08:40:46 +08:00
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2007-04-25 22:49:05 +08:00
|
|
|
static gboolean load_dialog (TIFF *tif,
|
2007-04-25 21:56:10 +08:00
|
|
|
TiffSelectedPages *pages);
|
|
|
|
|
|
|
|
static gint32 load_image (const gchar *filename,
|
2007-04-25 22:49:05 +08:00
|
|
|
TIFF *tif,
|
2007-04-25 02:36:35 +08:00
|
|
|
TiffSelectedPages *pages);
|
2007-02-14 16:10:10 +08:00
|
|
|
|
|
|
|
static void load_rgba (TIFF *tif,
|
|
|
|
channel_data *channel);
|
|
|
|
static void load_lines (TIFF *tif,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gboolean alpha,
|
|
|
|
gboolean is_bw,
|
|
|
|
gint extra);
|
|
|
|
static void load_tiles (TIFF *tif,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gboolean alpha,
|
|
|
|
gboolean is_bw,
|
|
|
|
gint extra);
|
|
|
|
static void load_paths (TIFF *tif,
|
|
|
|
gint image);
|
|
|
|
|
|
|
|
static void read_separate (const guchar *source,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint sample);
|
|
|
|
static void read_16bit (const guchar *source,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align);
|
|
|
|
static void read_8bit (const guchar *source,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align);
|
|
|
|
static void read_bw (const guchar *source,
|
|
|
|
channel_data *channel,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gint align);
|
|
|
|
static void read_default (const guchar *source,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gint startcol,
|
|
|
|
gint startrow,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align);
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2007-07-30 01:10:24 +08:00
|
|
|
static void fill_bit2byte (void);
|
|
|
|
|
|
|
|
static void tiff_warning (const gchar *module,
|
|
|
|
const gchar *fmt,
|
|
|
|
va_list ap);
|
|
|
|
static void tiff_error (const gchar *module,
|
|
|
|
const gchar *fmt,
|
|
|
|
va_list ap);
|
|
|
|
|
2007-04-25 02:36:35 +08:00
|
|
|
|
2006-05-16 20:26:20 +08:00
|
|
|
const GimpPlugInInfo PLUG_IN_INFO =
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-01-26 01:46:56 +08:00
|
|
|
NULL, /* init_proc */
|
|
|
|
NULL, /* quit_proc */
|
|
|
|
query, /* query_proc */
|
|
|
|
run, /* run_proc */
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static TiffSaveVals tsvals =
|
|
|
|
{
|
2007-02-14 16:10:10 +08:00
|
|
|
COMPRESSION_NONE, /* compression */
|
|
|
|
TRUE, /* alpha handling */
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
|
2007-04-25 21:56:10 +08:00
|
|
|
static GimpRunMode run_mode = GIMP_RUN_INTERACTIVE;
|
|
|
|
static GimpPageSelectorTarget target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-01-02 03:13:38 +08:00
|
|
|
static guchar bit2byte[256 * 8];
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
MAIN ()
|
|
|
|
|
|
|
|
static void
|
2000-01-26 01:46:56 +08:00
|
|
|
query (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2006-05-16 20:26:20 +08:00
|
|
|
static const GimpParamDef load_args[] =
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-08-16 06:42:34 +08: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-25 06:05:25 +08:00
|
|
|
};
|
2006-05-16 20:26:20 +08:00
|
|
|
static const GimpParamDef load_return_vals[] =
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
{ GIMP_PDB_IMAGE, "image", "Output image" }
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
2005-08-16 06:42:34 +08:00
|
|
|
gimp_install_procedure (LOAD_PROC,
|
2000-01-31 10:32:30 +08:00
|
|
|
"loads files of the tiff file format",
|
1997-11-25 06:05:25 +08:00
|
|
|
"FIXME: write help for tiff_load",
|
1998-05-18 08:54:11 +08:00
|
|
|
"Spencer Kimball, Peter Mattis & Nick Lamb",
|
1998-05-31 14:49:20 +08:00
|
|
|
"Nick Lamb <njl195@zepler.org.uk>",
|
2003-12-03 06:32:42 +08:00
|
|
|
"1995-1996,1998-2003",
|
2004-11-01 22:29:29 +08:00
|
|
|
N_("TIFF image"),
|
2004-02-08 08:40:46 +08:00
|
|
|
NULL,
|
2000-08-22 09:26:57 +08:00
|
|
|
GIMP_PLUGIN,
|
2001-12-06 10:28:58 +08:00
|
|
|
G_N_ELEMENTS (load_args),
|
|
|
|
G_N_ELEMENTS (load_return_vals),
|
1997-11-25 06:05:25 +08:00
|
|
|
load_args, load_return_vals);
|
|
|
|
|
2005-08-16 06:42:34 +08:00
|
|
|
gimp_register_file_handler_mime (LOAD_PROC, "image/tiff");
|
|
|
|
gimp_register_magic_load_handler (LOAD_PROC,
|
2004-05-14 08:01:11 +08:00
|
|
|
"tif,tiff",
|
|
|
|
"",
|
|
|
|
"0,string,II*\\0,0,string,MM\\0*");
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-07-02 08:15:09 +08:00
|
|
|
run (const gchar *name,
|
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2003-11-06 23:27:05 +08:00
|
|
|
static GimpParam values[2];
|
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
|
|
|
gint32 image;
|
2007-04-25 02:36:35 +08:00
|
|
|
TiffSelectedPages pages;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
run_mode = param[0].data.d_int32;
|
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
INIT_I18N ();
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
*nreturn_vals = 1;
|
2000-01-26 01:46:56 +08:00
|
|
|
*return_vals = values;
|
2002-01-08 17:20:02 +08:00
|
|
|
|
2000-08-22 09:26:57 +08:00
|
|
|
values[0].type = GIMP_PDB_STATUS;
|
|
|
|
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-04-25 02:36:35 +08:00
|
|
|
TIFFSetWarningHandler (tiff_warning);
|
|
|
|
TIFFSetErrorHandler (tiff_error);
|
|
|
|
|
2005-08-16 06:42:34 +08:00
|
|
|
if (strcmp (name, LOAD_PROC) == 0)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-07-29 19:26:36 +08:00
|
|
|
const gchar *filename = param[1].data.d_string;
|
2007-11-12 18:16:55 +08:00
|
|
|
TIFF *tif = NULL;
|
2007-07-29 19:26:36 +08:00
|
|
|
gint fd;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-07-29 19:26:36 +08:00
|
|
|
fd = g_open (filename, O_RDONLY | _O_BINARY, 0);
|
2007-04-25 02:36:35 +08:00
|
|
|
|
2007-07-29 19:26:36 +08:00
|
|
|
if (fd == -1)
|
2007-04-25 22:49:05 +08:00
|
|
|
{
|
|
|
|
g_message (_("Could not open '%s' for reading: %s"),
|
2007-07-29 19:26:36 +08:00
|
|
|
gimp_filename_to_utf8 (filename), g_strerror (errno));
|
2007-04-25 22:49:05 +08:00
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-07-29 19:26:36 +08:00
|
|
|
tif = TIFFFdOpen (fd, filename, "r");
|
2007-11-12 18:16:55 +08:00
|
|
|
}
|
2007-07-29 19:26:36 +08:00
|
|
|
|
2007-11-12 18:16:55 +08:00
|
|
|
if (tif)
|
|
|
|
{
|
2007-07-29 19:26:36 +08:00
|
|
|
gimp_get_data (LOAD_PROC, &target);
|
|
|
|
|
2007-04-25 23:14:52 +08:00
|
|
|
pages.n_pages = pages.o_pages = TIFFNumberOfDirectories (tif);
|
2007-04-25 02:36:35 +08:00
|
|
|
|
2007-04-25 22:49:05 +08:00
|
|
|
if (pages.n_pages == 0)
|
2007-04-25 02:36:35 +08:00
|
|
|
{
|
2007-04-25 22:49:05 +08:00
|
|
|
g_message (_("TIFF '%s' does not contain any directories"),
|
2007-07-29 19:26:36 +08:00
|
|
|
gimp_filename_to_utf8 (filename));
|
2007-04-25 22:49:05 +08:00
|
|
|
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
2007-04-25 02:36:35 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-04-25 22:49:05 +08:00
|
|
|
gboolean run_it = FALSE;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
if (run_mode != GIMP_RUN_INTERACTIVE)
|
|
|
|
{
|
|
|
|
pages.pages = g_new (gint, pages.n_pages);
|
|
|
|
|
|
|
|
for (i = 0; i < pages.n_pages; i++)
|
|
|
|
pages.pages[i] = i;
|
|
|
|
|
|
|
|
run_it = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pages.n_pages == 1)
|
|
|
|
{
|
2007-04-25 22:59:23 +08:00
|
|
|
target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
|
2007-04-25 22:49:05 +08:00
|
|
|
pages.pages = g_new0 (gint, pages.n_pages);
|
|
|
|
|
|
|
|
run_it = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((! run_it) && (run_mode == GIMP_RUN_INTERACTIVE))
|
|
|
|
run_it = load_dialog (tif, &pages);
|
|
|
|
|
|
|
|
if (run_it)
|
|
|
|
{
|
|
|
|
gimp_set_data (LOAD_PROC, &target, sizeof (target));
|
|
|
|
|
|
|
|
image = load_image (param[1].data.d_string, tif, &pages);
|
|
|
|
|
|
|
|
g_free (pages.pages);
|
|
|
|
|
|
|
|
if (image != -1)
|
|
|
|
{
|
|
|
|
*nreturn_vals = 2;
|
|
|
|
values[1].type = GIMP_PDB_IMAGE;
|
|
|
|
values[1].data.d_image = image;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2007-11-12 18:16:55 +08:00
|
|
|
{
|
|
|
|
status = GIMP_PDB_CANCEL;
|
|
|
|
}
|
2007-04-25 02:36:35 +08:00
|
|
|
}
|
2007-07-29 19:26:36 +08:00
|
|
|
|
2007-04-25 22:49:05 +08:00
|
|
|
TIFFClose (tif);
|
2007-07-29 19:26:36 +08:00
|
|
|
close (fd);
|
2004-02-08 08:40:46 +08:00
|
|
|
}
|
2007-11-12 18:16:55 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
close (fd);
|
|
|
|
status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2000-01-26 01:46:56 +08:00
|
|
|
else
|
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
2000-01-26 01:46:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
values[0].data.d_status = status;
|
1997-11-25 06:05:25 +08: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-15 06:44:06 +08:00
|
|
|
static void
|
2007-02-14 16:10:10 +08: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-15 06:44:06 +08:00
|
|
|
{
|
2004-02-01 06:01:34 +08:00
|
|
|
va_list ap_test;
|
|
|
|
|
|
|
|
/* Workaround for: http://bugzilla.gnome.org/show_bug.cgi?id=131975 */
|
|
|
|
/* Ignore the warnings about unregistered private tags (>= 32768) */
|
2006-11-15 08:07:44 +08:00
|
|
|
if (! strcmp (fmt, "%s: unknown field with tag %d (0x%x) encountered"))
|
|
|
|
{
|
|
|
|
G_VA_COPY (ap_test, ap);
|
|
|
|
if (va_arg (ap_test, char *)); /* ignore first argument */
|
|
|
|
if (va_arg (ap_test, int) >= 32768)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* for older versions of libtiff? */
|
|
|
|
else if (! strcmp (fmt, "unknown field with tag %d (0x%x) ignored"))
|
2004-02-01 06:01:34 +08:00
|
|
|
{
|
2004-02-01 08:45:49 +08:00
|
|
|
G_VA_COPY (ap_test, ap);
|
2004-02-01 06:01:34 +08:00
|
|
|
if (va_arg (ap_test, int) >= 32768)
|
2004-02-08 08:40:46 +08:00
|
|
|
return;
|
2004-02-01 06:01:34 +08:00
|
|
|
}
|
2006-11-27 18:41:42 +08: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-15 06:44:06 +08:00
|
|
|
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
|
|
|
|
}
|
2003-07-15 20:35:39 +08: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-15 06:44:06 +08:00
|
|
|
static void
|
2003-07-15 20:35:39 +08: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-15 06:44:06 +08:00
|
|
|
{
|
2004-02-01 06:01:34 +08: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;
|
2007-11-12 18:16:55 +08: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-15 06:44:06 +08:00
|
|
|
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2007-05-18 03:51:25 +08:00
|
|
|
/* returns a pointer into the TIFF */
|
|
|
|
static const gchar *
|
|
|
|
tiff_get_page_name (TIFF *tif)
|
|
|
|
{
|
|
|
|
static gchar *name;
|
|
|
|
|
|
|
|
if (TIFFGetField (tif, TIFFTAG_PAGENAME, &name) &&
|
|
|
|
g_utf8_validate (name, -1, NULL))
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-25 02:36:35 +08:00
|
|
|
static gboolean
|
2007-04-25 22:49:05 +08:00
|
|
|
load_dialog (TIFF *tif,
|
2007-04-25 21:56:10 +08:00
|
|
|
TiffSelectedPages *pages)
|
2007-04-25 02:36:35 +08:00
|
|
|
{
|
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkWidget *selector;
|
|
|
|
gint i;
|
|
|
|
gboolean run;
|
|
|
|
|
|
|
|
gimp_ui_init (PLUG_IN_BINARY, FALSE);
|
|
|
|
|
|
|
|
dialog = gimp_dialog_new (_("Import from TIFF"), PLUG_IN_BINARY,
|
|
|
|
NULL, 0,
|
|
|
|
gimp_standard_help_func, LOAD_PROC,
|
|
|
|
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
|
|
_("_Import"), GTK_RESPONSE_OK,
|
|
|
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
|
|
|
|
2007-05-15 15:12:15 +08:00
|
|
|
gimp_window_set_transient (GTK_WINDOW (dialog));
|
|
|
|
|
2007-04-25 02:36:35 +08:00
|
|
|
vbox = gtk_vbox_new (FALSE, 12);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
|
|
|
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
|
|
|
|
gtk_widget_show (vbox);
|
|
|
|
|
|
|
|
/* Page Selector */
|
|
|
|
selector = gimp_page_selector_new ();
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), selector, TRUE, TRUE, 0);
|
|
|
|
|
|
|
|
gimp_page_selector_set_n_pages (GIMP_PAGE_SELECTOR (selector), pages->n_pages);
|
|
|
|
gimp_page_selector_set_target (GIMP_PAGE_SELECTOR (selector), target);
|
|
|
|
|
|
|
|
for (i = 0; i < pages->n_pages; i++)
|
|
|
|
{
|
2007-05-18 03:51:25 +08:00
|
|
|
const gchar *name = tiff_get_page_name (tif);
|
2007-04-25 02:36:35 +08:00
|
|
|
|
|
|
|
if (name)
|
2007-05-18 03:51:25 +08:00
|
|
|
gimp_page_selector_set_page_label (GIMP_PAGE_SELECTOR (selector),
|
|
|
|
i, name);
|
2007-04-25 02:36:35 +08:00
|
|
|
|
|
|
|
TIFFReadDirectory (tif);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_signal_connect_swapped (selector, "activate",
|
|
|
|
G_CALLBACK (gtk_window_activate_default),
|
|
|
|
dialog);
|
|
|
|
|
|
|
|
gtk_widget_show (selector);
|
|
|
|
|
|
|
|
/* Setup done; display the dialog */
|
|
|
|
gtk_widget_show (dialog);
|
|
|
|
|
|
|
|
/* run the dialog */
|
|
|
|
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
|
|
|
|
|
|
|
if (run)
|
|
|
|
target = gimp_page_selector_get_target (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
|
|
|
|
pages->pages =
|
|
|
|
gimp_page_selector_get_selected_pages (GIMP_PAGE_SELECTOR (selector),
|
|
|
|
&pages->n_pages);
|
|
|
|
|
|
|
|
/* select all if none selected */
|
|
|
|
if (pages->n_pages == 0)
|
|
|
|
{
|
|
|
|
gimp_page_selector_select_all (GIMP_PAGE_SELECTOR (selector));
|
|
|
|
|
|
|
|
pages->pages =
|
|
|
|
gimp_page_selector_get_selected_pages (GIMP_PAGE_SELECTOR (selector),
|
|
|
|
&pages->n_pages);
|
|
|
|
}
|
|
|
|
|
|
|
|
return run;
|
|
|
|
}
|
|
|
|
|
2000-01-26 01:46:56 +08:00
|
|
|
static gint32
|
2007-04-25 22:49:05 +08:00
|
|
|
load_image (const gchar *filename,
|
|
|
|
TIFF *tif,
|
|
|
|
TiffSelectedPages *pages)
|
1999-10-04 02:54:54 +08:00
|
|
|
{
|
2003-12-03 06:32:42 +08:00
|
|
|
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;
|
2007-06-13 19:43:08 +08:00
|
|
|
gint first_image_type = GIMP_RGB;
|
2004-01-10 03:48:07 +08: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-03 06:32:42 +08:00
|
|
|
gushort extra, *extra_types;
|
|
|
|
channel_data *channel = NULL;
|
|
|
|
|
|
|
|
gushort *redmap, *greenmap, *bluemap;
|
|
|
|
GimpRGB color;
|
|
|
|
guchar cmap[768];
|
|
|
|
|
2005-01-02 03:13:38 +08:00
|
|
|
gboolean is_bw;
|
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
gint i, j;
|
|
|
|
gint ilayer;
|
|
|
|
gboolean worst_case = FALSE;
|
|
|
|
|
|
|
|
TiffSaveVals save_vals;
|
2000-05-27 06:28:40 +08:00
|
|
|
GimpParasite *parasite;
|
2003-12-03 06:32:42 +08:00
|
|
|
guint16 tmp;
|
|
|
|
|
2007-05-18 03:51:25 +08:00
|
|
|
const gchar *name;
|
2005-07-18 04:35:32 +08:00
|
|
|
|
2007-04-25 02:36:35 +08:00
|
|
|
GList *images_list = NULL, *images_list_temp;
|
|
|
|
gint li;
|
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
gboolean flip_horizontal = FALSE;
|
|
|
|
gboolean flip_vertical = FALSE;
|
|
|
|
|
2000-06-18 09:07:13 +08:00
|
|
|
#ifdef TIFFTAG_ICCPROFILE
|
2003-12-03 06:32:42 +08:00
|
|
|
uint32 profile_size;
|
|
|
|
guchar *icc_profile;
|
2000-06-18 09:07:13 +08: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-15 06:44:06 +08:00
|
|
|
|
2001-01-25 09:20:05 +08:00
|
|
|
gimp_rgb_set (&color, 0.0, 0.0, 0.0);
|
|
|
|
|
2005-09-30 16:16:10 +08:00
|
|
|
gimp_progress_init_printf (_("Opening '%s'"),
|
2005-09-30 02:34:08 +08:00
|
|
|
gimp_filename_to_utf8 (filename));
|
2003-12-03 06:32:42 +08:00
|
|
|
/* We will loop through the all pages in case of multipage TIFF
|
|
|
|
and load every page as a separate layer. */
|
2007-04-25 02:36:35 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
ilayer = 0;
|
2007-04-25 02:36:35 +08:00
|
|
|
|
|
|
|
for (li = 0; li < pages->n_pages; li++)
|
2003-12-03 06:32:42 +08:00
|
|
|
{
|
2007-04-25 02:36:35 +08:00
|
|
|
TIFFSetDirectory (tif, pages->pages[li]);
|
|
|
|
ilayer = pages->pages[li];
|
|
|
|
|
2007-04-25 22:10:20 +08:00
|
|
|
gimp_progress_update (0.0);
|
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, &bps);
|
1998-05-18 08:54:11 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (bps > 8 && bps != 16)
|
|
|
|
worst_case = TRUE; /* Wrong sample width => RGBA */
|
1998-05-18 08:54:11 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
|
|
|
|
extra = 0;
|
1998-05-18 08:54:11 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols))
|
|
|
|
{
|
2004-01-19 11:06:04 +08:00
|
|
|
g_message ("Could not get image width from '%s'",
|
|
|
|
gimp_filename_to_utf8 (filename));
|
2007-04-01 05:20:51 +08:00
|
|
|
return -1;
|
2003-12-03 06:32:42 +08:00
|
|
|
}
|
1998-05-18 08:54:11 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows))
|
|
|
|
{
|
2004-01-19 11:06:04 +08:00
|
|
|
g_message ("Could not get image length from '%s'",
|
|
|
|
gimp_filename_to_utf8 (filename));
|
2007-04-01 05:20:51 +08:00
|
|
|
return -1;
|
2003-12-03 06:32:42 +08:00
|
|
|
}
|
1998-05-18 08:54:11 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet))
|
|
|
|
{
|
2004-01-28 03:19:54 +08: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-03 06:32:42 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
/* test if the extrasample represents an associated alpha channel... */
|
|
|
|
if (extra > 0 && (extra_types[0] == EXTRASAMPLE_ASSOCALPHA))
|
|
|
|
{
|
|
|
|
alpha = TRUE;
|
2004-01-17 05:28:31 +08: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 11:06:04 +08:00
|
|
|
gimp_filename_to_utf8 (filename));
|
2004-01-17 05:28:31 +08:00
|
|
|
alpha = TRUE;
|
|
|
|
tsvals.save_transp_pixels = TRUE;
|
2003-12-03 06:32:42 +08:00
|
|
|
--extra;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
alpha = FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-12-03 06:32:42 +08: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-25 06:05:25 +08:00
|
|
|
|
2005-01-02 03:13:38 +08:00
|
|
|
is_bw = FALSE;
|
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
2005-01-02 03:13:38 +08:00
|
|
|
if (bps == 1 && !alpha && spp == 1)
|
|
|
|
{
|
|
|
|
image_type = GIMP_INDEXED;
|
2005-01-02 03:28:59 +08:00
|
|
|
layer_type = GIMP_INDEXED_IMAGE;
|
2005-01-02 03:13:38 +08:00
|
|
|
|
|
|
|
is_bw = TRUE;
|
|
|
|
fill_bit2byte ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
image_type = GIMP_GRAY;
|
|
|
|
layer_type = (alpha) ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
|
|
|
|
}
|
2003-12-03 06:32:42 +08:00
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
image_type = GIMP_RGB;
|
|
|
|
layer_type = (alpha) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
case PHOTOMETRIC_PALETTE:
|
|
|
|
image_type = GIMP_INDEXED;
|
|
|
|
layer_type = (alpha) ? GIMP_INDEXEDA_IMAGE : GIMP_INDEXED_IMAGE;
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
default:
|
|
|
|
worst_case = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (worst_case)
|
|
|
|
{
|
|
|
|
image_type = GIMP_RGB;
|
|
|
|
layer_type = GIMP_RGBA_IMAGE;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2007-06-13 17:57:43 +08:00
|
|
|
if (target == GIMP_PAGE_SELECTOR_TARGET_LAYERS)
|
|
|
|
{
|
|
|
|
if (li == 0)
|
2007-06-13 19:43:08 +08:00
|
|
|
first_image_type = image_type;
|
|
|
|
else if (image_type != first_image_type)
|
2007-06-13 17:57:43 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2007-04-25 23:14:52 +08:00
|
|
|
if ((target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) || (! image))
|
2003-12-03 06:32:42 +08:00
|
|
|
{
|
|
|
|
if ((image = gimp_image_new (cols, rows, image_type)) == -1)
|
|
|
|
{
|
|
|
|
g_message ("Could not create a new image");
|
2007-04-01 05:20:51 +08:00
|
|
|
return -1;
|
2003-12-03 06:32:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gimp_image_undo_disable (image);
|
2007-04-25 02:36:35 +08:00
|
|
|
|
2007-04-25 23:14:52 +08:00
|
|
|
if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
|
2007-04-25 02:36:35 +08:00
|
|
|
{
|
|
|
|
gchar *fname;
|
|
|
|
fname = g_strdup_printf ("%s-%d", filename, ilayer);
|
|
|
|
gimp_image_set_filename (image, fname);
|
|
|
|
g_free (fname);
|
|
|
|
|
2007-06-14 01:31:02 +08:00
|
|
|
images_list = g_list_prepend (images_list, GINT_TO_POINTER (image));
|
2007-04-25 02:36:35 +08:00
|
|
|
}
|
2007-04-25 23:14:52 +08:00
|
|
|
else if (pages->o_pages == pages->n_pages)
|
2007-04-25 02:36:35 +08:00
|
|
|
{
|
|
|
|
gimp_image_set_filename (image, filename);
|
|
|
|
}
|
2003-12-03 06:32:42 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
/* attach a parasite containing an ICC profile - if found in the TIFF */
|
2000-06-18 09:07:13 +08:00
|
|
|
|
|
|
|
#ifdef TIFFTAG_ICCPROFILE
|
2003-12-03 06:32:42 +08: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))
|
|
|
|
{
|
2007-08-12 02:27:01 +08:00
|
|
|
parasite = gimp_parasite_new ("icc-profile",
|
|
|
|
GIMP_PARASITE_PERSISTENT |
|
|
|
|
GIMP_PARASITE_UNDOABLE,
|
2003-12-03 06:32:42 +08:00
|
|
|
profile_size, icc_profile);
|
|
|
|
gimp_image_parasite_attach (image, parasite);
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
}
|
2000-06-18 09:07:13 +08:00
|
|
|
#endif
|
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
/* attach a parasite containing the compression */
|
|
|
|
if (!TIFFGetField (tif, TIFFTAG_COMPRESSION, &tmp))
|
2006-09-17 23:41:10 +08:00
|
|
|
{
|
|
|
|
save_vals.compression = COMPRESSION_NONE;
|
|
|
|
}
|
2003-12-03 06:32:42 +08:00
|
|
|
else
|
2005-04-25 15:42:52 +08:00
|
|
|
{
|
|
|
|
switch (tmp)
|
|
|
|
{
|
|
|
|
case COMPRESSION_NONE:
|
|
|
|
case COMPRESSION_LZW:
|
|
|
|
case COMPRESSION_PACKBITS:
|
|
|
|
case COMPRESSION_DEFLATE:
|
|
|
|
case COMPRESSION_JPEG:
|
2007-02-14 16:10:10 +08:00
|
|
|
case COMPRESSION_CCITTFAX3:
|
|
|
|
case COMPRESSION_CCITTFAX4:
|
2005-04-25 15:42:52 +08:00
|
|
|
save_vals.compression = tmp;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
save_vals.compression = COMPRESSION_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-10-05 18:05:29 +08:00
|
|
|
|
2003-12-03 06:32:42 +08: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-12 06:50:03 +08:00
|
|
|
|
2003-12-03 06:32:42 +08: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 20:35:39 +08:00
|
|
|
{
|
2003-12-03 06:32:42 +08:00
|
|
|
const gchar *img_desc;
|
1998-10-12 06:50:03 +08:00
|
|
|
|
2003-12-03 06:32:42 +08: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 18:05:29 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
/* any resolution info in the file? */
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2003-12-03 06:32:42 +08:00
|
|
|
gfloat xres = 72.0, yres = 72.0;
|
|
|
|
gushort read_unit;
|
|
|
|
GimpUnit unit = GIMP_UNIT_PIXEL; /* invalid unit */
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (TIFFGetField (tif, TIFFTAG_XRESOLUTION, &xres))
|
|
|
|
{
|
|
|
|
if (TIFFGetField (tif, TIFFTAG_YRESOLUTION, &yres))
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2003-12-03 06:32:42 +08:00
|
|
|
|
|
|
|
if (TIFFGetFieldDefaulted (tif, TIFFTAG_RESOLUTIONUNIT,
|
|
|
|
&read_unit))
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2003-12-03 06:32:42 +08:00
|
|
|
switch (read_unit)
|
|
|
|
{
|
|
|
|
case RESUNIT_NONE:
|
|
|
|
/* ImageMagick writes files with this silly resunit */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESUNIT_INCH:
|
|
|
|
unit = GIMP_UNIT_INCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESUNIT_CENTIMETER:
|
|
|
|
xres *= 2.54;
|
|
|
|
yres *= 2.54;
|
|
|
|
unit = GIMP_UNIT_MM; /* this is our default metric unit */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_message ("File error: unknown resolution "
|
|
|
|
"unit type %d, assuming dpi", read_unit);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* no res unit tag */
|
|
|
|
/* old AppleScan software produces these */
|
|
|
|
g_message ("Warning: resolution specified without "
|
|
|
|
"any units tag, assuming dpi");
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2003-12-03 06:32:42 +08:00
|
|
|
{ /* xres but no yres */
|
|
|
|
g_message ("Warning: no y resolution info, assuming same as x");
|
|
|
|
yres = xres;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
1998-10-05 18:05:29 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
/* now set the new image's resolution info */
|
2000-01-08 18:55:05 +08:00
|
|
|
|
2003-12-03 06:32:42 +08: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 20:35:39 +08:00
|
|
|
}
|
2003-12-03 06:32:42 +08: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-10 03:48:07 +08: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 20:35:39 +08:00
|
|
|
}
|
1998-10-05 18:05:29 +08:00
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
/* Install colormap for INDEXED images only */
|
|
|
|
if (image_type == GIMP_INDEXED)
|
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
if (is_bw)
|
2003-12-03 06:32:42 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08: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-03 06:32:42 +08:00
|
|
|
}
|
2005-01-02 03:13:38 +08:00
|
|
|
else
|
2003-12-03 06:32:42 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
if (!TIFFGetField (tif, TIFFTAG_COLORMAP,
|
|
|
|
&redmap, &greenmap, &bluemap))
|
|
|
|
{
|
|
|
|
g_message ("Could not get colormaps from '%s'",
|
|
|
|
gimp_filename_to_utf8 (filename));
|
2007-04-01 05:20:51 +08:00
|
|
|
return -1;
|
2005-01-02 03:13:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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-03 06:32:42 +08:00
|
|
|
}
|
2005-01-02 03:13:38 +08:00
|
|
|
|
2004-11-02 20:00:25 +08:00
|
|
|
gimp_image_set_colormap (image, cmap, (1 << bps));
|
2003-12-03 06:32:42 +08:00
|
|
|
}
|
1998-10-05 18:05:29 +08:00
|
|
|
|
2006-11-15 05:29:51 +08:00
|
|
|
load_paths (tif, image);
|
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
/* Allocate channel_data for all channels, even the background layer */
|
|
|
|
channel = g_new0 (channel_data, extra + 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-02-08 08:40:46 +08:00
|
|
|
/* try and use layer name from tiff file */
|
2007-05-18 03:51:25 +08:00
|
|
|
name = tiff_get_page_name (tif);
|
2005-01-02 03:13:38 +08:00
|
|
|
|
2005-07-18 04:35:32 +08:00
|
|
|
if (name)
|
2004-02-08 08:40:46 +08:00
|
|
|
{
|
|
|
|
layer = gimp_layer_new (image, name,
|
2005-01-02 03:13:38 +08:00
|
|
|
cols, rows,
|
|
|
|
layer_type, 100, GIMP_NORMAL_MODE);
|
2004-02-08 08:40:46 +08:00
|
|
|
}
|
2003-12-03 06:32:42 +08:00
|
|
|
else
|
2004-02-08 08:40:46 +08:00
|
|
|
{
|
2007-05-18 03:51:25 +08:00
|
|
|
gchar *name;
|
|
|
|
|
2004-02-08 08:40:46 +08:00
|
|
|
if (ilayer == 0)
|
|
|
|
name = g_strdup (_("Background"));
|
|
|
|
else
|
|
|
|
name = g_strdup_printf (_("Page %d"), ilayer);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-02-08 08:40:46 +08:00
|
|
|
layer = gimp_layer_new (image, name,
|
2005-01-02 03:13:38 +08:00
|
|
|
cols, rows,
|
|
|
|
layer_type, 100, GIMP_NORMAL_MODE);
|
2004-02-08 08:40:46 +08:00
|
|
|
g_free (name);
|
|
|
|
}
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
channel[0].ID = layer;
|
|
|
|
channel[0].drawable = gimp_drawable_get (layer);
|
|
|
|
|
|
|
|
if (extra > 0 && !worst_case)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2003-12-03 06:32:42 +08: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 20:35:39 +08:00
|
|
|
}
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-12-03 06:32:42 +08: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-11 05:44:54 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (worst_case)
|
|
|
|
{
|
|
|
|
load_rgba (tif, channel);
|
|
|
|
}
|
2004-11-02 21:44:13 +08:00
|
|
|
else if (TIFFIsTiled (tif))
|
2003-12-03 06:32:42 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
load_tiles (tif, channel, bps, photomet, alpha, is_bw, extra);
|
2003-12-03 06:32:42 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* Load scanlines in tile_height chunks */
|
2005-01-02 03:13:38 +08:00
|
|
|
load_lines (tif, channel, bps, photomet, alpha, is_bw, extra);
|
2003-12-03 06:32:42 +08:00
|
|
|
}
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
if (TIFFGetField (tif, TIFFTAG_ORIENTATION, &orientation))
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2003-12-03 06:32:42 +08: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 21:44:13 +08:00
|
|
|
gimp_drawable_transform_flip_simple (layer,
|
|
|
|
GIMP_ORIENTATION_HORIZONTAL,
|
|
|
|
TRUE, 0.0, TRUE);
|
2003-12-03 06:32:42 +08:00
|
|
|
|
|
|
|
if (flip_vertical)
|
2004-11-02 21:44:13 +08:00
|
|
|
gimp_drawable_transform_flip_simple (layer,
|
|
|
|
GIMP_ORIENTATION_VERTICAL,
|
|
|
|
TRUE, 0.0, TRUE);
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
2003-01-10 21:59:41 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
gimp_drawable_flush (channel[0].drawable);
|
|
|
|
gimp_drawable_detach (channel[0].drawable);
|
2003-01-10 21:59:41 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
for (i = 1; !worst_case && i < extra; ++i)
|
|
|
|
{
|
|
|
|
gimp_drawable_flush (channel[i].drawable);
|
|
|
|
gimp_drawable_detach (channel[i].drawable);
|
|
|
|
}
|
2003-01-11 04:14:30 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
g_free (channel);
|
|
|
|
channel = NULL;
|
2003-01-10 21:59:41 +08:00
|
|
|
|
2007-04-26 20:20:56 +08:00
|
|
|
|
|
|
|
/* TODO: in GIMP 2.6, use a dialog to selectively enable the
|
|
|
|
* following code, as the save plug-in will then save layer offests
|
|
|
|
* as well.
|
|
|
|
*/
|
|
|
|
|
2004-01-10 03:48:07 +08: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-03 06:32:42 +08:00
|
|
|
if (ilayer > 0 && !alpha)
|
|
|
|
gimp_layer_add_alpha (layer);
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2003-12-03 06:32:42 +08:00
|
|
|
gimp_image_add_layer (image, layer, -1);
|
2007-04-25 02:36:35 +08:00
|
|
|
|
2007-04-25 23:14:52 +08:00
|
|
|
if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES)
|
2007-04-25 02:36:35 +08:00
|
|
|
{
|
|
|
|
gimp_image_undo_enable (image);
|
|
|
|
gimp_image_clean_all (image);
|
|
|
|
}
|
2007-04-25 22:10:20 +08:00
|
|
|
|
|
|
|
gimp_progress_update (1.0);
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
2003-12-03 06:32:42 +08:00
|
|
|
|
2007-04-25 23:14:52 +08:00
|
|
|
if (target != GIMP_PAGE_SELECTOR_TARGET_IMAGES)
|
2007-04-25 02:36:35 +08:00
|
|
|
{
|
|
|
|
/* resize image to bounding box of all layers */
|
|
|
|
gimp_image_resize (image,
|
2004-01-10 03:48:07 +08:00
|
|
|
max_col - min_col, max_row - min_row, -min_col, -min_row);
|
|
|
|
|
2007-04-25 02:36:35 +08:00
|
|
|
gimp_image_undo_enable (image);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
images_list_temp = images_list;
|
|
|
|
|
|
|
|
if (images_list)
|
|
|
|
{
|
|
|
|
image = GPOINTER_TO_INT (images_list->data);
|
|
|
|
images_list = images_list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (images_list)
|
|
|
|
{
|
|
|
|
gimp_display_new (GPOINTER_TO_INT (images_list->data));
|
|
|
|
images_list = images_list->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free (images_list_temp);
|
|
|
|
}
|
|
|
|
|
1998-11-09 10:05:24 +08:00
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-07-15 20:35:39 +08:00
|
|
|
load_rgba (TIFF *tif,
|
|
|
|
channel_data *channel)
|
1998-11-09 10:05:24 +08:00
|
|
|
{
|
2003-07-15 20:35:39 +08:00
|
|
|
uint32 imageWidth, imageLength;
|
|
|
|
uint32 row;
|
2003-01-06 04:38:21 +08:00
|
|
|
uint32 *buffer;
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &imageLength);
|
|
|
|
|
2006-09-17 23:41:10 +08:00
|
|
|
gimp_tile_cache_ntiles (1 + imageWidth / gimp_tile_width ());
|
|
|
|
|
1999-09-18 06:28:25 +08:00
|
|
|
gimp_pixel_rgn_init (&(channel[0].pixel_rgn), channel[0].drawable,
|
2003-07-15 20:35:39 +08:00
|
|
|
0, 0, imageWidth, imageLength, TRUE, FALSE);
|
|
|
|
|
2003-01-11 09:31:22 +08:00
|
|
|
buffer = g_new (uint32, imageWidth * imageLength);
|
2007-06-27 16:15:54 +08:00
|
|
|
channel[0].pixels = (guchar *) buffer;
|
2003-01-11 09:31:22 +08:00
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
if (!TIFFReadRGBAImage (tif, imageWidth, imageLength, buffer, 0))
|
2003-06-13 22:37:00 +08:00
|
|
|
g_message ("Unsupported layout, no RGBA loader");
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
for (row = 0; row < imageLength; ++row)
|
|
|
|
{
|
2004-07-14 18:57:13 +08: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
|
2007-09-28 18:10:28 +08:00
|
|
|
|
|
|
|
gimp_pixel_rgn_set_row (&(channel[0].pixel_rgn),
|
|
|
|
channel[0].pixels + row * imageWidth * 4,
|
|
|
|
0, imageLength -row -1, imageWidth);
|
2003-06-13 22:37:00 +08:00
|
|
|
|
2007-05-10 00:14:18 +08:00
|
|
|
if ((row % 32) == 0)
|
|
|
|
gimp_progress_update ((gdouble) row / (gdouble) imageLength);
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
1999-09-18 06:28:25 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-11-15 05:29:51 +08:00
|
|
|
static void
|
|
|
|
load_paths (TIFF *tif, gint image)
|
|
|
|
{
|
|
|
|
guint16 id;
|
2007-06-05 22:26:42 +08:00
|
|
|
gsize len, n_bytes, pos;
|
2006-11-15 05:29:51 +08:00
|
|
|
gchar *bytes, *name;
|
|
|
|
guint32 *val32;
|
|
|
|
guint16 *val16;
|
|
|
|
|
|
|
|
gint width, height;
|
2007-05-17 08:22:11 +08:00
|
|
|
gint path_index;
|
2006-11-15 05:29:51 +08:00
|
|
|
|
|
|
|
width = gimp_image_width (image);
|
|
|
|
height = gimp_image_height (image);
|
|
|
|
|
|
|
|
if (!TIFFGetField (tif, TIFFTAG_PHOTOSHOP, &n_bytes, &bytes))
|
|
|
|
return;
|
|
|
|
|
2007-05-17 08:22:11 +08:00
|
|
|
path_index = 0;
|
|
|
|
|
2006-11-15 05:29:51 +08:00
|
|
|
pos = 0;
|
|
|
|
|
|
|
|
while (pos < n_bytes)
|
|
|
|
{
|
|
|
|
if (n_bytes-pos < 7 ||
|
|
|
|
strncmp (bytes + pos, "8BIM", 4) != 0)
|
|
|
|
break;
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
val16 = (guint16 *) (bytes + pos);
|
|
|
|
id = GUINT16_FROM_BE (*val16);
|
|
|
|
pos += 2;
|
|
|
|
|
2006-11-15 07:21:53 +08:00
|
|
|
/* g_printerr ("id: %x\n", id); */
|
2006-11-15 05:29:51 +08:00
|
|
|
len = (guchar) bytes[pos];
|
|
|
|
|
|
|
|
if (n_bytes - pos < len + 1)
|
|
|
|
break; /* block not big enough */
|
|
|
|
|
2007-06-05 22:26:42 +08:00
|
|
|
/*
|
|
|
|
* do we have the UTF-marker? is it valid UTF-8?
|
|
|
|
* if so, we assume an utf-8 encoded name, otherwise we
|
|
|
|
* assume iso8859-1
|
|
|
|
*/
|
|
|
|
name = bytes + pos + 1;
|
|
|
|
if (len >= 3 &&
|
|
|
|
name[0] == '\xEF' && name[1] == '\xBB' && name[2] == '\xBF' &&
|
2007-06-05 22:33:44 +08:00
|
|
|
g_utf8_validate (name, len, NULL))
|
2007-06-05 22:26:42 +08:00
|
|
|
{
|
|
|
|
name = g_strndup (name + 3, len - 3);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
name = g_convert (name, len, "utf-8", "iso8859-1", NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
name = g_strdup ("(imported path)");
|
|
|
|
|
2006-11-15 05:29:51 +08:00
|
|
|
pos += len + 1;
|
|
|
|
|
|
|
|
if (pos % 2) /* padding */
|
|
|
|
pos++;
|
|
|
|
|
|
|
|
if (n_bytes - pos < 4)
|
|
|
|
break; /* block not big enough */
|
|
|
|
|
|
|
|
val32 = (guint32 *) (bytes + pos);
|
|
|
|
len = GUINT32_FROM_BE (*val32);
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
if (n_bytes - pos < len)
|
|
|
|
break; /* block not big enough */
|
|
|
|
|
|
|
|
if (id >= 2000 && id <= 2998)
|
|
|
|
{
|
|
|
|
/* path information */
|
|
|
|
guint16 type;
|
|
|
|
gint rec = pos;
|
|
|
|
gint32 vectors;
|
|
|
|
gdouble *points = NULL;
|
|
|
|
gint expected_points = 0;
|
|
|
|
gint pointcount = 0;
|
2006-11-24 07:03:55 +08:00
|
|
|
gboolean closed = FALSE;
|
2006-11-15 05:29:51 +08:00
|
|
|
|
|
|
|
vectors = gimp_vectors_new (image, name);
|
2007-05-17 08:22:11 +08:00
|
|
|
gimp_image_add_vectors (image, vectors, path_index);
|
|
|
|
path_index++;
|
2006-11-15 05:29:51 +08:00
|
|
|
|
|
|
|
while (rec < pos + len)
|
|
|
|
{
|
|
|
|
/* path records */
|
|
|
|
val16 = (guint16 *) (bytes + rec);
|
|
|
|
type = GUINT16_FROM_BE (*val16);
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 0: /* new closed subpath */
|
|
|
|
case 3: /* new open subpath */
|
|
|
|
val16 = (guint16 *) (bytes + rec + 2);
|
|
|
|
expected_points = GUINT16_FROM_BE (*val16);
|
|
|
|
pointcount = 0;
|
|
|
|
closed = (type == 0);
|
|
|
|
|
|
|
|
if (n_bytes - rec < (expected_points + 1) * 26)
|
|
|
|
{
|
|
|
|
g_printerr ("not enough point records\n");
|
|
|
|
rec = pos + len;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (points)
|
|
|
|
g_free (points);
|
|
|
|
points = g_new (gdouble, expected_points * 6);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* closed subpath bezier knot, linked */
|
|
|
|
case 2: /* closed subpath bezier knot, unlinked */
|
|
|
|
case 4: /* open subpath bezier knot, linked */
|
|
|
|
case 5: /* open subpath bezier knot, unlinked */
|
|
|
|
/* since we already know if the subpath is open
|
|
|
|
* or closed and since we don't differenciate between
|
|
|
|
* linked and unlinked, just treat all the same... */
|
|
|
|
|
|
|
|
if (pointcount < expected_points)
|
|
|
|
{
|
|
|
|
gint j;
|
|
|
|
gdouble f;
|
|
|
|
guint32 coord;
|
|
|
|
|
|
|
|
for (j = 0; j < 6; j++)
|
|
|
|
{
|
|
|
|
val32 = (guint32 *) (bytes + rec + 2 + j * 4);
|
|
|
|
coord = GUINT32_FROM_BE (*val32);
|
|
|
|
|
2007-05-17 07:56:51 +08:00
|
|
|
f = (double) ((gchar) ((coord >> 24) & 0xFF)) +
|
2006-11-15 05:29:51 +08:00
|
|
|
(double) (coord & 0x00FFFFFF) /
|
|
|
|
(double) 0xFFFFFF;
|
|
|
|
|
|
|
|
/* coords are stored with vertical component
|
|
|
|
* first, gimp expects the horizontal component
|
|
|
|
* first. Sigh. */
|
2006-11-15 07:21:53 +08:00
|
|
|
points[pointcount * 6 + (j ^ 1)] = f * (j % 2 ? width : height);
|
2006-11-15 05:29:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pointcount ++;
|
|
|
|
|
|
|
|
if (pointcount == expected_points)
|
|
|
|
{
|
|
|
|
gimp_vectors_stroke_new_from_points (vectors,
|
|
|
|
GIMP_VECTORS_STROKE_TYPE_BEZIER,
|
|
|
|
pointcount * 6,
|
|
|
|
points,
|
|
|
|
closed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_printerr ("Oops - unexpected point record\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6: /* path fill rule record */
|
|
|
|
case 7: /* clipboard record (?) */
|
|
|
|
case 8: /* initial fill rule record (?) */
|
|
|
|
/* we cannot use this information */
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rec += 26;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (points)
|
|
|
|
g_free (points);
|
|
|
|
}
|
|
|
|
|
|
|
|
pos += len;
|
|
|
|
|
|
|
|
if (pos % 2) /* padding */
|
|
|
|
pos++;
|
|
|
|
|
|
|
|
g_free (name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-09-18 06:28:25 +08:00
|
|
|
static void
|
2003-12-03 06:32:42 +08:00
|
|
|
load_tiles (TIFF *tif,
|
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gboolean alpha,
|
2005-01-02 03:13:38 +08:00
|
|
|
gboolean is_bw,
|
2003-12-03 06:32:42 +08:00
|
|
|
gint extra)
|
1999-09-18 06:28:25 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
uint16 planar = PLANARCONFIG_CONTIG;
|
2003-07-15 20:35:39 +08:00
|
|
|
uint32 imageWidth, imageLength;
|
|
|
|
uint32 tileWidth, tileLength;
|
|
|
|
uint32 x, y, rows, cols;
|
1999-09-18 06:28:25 +08:00
|
|
|
guchar *buffer;
|
2005-01-02 03:13:38 +08:00
|
|
|
gdouble progress = 0.0, one_row;
|
2003-07-15 20:35:39 +08:00
|
|
|
gint i;
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-07-15 20:35:39 +08: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 23:41:10 +08: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 20:35:39 +08:00
|
|
|
one_row = (gdouble) tileLength / (gdouble) imageLength;
|
|
|
|
buffer = g_malloc (TIFFTileSize (tif));
|
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2003-08-17 06:17:04 +08:00
|
|
|
channel[i].pixels = g_new (guchar,
|
2004-02-08 08:40:46 +08:00
|
|
|
tileWidth * tileLength *
|
|
|
|
channel[i].drawable->bpp);
|
1998-11-09 10:05:24 +08:00
|
|
|
}
|
2003-07-15 20:35:39 +08: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-02 03:13:38 +08:00
|
|
|
else if (is_bw)
|
|
|
|
{
|
|
|
|
read_bw (buffer, channel, y, x, rows, cols, tileWidth - cols);
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
read_default (buffer, channel, bps, photomet, y, x, rows, cols,
|
|
|
|
alpha, extra, tileWidth - cols);
|
|
|
|
}
|
|
|
|
}
|
2006-09-17 23:41:10 +08:00
|
|
|
|
2005-01-02 03:13:38 +08:00
|
|
|
progress += one_row;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
1999-09-18 06:28:25 +08:00
|
|
|
g_free(channel[i].pixels);
|
2003-07-15 20:35:39 +08:00
|
|
|
|
1999-09-18 06:28:25 +08:00
|
|
|
g_free(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-12-03 06:32:42 +08:00
|
|
|
load_lines (TIFF *tif,
|
|
|
|
channel_data *channel,
|
2004-02-08 08:40:46 +08:00
|
|
|
gushort bps,
|
2003-12-03 06:32:42 +08:00
|
|
|
gushort photomet,
|
2004-02-08 08:40:46 +08:00
|
|
|
gboolean alpha,
|
2005-01-02 03:13:38 +08:00
|
|
|
gboolean is_bw,
|
2003-12-03 06:32:42 +08:00
|
|
|
gint extra)
|
1999-09-18 06:28:25 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
uint16 planar = PLANARCONFIG_CONTIG;
|
2003-07-15 20:35:39 +08:00
|
|
|
uint32 imageLength, lineSize, cols, rows;
|
1999-09-18 06:28:25 +08:00
|
|
|
guchar *buffer;
|
2003-07-15 20:35:39 +08:00
|
|
|
gint i, y;
|
|
|
|
gint tile_height = gimp_tile_height ();
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &imageLength);
|
|
|
|
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols);
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2005-01-02 03:13:38 +08:00
|
|
|
lineSize = TIFFScanlineSize (tif);
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
channel[i].pixels = g_new (guchar,
|
|
|
|
tile_height * cols * channel[i].drawable->bpp);
|
1998-11-09 10:05:24 +08:00
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2006-09-17 23:41:10 +08:00
|
|
|
gimp_tile_cache_ntiles (1 + cols / gimp_tile_width ());
|
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
buffer = g_malloc (lineSize * tile_height);
|
|
|
|
|
|
|
|
if (planar == PLANARCONFIG_CONTIG)
|
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
for (y = 0; y < imageLength; y += tile_height )
|
2003-07-15 20:35:39 +08: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-02 03:13:38 +08:00
|
|
|
else if (is_bw)
|
|
|
|
{
|
|
|
|
read_bw (buffer, channel, y, 0, rows, cols, 0);
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
read_default (buffer, channel, bps, photomet, y, 0, rows, cols,
|
|
|
|
alpha, extra, 0);
|
|
|
|
}
|
|
|
|
}
|
1999-09-18 06:28:25 +08:00
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
|
|
|
{ /* PLANARCONFIG_SEPARATE -- Just say "No" */
|
|
|
|
uint16 s, samples;
|
|
|
|
|
|
|
|
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples);
|
|
|
|
|
|
|
|
for (s = 0; s < samples; ++s)
|
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
for (y = 0; y < imageLength; y += tile_height )
|
2003-07-15 20:35:39 +08: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-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
1999-09-18 06:28:25 +08:00
|
|
|
g_free(channel[i].pixels);
|
2003-07-15 20:35:39 +08:00
|
|
|
|
1999-09-18 06:28:25 +08:00
|
|
|
g_free(buffer);
|
|
|
|
}
|
1998-11-09 10:05:24 +08:00
|
|
|
|
1999-09-18 06:28:25 +08:00
|
|
|
static void
|
2005-05-09 18:41:39 +08:00
|
|
|
read_16bit (const guchar *source,
|
2004-02-08 08:40:46 +08:00
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startrow,
|
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
2000-10-26 07:49:30 +08:00
|
|
|
gint extra,
|
|
|
|
gint align)
|
1999-09-18 06:28:25 +08:00
|
|
|
{
|
|
|
|
guchar *dest;
|
2000-05-02 04:22:55 +08:00
|
|
|
gint gray_val, red_val, green_val, blue_val, alpha_val;
|
|
|
|
gint col, row, i;
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
|
|
|
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
|
|
|
}
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2000-11-20 07:54:46 +08:00
|
|
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
|
|
source++; /* offset source once, to look at the high byte */
|
|
|
|
#endif
|
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
dest = channel[0].pixels + row * cols * channel[0].drawable->bpp;
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2005-01-02 03:13:38 +08:00
|
|
|
channel[i].pixel = channel[i].pixels + row * cols;
|
2003-07-15 20:35:39 +08:00
|
|
|
|
|
|
|
for (col = 0; col < cols; col++)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
2004-01-17 05:28:31 +08: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 20:35:39 +08:00
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-08-17 06:17:04 +08:00
|
|
|
*dest++ = *source; source += 2;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-21 01:10:16 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
2004-01-17 05:28:31 +08:00
|
|
|
{
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
}
|
2004-01-21 01:10:16 +08:00
|
|
|
else
|
2004-01-17 05:28:31 +08:00
|
|
|
{
|
|
|
|
gray_val = *source; source += 2;
|
|
|
|
alpha_val = *source; source += 2;
|
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
2004-01-21 01:10:16 +08:00
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = ((alpha_val - gray_val) * 255) / alpha_val;
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
2004-01-21 01:10:16 +08:00
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-08-17 06:17:04 +08:00
|
|
|
*dest++ = ~(*source); source += 2;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
2003-08-17 06:17:04 +08:00
|
|
|
*dest++= *source; source += 2;
|
|
|
|
if (alpha) *dest++= *source; source += 2;
|
2003-07-15 20:35:39 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-17 05:28:31 +08: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 20:35:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-08-17 06:17:04 +08:00
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
|
|
|
*dest++ = *source; source += 2;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* This case was handled earlier */
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2004-02-08 08:40:46 +08:00
|
|
|
{
|
|
|
|
*channel[i].pixel++ = *source; source += 2;
|
|
|
|
}
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
|
|
|
|
if (align)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
2003-08-17 06:17:04 +08:00
|
|
|
source += align * (1 + alpha + extra) * 2;
|
2003-07-15 20:35:39 +08:00
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_RGB:
|
2003-08-17 06:17:04 +08:00
|
|
|
source += align * (3 + alpha + extra) * 2;
|
2003-07-15 20:35:39 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-09-18 06:28:25 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
|
|
|
gimp_pixel_rgn_set_rect (&(channel[i].pixel_rgn), channel[i].pixels,
|
2004-02-08 08:40:46 +08:00
|
|
|
startcol, startrow, cols, rows);
|
1999-09-18 06:28:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-05-09 18:41:39 +08:00
|
|
|
read_8bit (const guchar *source,
|
2004-02-08 08:40:46 +08:00
|
|
|
channel_data *channel,
|
|
|
|
gushort photomet,
|
|
|
|
gint startrow,
|
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
|
|
|
gint align)
|
1999-09-18 06:28:25 +08:00
|
|
|
{
|
|
|
|
guchar *dest;
|
2000-05-02 04:22:55 +08:00
|
|
|
gint gray_val, red_val, green_val, blue_val, alpha_val;
|
|
|
|
gint col, row, i;
|
1999-09-18 06:28:25 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
|
|
|
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
1999-09-18 06:28:25 +08:00
|
|
|
}
|
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
dest = channel[0].pixels + row * cols * channel[0].drawable->bpp;
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 1; i <= extra; ++i)
|
|
|
|
channel[i].pixel = channel[i].pixels + row * cols;
|
2003-07-15 20:35:39 +08:00
|
|
|
|
|
|
|
for (col = 0; col < cols; col++)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
2004-01-17 05:28:31 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
gray_val = *source++;
|
|
|
|
alpha_val = *source++;
|
|
|
|
gray_val = MIN(gray_val, alpha_val);
|
2004-01-17 05:28:31 +08:00
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = gray_val * 255 / alpha_val;
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = *source++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
2004-01-17 05:28:31 +08: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 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = ~(*source++);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
|
|
|
*dest++= *source++;
|
2003-12-03 06:32:42 +08:00
|
|
|
if (alpha)
|
|
|
|
*dest++= *source++;
|
2003-07-15 20:35:39 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
if (alpha)
|
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
|
|
|
*dest++ = *source; source++;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-17 05:28:31 +08: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 20:35:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = *source++;
|
|
|
|
*dest++ = *source++;
|
|
|
|
*dest++ = *source++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* This case was handled earlier */
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
*channel[i].pixel++ = *source++;
|
|
|
|
}
|
|
|
|
|
2005-01-02 03:13:38 +08: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 10:05:24 +08:00
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
1999-09-18 06:28:25 +08:00
|
|
|
gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
|
2003-07-15 20:35:39 +08:00
|
|
|
startcol, startrow, cols, rows);
|
1998-11-09 10:05:24 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-01-02 03:13:38 +08:00
|
|
|
static void
|
2005-05-09 18:41:39 +08:00
|
|
|
read_bw (const guchar *source,
|
2005-01-02 03:13:38 +08: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-02 03:28:59 +08:00
|
|
|
dest += col;
|
|
|
|
source++;
|
2005-01-02 03:13:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
source += align;
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_pixel_rgn_set_rect(&(channel[0].pixel_rgn), channel[0].pixels,
|
|
|
|
startcol, startrow, cols, rows);
|
|
|
|
}
|
|
|
|
|
1998-05-18 08:54:11 +08:00
|
|
|
/* Step through all <= 8-bit samples in an image */
|
|
|
|
|
|
|
|
#define NEXTSAMPLE(var) \
|
1997-11-25 06:05:25 +08:00
|
|
|
{ \
|
1998-05-18 08:54:11 +08:00
|
|
|
if (bitsleft == 0) \
|
1997-11-25 06:05:25 +08:00
|
|
|
{ \
|
2004-02-08 08:40:46 +08:00
|
|
|
source++; \
|
|
|
|
bitsleft = 8; \
|
1997-11-25 06:05:25 +08:00
|
|
|
} \
|
|
|
|
bitsleft -= bps; \
|
1999-09-18 06:28:25 +08:00
|
|
|
var = ( *source >> bitsleft ) & maxval; \
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
1998-11-09 10:05:24 +08:00
|
|
|
static void
|
2005-05-09 18:41:39 +08:00
|
|
|
read_default (const guchar *source,
|
2004-02-08 08:40:46 +08:00
|
|
|
channel_data *channel,
|
|
|
|
gushort bps,
|
|
|
|
gushort photomet,
|
|
|
|
gint startrow,
|
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
|
|
|
gboolean alpha,
|
|
|
|
gint extra,
|
2000-10-26 07:49:30 +08:00
|
|
|
gint align)
|
1998-11-09 10:05:24 +08:00
|
|
|
{
|
1999-09-18 06:28:25 +08:00
|
|
|
guchar *dest;
|
2000-05-02 04:22:55 +08: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 10:05:24 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
|
|
|
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
1998-11-09 10:05:24 +08:00
|
|
|
}
|
1998-05-18 08:54:11 +08:00
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
for (row = 0; row < rows; ++row)
|
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
dest = channel[0].pixels + row * cols * channel[0].drawable->bpp;
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2005-01-02 03:13:38 +08:00
|
|
|
channel[i].pixel = channel[i].pixels + row * cols;
|
2003-07-15 20:35:39 +08:00
|
|
|
|
|
|
|
for (col = 0; col < cols; col++)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
NEXTSAMPLE (gray_val);
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
NEXTSAMPLE (alpha_val);
|
2004-01-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = (gray_val * 255) / maxval;
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
2004-01-17 05:28:31 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
if (alpha_val)
|
|
|
|
*dest++ = (gray_val * 65025) / (alpha_val * maxval);
|
|
|
|
else
|
|
|
|
*dest++ = 0;
|
|
|
|
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = (gray_val * 255) / maxval;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
NEXTSAMPLE (gray_val);
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
NEXTSAMPLE (alpha_val);
|
2004-01-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
|
|
|
{
|
|
|
|
*dest++ = ((maxval - gray_val) * 255) / maxval;
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
else
|
2004-01-17 05:28:31 +08:00
|
|
|
{
|
2005-01-02 03:13:38 +08:00
|
|
|
gray_val = MIN (gray_val, alpha_val);
|
2004-01-21 01:10:16 +08:00
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
if (alpha_val)
|
2005-01-02 03:13:38 +08:00
|
|
|
*dest++ = ((maxval - gray_val) * 65025) /
|
|
|
|
(alpha_val * maxval);
|
2004-01-17 05:28:31 +08:00
|
|
|
else
|
|
|
|
*dest++ = 0;
|
|
|
|
|
|
|
|
*dest++ = alpha_val;
|
|
|
|
}
|
2003-07-15 20:35:39 +08: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-17 05:28:31 +08:00
|
|
|
if (tsvals.save_transp_pixels)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
2004-01-17 05:28:31 +08:00
|
|
|
*dest++ = red_val;
|
|
|
|
*dest++ = green_val;
|
|
|
|
*dest++ = blue_val;
|
|
|
|
*dest++ = alpha_val;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-17 05:28:31 +08: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-21 01:10:16 +08:00
|
|
|
|
2004-01-17 05:28:31 +08:00
|
|
|
*dest++ = alpha_val;
|
2003-07-15 20:35:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dest++ = red_val;
|
|
|
|
*dest++ = green_val;
|
|
|
|
*dest++ = blue_val;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* This case was handled earlier */
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 1; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
{
|
|
|
|
NEXTSAMPLE(alpha_val);
|
|
|
|
*channel[i].pixel++ = alpha_val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (align)
|
|
|
|
{
|
|
|
|
switch (photomet)
|
|
|
|
{
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i < align * (1 + alpha + extra); ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
NEXTSAMPLE (alpha_val);
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_RGB:
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i < align * (3 + alpha + extra); ++i)
|
|
|
|
NEXTSAMPLE (alpha_val);
|
2003-07-15 20:35:39 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-02 03:13:38 +08:00
|
|
|
bitsleft = 0;
|
2000-10-26 07:49:30 +08:00
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
|
2003-08-17 06:17:04 +08:00
|
|
|
for (i = 0; i <= extra; ++i)
|
2003-07-15 20:35:39 +08:00
|
|
|
gimp_pixel_rgn_set_rect (&(channel[i].pixel_rgn), channel[i].pixels,
|
|
|
|
startcol, startrow, cols, rows);
|
1998-11-09 10:05:24 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-11-09 10:05:24 +08:00
|
|
|
static void
|
2005-05-09 18:41:39 +08:00
|
|
|
read_separate (const guchar *source,
|
2004-02-08 08:40:46 +08:00
|
|
|
channel_data *channel,
|
2000-05-02 04:22:55 +08:00
|
|
|
gushort bps,
|
2004-02-08 08:40:46 +08:00
|
|
|
gushort photomet,
|
2000-05-02 04:22:55 +08:00
|
|
|
gint startrow,
|
2004-02-08 08:40:46 +08:00
|
|
|
gint startcol,
|
|
|
|
gint rows,
|
|
|
|
gint cols,
|
2003-12-03 06:32:42 +08:00
|
|
|
gboolean alpha,
|
2004-02-08 08:40:46 +08:00
|
|
|
gint extra,
|
|
|
|
gint sample)
|
1998-11-09 10:05:24 +08:00
|
|
|
{
|
1999-09-18 06:28:25 +08:00
|
|
|
guchar *dest;
|
2000-05-02 04:22:55 +08:00
|
|
|
gint col, row, c;
|
|
|
|
gint bitsleft = 8, maxval = (1 << bps) - 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
if (bps > 8)
|
|
|
|
{
|
|
|
|
g_message ("Unsupported layout");
|
|
|
|
gimp_quit ();
|
|
|
|
}
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-07-15 20:35:39 +08:00
|
|
|
if (sample < channel[0].drawable->bpp)
|
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = (sample - channel[0].drawable->bpp) + 4;
|
|
|
|
photomet = PHOTOMETRIC_MINISBLACK;
|
|
|
|
}
|
1998-11-09 10:05:24 +08:00
|
|
|
|
1999-09-18 06:28:25 +08:00
|
|
|
gimp_pixel_rgn_init (&(channel[c].pixel_rgn), channel[c].drawable,
|
|
|
|
startcol, startrow, cols, rows, TRUE, FALSE);
|
1998-11-09 10:05:24 +08:00
|
|
|
|
2003-07-15 20:35:39 +08: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 10:05:24 +08:00
|
|
|
}
|
2003-07-15 20:35:39 +08:00
|
|
|
|
|
|
|
gimp_pixel_rgn_set_rect (&(channel[c].pixel_rgn), channel[c].pixels,
|
|
|
|
startcol, startrow, cols, rows);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2005-01-02 03:13:38 +08: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;
|
|
|
|
}
|