mirror of https://github.com/GNOME/gimp.git
Updated tiff plug-in.
From Nicolas Lamb: This is a total replacement for the TIFF loading code, probably 50% new code and the rest rewritten. It is faster (for boring images, such as RGB and 8-bit Grayscale) and more stable. --Sven
This commit is contained in:
parent
a7b206b5c3
commit
11832a6f1d
|
@ -1,3 +1,7 @@
|
|||
Mon May 18 02:50:03 MEST 1998 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* plug-ins/tiff/tiff.c: updated tiff plug-in
|
||||
|
||||
Sun May 17 17:31:05 PDT 1998 Manish Singh <yosh@gimp.org>
|
||||
|
||||
* plug-ins/maze: updated maze plugin
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* tiff loading and saving for the GIMP
|
||||
* -Peter Mattis
|
||||
* various fixes along the route to GIMP 1.0
|
||||
* -Nick Lamb and others (list yourselves here people)
|
||||
* The TIFF loading code has been completely revamped by Nick Lamb
|
||||
* njl195@zepler.org.uk -- 18 May 1998
|
||||
*
|
||||
* The code for this filter is based on "tifftopnm" and "pnmtotiff",
|
||||
* 2 programs that are a part of the netpbm package.
|
||||
|
@ -57,8 +57,8 @@ static void run (char *name,
|
|||
GParam **return_vals);
|
||||
static gint32 load_image (char *filename);
|
||||
static gint save_image (char *filename,
|
||||
gint32 image_ID,
|
||||
gint32 drawable_ID);
|
||||
gint32 image,
|
||||
gint32 drawable);
|
||||
|
||||
static gint save_dialog ();
|
||||
|
||||
|
@ -123,9 +123,9 @@ query ()
|
|||
gimp_install_procedure ("file_tiff_load",
|
||||
"loads files of the tiff file format",
|
||||
"FIXME: write help for tiff_load",
|
||||
"Spencer Kimball & Peter Mattis",
|
||||
"Spencer Kimball & Peter Mattis",
|
||||
"1995-1996",
|
||||
"Spencer Kimball, Peter Mattis & Nick Lamb",
|
||||
"Nick Lamb <njl195@.ecs.soton.ac.uk>",
|
||||
"1995-1996,1998",
|
||||
"<Load>/Tiff",
|
||||
NULL,
|
||||
PROC_PLUG_IN,
|
||||
|
@ -139,7 +139,7 @@ query ()
|
|||
"Spencer Kimball & Peter Mattis",
|
||||
"1995-1996",
|
||||
"<Save>/Tiff",
|
||||
"RGB*, GRAY*",
|
||||
"RGB*, GRAY*, INDEXED",
|
||||
PROC_PLUG_IN,
|
||||
nsave_args, 0,
|
||||
save_args, NULL);
|
||||
|
@ -159,7 +159,7 @@ run (char *name,
|
|||
static GParam values[2];
|
||||
GRunModeType run_mode;
|
||||
GStatusType status = STATUS_SUCCESS;
|
||||
gint32 image_ID;
|
||||
gint32 image;
|
||||
|
||||
run_mode = param[0].data.d_int32;
|
||||
|
||||
|
@ -170,14 +170,14 @@ run (char *name,
|
|||
|
||||
if (strcmp (name, "file_tiff_load") == 0)
|
||||
{
|
||||
image_ID = load_image (param[1].data.d_string);
|
||||
image = load_image (param[1].data.d_string);
|
||||
|
||||
if (image_ID != -1)
|
||||
if (image != -1)
|
||||
{
|
||||
*nreturn_vals = 2;
|
||||
values[0].data.d_status = STATUS_SUCCESS;
|
||||
values[1].type = PARAM_IMAGE;
|
||||
values[1].data.d_image = image_ID;
|
||||
values[1].data.d_image = image;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -240,410 +240,307 @@ run (char *name,
|
|||
}
|
||||
}
|
||||
|
||||
static gint32
|
||||
load_image (char *filename)
|
||||
{
|
||||
static gint32 load_image (char *filename) {
|
||||
TIFF *tif;
|
||||
int col;
|
||||
unsigned short bps, spp, photomet;
|
||||
int cols, rows, maxval, alpha;
|
||||
int image, layer, tile_height;
|
||||
unsigned short *redmap, *greenmap, *bluemap;
|
||||
guchar cmap[768];
|
||||
int image_type= 0, layer_type= 0;
|
||||
unsigned short *extra_types, extra = 0;
|
||||
|
||||
int col, row, start, i, j;
|
||||
unsigned char sample;
|
||||
int bitsleft;
|
||||
int cols, rows, grayscale;
|
||||
int alpha;
|
||||
int gray_val, red_val, green_val, blue_val, alpha_val;
|
||||
int numcolors;
|
||||
int row, i;
|
||||
guchar *buf, *s;
|
||||
guchar *dest, *d;
|
||||
int maxval;
|
||||
int image_type;
|
||||
int layer_type;
|
||||
unsigned short bps, spp, photomet;
|
||||
unsigned short *redcolormap;
|
||||
unsigned short *greencolormap;
|
||||
unsigned short *bluecolormap;
|
||||
unsigned short k, num_extra = 0;
|
||||
unsigned short *extra_samples;
|
||||
int image_ID;
|
||||
int layer_ID;
|
||||
|
||||
guchar *source, *s, *dest, *d;
|
||||
GDrawable *drawable;
|
||||
GPixelRgn pixel_rgn;
|
||||
int tile_height;
|
||||
int y, yend;
|
||||
char *name;
|
||||
|
||||
typedef struct {
|
||||
gint32 ID;
|
||||
GDrawable *drawable;
|
||||
GPixelRgn pixel_rgn;
|
||||
guchar *pixels, *pixel;
|
||||
} channel_data;
|
||||
|
||||
channel_data *channel;
|
||||
|
||||
guchar colors[3]= {0, 0, 0};
|
||||
|
||||
tif = TIFFOpen (filename, "r");
|
||||
if (!tif)
|
||||
{
|
||||
g_warning ("can't open \"%s\"\n", filename);
|
||||
gimp_quit ();
|
||||
}
|
||||
typedef struct {
|
||||
gint32 ID;
|
||||
GDrawable *drawable;
|
||||
GPixelRgn pixel_rgn;
|
||||
guchar *pixels;
|
||||
guchar *pixel;
|
||||
} channel_data;
|
||||
|
||||
name = malloc (strlen (filename) + 12);
|
||||
channel_data *channel= NULL;
|
||||
|
||||
tif = TIFFOpen (filename, "r");
|
||||
if (!tif) {
|
||||
g_error ("TIFF Can't open \"%s\"\n", filename);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
name = g_malloc (strlen (filename) + 12);
|
||||
sprintf (name, "Loading %s:", filename);
|
||||
gimp_progress_init (name);
|
||||
free (name);
|
||||
g_free (name);
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_BITSPERSAMPLE, &bps))
|
||||
bps = 1;
|
||||
|
||||
if (bps > 8) {
|
||||
g_error("TIFF Can't handle samples wider than 8-bit\n");
|
||||
gimp_quit();
|
||||
}
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_SAMPLESPERPIXEL, &spp))
|
||||
spp = 1;
|
||||
if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &num_extra, &extra_samples))
|
||||
alpha = 0;
|
||||
if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet))
|
||||
{
|
||||
g_warning ("error getting photometric\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
|
||||
extra = 0;
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols)) {
|
||||
g_error ("TIFF Can't get image width\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows)) {
|
||||
g_error ("TIFF Can't get image length\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet)) {
|
||||
g_error ("TIFF Can't get photometric\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
/* test if the extrasample represents an associated alpha channel... */
|
||||
if (num_extra > 0 && (extra_samples [0] == EXTRASAMPLE_ASSOCALPHA))
|
||||
if (extra > 0 && (extra_types[0] == EXTRASAMPLE_ASSOCALPHA)) {
|
||||
alpha = 1;
|
||||
else
|
||||
} else {
|
||||
alpha = 0;
|
||||
}
|
||||
|
||||
if (spp > 3) alpha = 1; /* Kludge - like all the rest of this -- njl195 */
|
||||
|
||||
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols);
|
||||
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows);
|
||||
/* some programs seem to think alpha etc. aren't "extra" samples (?) */
|
||||
if (spp > 3) {
|
||||
extra= spp - 3;
|
||||
}
|
||||
|
||||
maxval = (1 << bps) - 1;
|
||||
if (maxval == 1 && spp == 1)
|
||||
{
|
||||
grayscale = 1;
|
||||
|
||||
switch (photomet) {
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
image_type = GRAY;
|
||||
layer_type = (alpha) ? GRAYA_IMAGE : GRAY_IMAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (photomet)
|
||||
{
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
grayscale = 1;
|
||||
image_type = GRAY;
|
||||
layer_type = (alpha) ? GRAYA_IMAGE : GRAY_IMAGE;
|
||||
break;
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
grayscale = 1;
|
||||
image_type = GRAY;
|
||||
layer_type = (alpha) ? GRAYA_IMAGE : GRAY_IMAGE;
|
||||
break;
|
||||
case PHOTOMETRIC_RGB:
|
||||
image_type = RGB;
|
||||
layer_type = (alpha) ? RGBA_IMAGE : RGB_IMAGE;
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
if (alpha)
|
||||
g_print ("ignoring alpha channel on indexed color image\n");
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
image_type = INDEXED;
|
||||
layer_type = (alpha) ? INDEXEDA_IMAGE : INDEXED_IMAGE;
|
||||
break;
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_COLORMAP, &redcolormap,
|
||||
&greencolormap, &bluecolormap))
|
||||
{
|
||||
g_print ("error getting colormaps\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
numcolors = maxval + 1;
|
||||
maxval = 255;
|
||||
grayscale = 0;
|
||||
case PHOTOMETRIC_MASK:
|
||||
g_error ("TIFF Can't handle PHOTOMETRIC_MASK\n");
|
||||
gimp_quit ();
|
||||
break;
|
||||
default:
|
||||
g_error ("TIFF Unknown photometric: %d\n", photomet);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
for (i = 0; i < numcolors; i++)
|
||||
{
|
||||
redcolormap[i] >>= 8;
|
||||
greencolormap[i] >>= 8;
|
||||
bluecolormap[i] >>= 8;
|
||||
}
|
||||
if ((image = gimp_image_new (cols, rows, image_type)) == -1) {
|
||||
g_error ("TIFF Can't allocate new image\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
gimp_image_set_filename (image, filename);
|
||||
|
||||
if (numcolors > 256)
|
||||
{
|
||||
image_type = RGB;
|
||||
layer_type = (alpha) ? RGBA_IMAGE : RGB_IMAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
image_type = INDEXED;
|
||||
layer_type = (alpha) ? INDEXEDA_IMAGE : INDEXED_IMAGE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_RGB:
|
||||
grayscale = 0;
|
||||
image_type = RGB;
|
||||
layer_type = (alpha) ? RGBA_IMAGE : RGB_IMAGE;
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MASK:
|
||||
g_print ("don't know how to handle PHOTOMETRIC_MASK\n");
|
||||
gimp_quit ();
|
||||
|
||||
default:
|
||||
g_print ("unknown photometric: %d\n", photomet);
|
||||
gimp_quit ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
image_ID = gimp_image_new (cols, rows, image_type);
|
||||
if (image_ID == -1)
|
||||
{
|
||||
g_print ("can't allocate new image\n");
|
||||
/* Install colormap for INDEXED images only */
|
||||
if (image_type == INDEXED) {
|
||||
if (!TIFFGetField (tif, TIFFTAG_COLORMAP, &redmap, &greenmap, &bluemap)) {
|
||||
g_error ("TIFF Can't get colormaps\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
gimp_image_set_filename (image_ID, filename);
|
||||
|
||||
if ((image_type == INDEXED) && (numcolors <= 256))
|
||||
{
|
||||
guchar *cmap;
|
||||
gint i, j;
|
||||
|
||||
cmap = g_new (guchar, numcolors * 3);
|
||||
for (i = 0, j = 0; i < numcolors; i++)
|
||||
{
|
||||
cmap[j++] = redcolormap[i];
|
||||
cmap[j++] = greencolormap[i];
|
||||
cmap[j++] = bluecolormap[i];
|
||||
}
|
||||
|
||||
gimp_image_set_cmap (image_ID, cmap, numcolors);
|
||||
g_free (cmap);
|
||||
for (i = 0, j = 0; i <= maxval; i++) {
|
||||
cmap[j++] = redmap[i] >> 8;
|
||||
cmap[j++] = greenmap[i] >> 8;
|
||||
cmap[j++] = bluemap[i] >> 8;
|
||||
}
|
||||
gimp_image_set_cmap (image, cmap, maxval + 1);
|
||||
}
|
||||
|
||||
layer_ID = gimp_layer_new (image_ID, "Background",
|
||||
cols, rows, layer_type,
|
||||
layer = gimp_layer_new (image, "Background", cols, rows, layer_type,
|
||||
100, NORMAL_MODE);
|
||||
gimp_image_add_layer (image_ID, layer_ID, 0);
|
||||
|
||||
buf = g_new (guchar, TIFFScanlineSize (tif));
|
||||
|
||||
drawable = gimp_drawable_get (layer_ID);
|
||||
gimp_image_add_layer (image, layer, 0);
|
||||
drawable = gimp_drawable_get (layer);
|
||||
|
||||
source= g_new (guchar, TIFFScanlineSize (tif));
|
||||
tile_height = gimp_tile_height ();
|
||||
dest = g_new (guchar, tile_height * cols * drawable->bpp);
|
||||
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, cols, rows, TRUE, FALSE);
|
||||
|
||||
if (num_extra - alpha > 0)
|
||||
channel = g_new (channel_data, num_extra - alpha);
|
||||
if (extra - alpha > 0)
|
||||
channel = g_new (channel_data, extra - alpha);
|
||||
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
channel[k].ID= gimp_channel_new(image_ID, "TIFF Channel", cols, rows,
|
||||
100.0, colors);
|
||||
gimp_image_add_channel(image_ID, channel[k].ID, 0);
|
||||
channel[k].drawable= gimp_drawable_get (channel[k].ID);
|
||||
channel[k].pixels= g_new(guchar, tile_height * cols);
|
||||
/* Add alpha channels as appropriate */
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
channel[i].ID= gimp_channel_new(image, "TIFF Channel", cols, rows,
|
||||
100.0, colors);
|
||||
gimp_image_add_channel(image, channel[i].ID, 0);
|
||||
channel[i].drawable= gimp_drawable_get (channel[i].ID);
|
||||
channel[i].pixels= g_new(guchar, tile_height * cols);
|
||||
|
||||
gimp_pixel_rgn_init (&(channel[k].pixel_rgn), channel[k].drawable, 0, 0,
|
||||
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable, 0, 0,
|
||||
cols, rows, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#define NEXTSAMPLE \
|
||||
/* Step through all <= 8-bit samples in an image */
|
||||
|
||||
#define NEXTSAMPLE(var) \
|
||||
{ \
|
||||
if ( bitsleft == 0 ) \
|
||||
if (bitsleft == 0) \
|
||||
{ \
|
||||
s++; \
|
||||
bitsleft = 8; \
|
||||
} \
|
||||
bitsleft -= bps; \
|
||||
sample = ( *s >> bitsleft ) & maxval; \
|
||||
var = ( *s >> bitsleft ) & maxval; \
|
||||
}
|
||||
|
||||
for (y = 0; y < rows; y = yend)
|
||||
{
|
||||
yend = y + tile_height;
|
||||
yend = MIN (yend, rows);
|
||||
for (start= 0, row = 0; row < rows; ++row) {
|
||||
d= dest + cols * (row % tile_height) * drawable->bpp;
|
||||
|
||||
for (row = y; row < yend; row++)
|
||||
{
|
||||
if (TIFFReadScanline (tif, buf, row, 0) < 0)
|
||||
{
|
||||
g_print ("bad data read on line %d\n", row);
|
||||
gimp_quit ();
|
||||
/* Special cases: Scanline is compatible with GIMP storage */
|
||||
if (extra == 0 && bps == 8) {
|
||||
if (TIFFReadScanline (tif, d, row, 0) < 0) {
|
||||
g_error ("TIFF Bad data read on line %d\n", row);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
/* Or read in and process each sample -- slower */
|
||||
} else {
|
||||
if (TIFFReadScanline (tif, source, row, 0) < 0) {
|
||||
g_error ("TIFF Bad data read on line %d\n", row);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
channel[i].pixel= channel[i].pixels + cols * (row % tile_height);
|
||||
}
|
||||
|
||||
/* Set s/bitleft ready to use NEXTSAMPLE macro */
|
||||
|
||||
s= source;
|
||||
bitsleft= 8;
|
||||
|
||||
switch (photomet) {
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(gray_val);
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(alpha_val);
|
||||
if (alpha_val)
|
||||
*d++ = (gray_val * 65025) / (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
} else {
|
||||
*d++ = (gray_val * 255) / maxval;
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(gray_val);
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(alpha_val);
|
||||
if (alpha_val)
|
||||
*d++ = ((maxval - gray_val) * 65025) / (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
} else {
|
||||
*d++ = ((maxval - gray_val) * 255) / maxval;
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(*d++);
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(*d++);
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_RGB:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(red_val)
|
||||
NEXTSAMPLE(green_val)
|
||||
NEXTSAMPLE(blue_val)
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(alpha_val)
|
||||
if (alpha_val) {
|
||||
*d++ = (red_val * 255) / alpha_val;
|
||||
*d++ = (green_val * 255) / alpha_val;
|
||||
*d++ = (blue_val * 255) / alpha_val;
|
||||
} else {
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
}
|
||||
*d++ = alpha_val;
|
||||
} else {
|
||||
*d++ = red_val;
|
||||
*d++ = green_val;
|
||||
*d++ = blue_val;
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
bitsleft = 8;
|
||||
s = buf;
|
||||
d = dest + cols * (row - y) * drawable->bpp;
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
channel[k].pixel= channel[k].pixels + cols * (row - y);
|
||||
|
||||
switch (photomet)
|
||||
{
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
gray_val = sample;
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
*d++ = (gray_val * 65025) / (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
*d++ = (gray_val * 255) / maxval;
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
gray_val = sample;
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
*d++ = ((maxval - gray_val) * 65025)
|
||||
/ (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
*d++ = ((maxval - gray_val) * 255) / maxval ;
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
if (numcolors > 256)
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
red_val = redcolormap[sample];
|
||||
green_val = greencolormap[sample];
|
||||
blue_val = bluecolormap[sample];
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
{
|
||||
*d++ = (red_val * 255) / alpha_val;
|
||||
*d++ = (green_val * 255) / alpha_val;
|
||||
*d++ = (blue_val * 255) / alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
}
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = red_val;
|
||||
*d++ = green_val;
|
||||
*d++ = blue_val;
|
||||
}
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
if (alpha)
|
||||
{
|
||||
*d++ = sample;
|
||||
NEXTSAMPLE;
|
||||
*d++ = sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = sample;
|
||||
}
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_RGB:
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
red_val = sample;
|
||||
NEXTSAMPLE;
|
||||
green_val = sample;
|
||||
NEXTSAMPLE;
|
||||
blue_val = sample;
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
{
|
||||
*d++ = (red_val * 255) / alpha_val;
|
||||
*d++ = (green_val * 255) / alpha_val;
|
||||
*d++ = (blue_val * 255) / alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
}
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = red_val;
|
||||
*d++ = green_val;
|
||||
*d++ = blue_val;
|
||||
}
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_print ("unknown photometric: %d\n", photomet);
|
||||
gimp_quit ();
|
||||
}
|
||||
}
|
||||
|
||||
gimp_pixel_rgn_set_rect (&pixel_rgn, dest, 0, y, cols, yend - y);
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
gimp_pixel_rgn_set_rect(&(channel[k].pixel_rgn),
|
||||
channel[k].pixels, 0, y, cols, yend -y);
|
||||
gimp_progress_update ((double) row / (double) rows);
|
||||
default:
|
||||
/* This case was handled earlier */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (((row + 1) % tile_height) == 0 || row + 1 == rows) {
|
||||
gimp_pixel_rgn_set_rect (&pixel_rgn, dest, 0, start, cols, 1+row-start);
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
|
||||
0, start, cols, 1+row-start);
|
||||
}
|
||||
gimp_progress_update ((double) row / (double) rows);
|
||||
start= row + 1;
|
||||
}
|
||||
}
|
||||
|
||||
gimp_drawable_flush (drawable);
|
||||
gimp_drawable_detach (drawable);
|
||||
|
||||
return image_ID;
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -669,11 +566,7 @@ load_image (char *filename)
|
|||
** other special, indirect and consequential damages.
|
||||
*/
|
||||
|
||||
static gint
|
||||
save_image (char *filename,
|
||||
gint32 image_ID,
|
||||
gint32 drawable_ID)
|
||||
{
|
||||
static gint save_image (char *filename, gint32 image, gint32 layer) {
|
||||
TIFF *tif;
|
||||
unsigned short red[256];
|
||||
unsigned short grn[256];
|
||||
|
@ -720,8 +613,8 @@ save_image (char *filename,
|
|||
gimp_progress_init (name);
|
||||
free (name);
|
||||
|
||||
drawable = gimp_drawable_get (drawable_ID);
|
||||
drawable_type = gimp_drawable_type (drawable_ID);
|
||||
drawable = gimp_drawable_get (layer);
|
||||
drawable_type = gimp_drawable_type (layer);
|
||||
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
||||
|
||||
cols = drawable->width;
|
||||
|
@ -764,7 +657,7 @@ save_image (char *filename,
|
|||
bytesperrow = cols;
|
||||
alpha = 0;
|
||||
|
||||
cmap = gimp_image_get_cmap (image_ID, &colors);
|
||||
cmap = gimp_image_get_cmap (image, &colors);
|
||||
|
||||
for (i = 0; i < colors; i++)
|
||||
{
|
||||
|
@ -798,13 +691,13 @@ save_image (char *filename,
|
|||
TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField (tif, TIFFTAG_FILLORDER, fillorder);
|
||||
TIFFSetField (tif, TIFFTAG_DOCUMENTNAME, filename);
|
||||
TIFFSetField (tif, TIFFTAG_IMAGEDESCRIPTION, "created with The GIMP");
|
||||
TIFFSetField (tif, TIFFTAG_IMAGEDESCRIPTION, "Created with The GIMP");
|
||||
TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
|
||||
TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
/* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, rows / rowsperstrip ); */
|
||||
TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
|
||||
if (gimp_drawable_type (drawable_ID) == INDEXED_IMAGE)
|
||||
if (drawable_type == INDEXED_IMAGE)
|
||||
TIFFSetField (tif, TIFFTAG_COLORMAP, red, grn, blu);
|
||||
|
||||
/* array to rearrange data */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* tiff loading and saving for the GIMP
|
||||
* -Peter Mattis
|
||||
* various fixes along the route to GIMP 1.0
|
||||
* -Nick Lamb and others (list yourselves here people)
|
||||
* The TIFF loading code has been completely revamped by Nick Lamb
|
||||
* njl195@zepler.org.uk -- 18 May 1998
|
||||
*
|
||||
* The code for this filter is based on "tifftopnm" and "pnmtotiff",
|
||||
* 2 programs that are a part of the netpbm package.
|
||||
|
@ -57,8 +57,8 @@ static void run (char *name,
|
|||
GParam **return_vals);
|
||||
static gint32 load_image (char *filename);
|
||||
static gint save_image (char *filename,
|
||||
gint32 image_ID,
|
||||
gint32 drawable_ID);
|
||||
gint32 image,
|
||||
gint32 drawable);
|
||||
|
||||
static gint save_dialog ();
|
||||
|
||||
|
@ -123,9 +123,9 @@ query ()
|
|||
gimp_install_procedure ("file_tiff_load",
|
||||
"loads files of the tiff file format",
|
||||
"FIXME: write help for tiff_load",
|
||||
"Spencer Kimball & Peter Mattis",
|
||||
"Spencer Kimball & Peter Mattis",
|
||||
"1995-1996",
|
||||
"Spencer Kimball, Peter Mattis & Nick Lamb",
|
||||
"Nick Lamb <njl195@.ecs.soton.ac.uk>",
|
||||
"1995-1996,1998",
|
||||
"<Load>/Tiff",
|
||||
NULL,
|
||||
PROC_PLUG_IN,
|
||||
|
@ -139,7 +139,7 @@ query ()
|
|||
"Spencer Kimball & Peter Mattis",
|
||||
"1995-1996",
|
||||
"<Save>/Tiff",
|
||||
"RGB*, GRAY*",
|
||||
"RGB*, GRAY*, INDEXED",
|
||||
PROC_PLUG_IN,
|
||||
nsave_args, 0,
|
||||
save_args, NULL);
|
||||
|
@ -159,7 +159,7 @@ run (char *name,
|
|||
static GParam values[2];
|
||||
GRunModeType run_mode;
|
||||
GStatusType status = STATUS_SUCCESS;
|
||||
gint32 image_ID;
|
||||
gint32 image;
|
||||
|
||||
run_mode = param[0].data.d_int32;
|
||||
|
||||
|
@ -170,14 +170,14 @@ run (char *name,
|
|||
|
||||
if (strcmp (name, "file_tiff_load") == 0)
|
||||
{
|
||||
image_ID = load_image (param[1].data.d_string);
|
||||
image = load_image (param[1].data.d_string);
|
||||
|
||||
if (image_ID != -1)
|
||||
if (image != -1)
|
||||
{
|
||||
*nreturn_vals = 2;
|
||||
values[0].data.d_status = STATUS_SUCCESS;
|
||||
values[1].type = PARAM_IMAGE;
|
||||
values[1].data.d_image = image_ID;
|
||||
values[1].data.d_image = image;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -240,410 +240,307 @@ run (char *name,
|
|||
}
|
||||
}
|
||||
|
||||
static gint32
|
||||
load_image (char *filename)
|
||||
{
|
||||
static gint32 load_image (char *filename) {
|
||||
TIFF *tif;
|
||||
int col;
|
||||
unsigned short bps, spp, photomet;
|
||||
int cols, rows, maxval, alpha;
|
||||
int image, layer, tile_height;
|
||||
unsigned short *redmap, *greenmap, *bluemap;
|
||||
guchar cmap[768];
|
||||
int image_type= 0, layer_type= 0;
|
||||
unsigned short *extra_types, extra = 0;
|
||||
|
||||
int col, row, start, i, j;
|
||||
unsigned char sample;
|
||||
int bitsleft;
|
||||
int cols, rows, grayscale;
|
||||
int alpha;
|
||||
int gray_val, red_val, green_val, blue_val, alpha_val;
|
||||
int numcolors;
|
||||
int row, i;
|
||||
guchar *buf, *s;
|
||||
guchar *dest, *d;
|
||||
int maxval;
|
||||
int image_type;
|
||||
int layer_type;
|
||||
unsigned short bps, spp, photomet;
|
||||
unsigned short *redcolormap;
|
||||
unsigned short *greencolormap;
|
||||
unsigned short *bluecolormap;
|
||||
unsigned short k, num_extra = 0;
|
||||
unsigned short *extra_samples;
|
||||
int image_ID;
|
||||
int layer_ID;
|
||||
|
||||
guchar *source, *s, *dest, *d;
|
||||
GDrawable *drawable;
|
||||
GPixelRgn pixel_rgn;
|
||||
int tile_height;
|
||||
int y, yend;
|
||||
char *name;
|
||||
|
||||
typedef struct {
|
||||
gint32 ID;
|
||||
GDrawable *drawable;
|
||||
GPixelRgn pixel_rgn;
|
||||
guchar *pixels, *pixel;
|
||||
} channel_data;
|
||||
|
||||
channel_data *channel;
|
||||
|
||||
guchar colors[3]= {0, 0, 0};
|
||||
|
||||
tif = TIFFOpen (filename, "r");
|
||||
if (!tif)
|
||||
{
|
||||
g_warning ("can't open \"%s\"\n", filename);
|
||||
gimp_quit ();
|
||||
}
|
||||
typedef struct {
|
||||
gint32 ID;
|
||||
GDrawable *drawable;
|
||||
GPixelRgn pixel_rgn;
|
||||
guchar *pixels;
|
||||
guchar *pixel;
|
||||
} channel_data;
|
||||
|
||||
name = malloc (strlen (filename) + 12);
|
||||
channel_data *channel= NULL;
|
||||
|
||||
tif = TIFFOpen (filename, "r");
|
||||
if (!tif) {
|
||||
g_error ("TIFF Can't open \"%s\"\n", filename);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
name = g_malloc (strlen (filename) + 12);
|
||||
sprintf (name, "Loading %s:", filename);
|
||||
gimp_progress_init (name);
|
||||
free (name);
|
||||
g_free (name);
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_BITSPERSAMPLE, &bps))
|
||||
bps = 1;
|
||||
|
||||
if (bps > 8) {
|
||||
g_error("TIFF Can't handle samples wider than 8-bit\n");
|
||||
gimp_quit();
|
||||
}
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_SAMPLESPERPIXEL, &spp))
|
||||
spp = 1;
|
||||
if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &num_extra, &extra_samples))
|
||||
alpha = 0;
|
||||
if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet))
|
||||
{
|
||||
g_warning ("error getting photometric\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
|
||||
extra = 0;
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols)) {
|
||||
g_error ("TIFF Can't get image width\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows)) {
|
||||
g_error ("TIFF Can't get image length\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet)) {
|
||||
g_error ("TIFF Can't get photometric\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
/* test if the extrasample represents an associated alpha channel... */
|
||||
if (num_extra > 0 && (extra_samples [0] == EXTRASAMPLE_ASSOCALPHA))
|
||||
if (extra > 0 && (extra_types[0] == EXTRASAMPLE_ASSOCALPHA)) {
|
||||
alpha = 1;
|
||||
else
|
||||
} else {
|
||||
alpha = 0;
|
||||
}
|
||||
|
||||
if (spp > 3) alpha = 1; /* Kludge - like all the rest of this -- njl195 */
|
||||
|
||||
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols);
|
||||
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows);
|
||||
/* some programs seem to think alpha etc. aren't "extra" samples (?) */
|
||||
if (spp > 3) {
|
||||
extra= spp - 3;
|
||||
}
|
||||
|
||||
maxval = (1 << bps) - 1;
|
||||
if (maxval == 1 && spp == 1)
|
||||
{
|
||||
grayscale = 1;
|
||||
|
||||
switch (photomet) {
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
image_type = GRAY;
|
||||
layer_type = (alpha) ? GRAYA_IMAGE : GRAY_IMAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (photomet)
|
||||
{
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
grayscale = 1;
|
||||
image_type = GRAY;
|
||||
layer_type = (alpha) ? GRAYA_IMAGE : GRAY_IMAGE;
|
||||
break;
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
grayscale = 1;
|
||||
image_type = GRAY;
|
||||
layer_type = (alpha) ? GRAYA_IMAGE : GRAY_IMAGE;
|
||||
break;
|
||||
case PHOTOMETRIC_RGB:
|
||||
image_type = RGB;
|
||||
layer_type = (alpha) ? RGBA_IMAGE : RGB_IMAGE;
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
if (alpha)
|
||||
g_print ("ignoring alpha channel on indexed color image\n");
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
image_type = INDEXED;
|
||||
layer_type = (alpha) ? INDEXEDA_IMAGE : INDEXED_IMAGE;
|
||||
break;
|
||||
|
||||
if (!TIFFGetField (tif, TIFFTAG_COLORMAP, &redcolormap,
|
||||
&greencolormap, &bluecolormap))
|
||||
{
|
||||
g_print ("error getting colormaps\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
numcolors = maxval + 1;
|
||||
maxval = 255;
|
||||
grayscale = 0;
|
||||
case PHOTOMETRIC_MASK:
|
||||
g_error ("TIFF Can't handle PHOTOMETRIC_MASK\n");
|
||||
gimp_quit ();
|
||||
break;
|
||||
default:
|
||||
g_error ("TIFF Unknown photometric: %d\n", photomet);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
for (i = 0; i < numcolors; i++)
|
||||
{
|
||||
redcolormap[i] >>= 8;
|
||||
greencolormap[i] >>= 8;
|
||||
bluecolormap[i] >>= 8;
|
||||
}
|
||||
if ((image = gimp_image_new (cols, rows, image_type)) == -1) {
|
||||
g_error ("TIFF Can't allocate new image\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
gimp_image_set_filename (image, filename);
|
||||
|
||||
if (numcolors > 256)
|
||||
{
|
||||
image_type = RGB;
|
||||
layer_type = (alpha) ? RGBA_IMAGE : RGB_IMAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
image_type = INDEXED;
|
||||
layer_type = (alpha) ? INDEXEDA_IMAGE : INDEXED_IMAGE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_RGB:
|
||||
grayscale = 0;
|
||||
image_type = RGB;
|
||||
layer_type = (alpha) ? RGBA_IMAGE : RGB_IMAGE;
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MASK:
|
||||
g_print ("don't know how to handle PHOTOMETRIC_MASK\n");
|
||||
gimp_quit ();
|
||||
|
||||
default:
|
||||
g_print ("unknown photometric: %d\n", photomet);
|
||||
gimp_quit ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
image_ID = gimp_image_new (cols, rows, image_type);
|
||||
if (image_ID == -1)
|
||||
{
|
||||
g_print ("can't allocate new image\n");
|
||||
/* Install colormap for INDEXED images only */
|
||||
if (image_type == INDEXED) {
|
||||
if (!TIFFGetField (tif, TIFFTAG_COLORMAP, &redmap, &greenmap, &bluemap)) {
|
||||
g_error ("TIFF Can't get colormaps\n");
|
||||
gimp_quit ();
|
||||
}
|
||||
gimp_image_set_filename (image_ID, filename);
|
||||
|
||||
if ((image_type == INDEXED) && (numcolors <= 256))
|
||||
{
|
||||
guchar *cmap;
|
||||
gint i, j;
|
||||
|
||||
cmap = g_new (guchar, numcolors * 3);
|
||||
for (i = 0, j = 0; i < numcolors; i++)
|
||||
{
|
||||
cmap[j++] = redcolormap[i];
|
||||
cmap[j++] = greencolormap[i];
|
||||
cmap[j++] = bluecolormap[i];
|
||||
}
|
||||
|
||||
gimp_image_set_cmap (image_ID, cmap, numcolors);
|
||||
g_free (cmap);
|
||||
for (i = 0, j = 0; i <= maxval; i++) {
|
||||
cmap[j++] = redmap[i] >> 8;
|
||||
cmap[j++] = greenmap[i] >> 8;
|
||||
cmap[j++] = bluemap[i] >> 8;
|
||||
}
|
||||
gimp_image_set_cmap (image, cmap, maxval + 1);
|
||||
}
|
||||
|
||||
layer_ID = gimp_layer_new (image_ID, "Background",
|
||||
cols, rows, layer_type,
|
||||
layer = gimp_layer_new (image, "Background", cols, rows, layer_type,
|
||||
100, NORMAL_MODE);
|
||||
gimp_image_add_layer (image_ID, layer_ID, 0);
|
||||
|
||||
buf = g_new (guchar, TIFFScanlineSize (tif));
|
||||
|
||||
drawable = gimp_drawable_get (layer_ID);
|
||||
gimp_image_add_layer (image, layer, 0);
|
||||
drawable = gimp_drawable_get (layer);
|
||||
|
||||
source= g_new (guchar, TIFFScanlineSize (tif));
|
||||
tile_height = gimp_tile_height ();
|
||||
dest = g_new (guchar, tile_height * cols * drawable->bpp);
|
||||
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, cols, rows, TRUE, FALSE);
|
||||
|
||||
if (num_extra - alpha > 0)
|
||||
channel = g_new (channel_data, num_extra - alpha);
|
||||
if (extra - alpha > 0)
|
||||
channel = g_new (channel_data, extra - alpha);
|
||||
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
channel[k].ID= gimp_channel_new(image_ID, "TIFF Channel", cols, rows,
|
||||
100.0, colors);
|
||||
gimp_image_add_channel(image_ID, channel[k].ID, 0);
|
||||
channel[k].drawable= gimp_drawable_get (channel[k].ID);
|
||||
channel[k].pixels= g_new(guchar, tile_height * cols);
|
||||
/* Add alpha channels as appropriate */
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
channel[i].ID= gimp_channel_new(image, "TIFF Channel", cols, rows,
|
||||
100.0, colors);
|
||||
gimp_image_add_channel(image, channel[i].ID, 0);
|
||||
channel[i].drawable= gimp_drawable_get (channel[i].ID);
|
||||
channel[i].pixels= g_new(guchar, tile_height * cols);
|
||||
|
||||
gimp_pixel_rgn_init (&(channel[k].pixel_rgn), channel[k].drawable, 0, 0,
|
||||
gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable, 0, 0,
|
||||
cols, rows, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#define NEXTSAMPLE \
|
||||
/* Step through all <= 8-bit samples in an image */
|
||||
|
||||
#define NEXTSAMPLE(var) \
|
||||
{ \
|
||||
if ( bitsleft == 0 ) \
|
||||
if (bitsleft == 0) \
|
||||
{ \
|
||||
s++; \
|
||||
bitsleft = 8; \
|
||||
} \
|
||||
bitsleft -= bps; \
|
||||
sample = ( *s >> bitsleft ) & maxval; \
|
||||
var = ( *s >> bitsleft ) & maxval; \
|
||||
}
|
||||
|
||||
for (y = 0; y < rows; y = yend)
|
||||
{
|
||||
yend = y + tile_height;
|
||||
yend = MIN (yend, rows);
|
||||
for (start= 0, row = 0; row < rows; ++row) {
|
||||
d= dest + cols * (row % tile_height) * drawable->bpp;
|
||||
|
||||
for (row = y; row < yend; row++)
|
||||
{
|
||||
if (TIFFReadScanline (tif, buf, row, 0) < 0)
|
||||
{
|
||||
g_print ("bad data read on line %d\n", row);
|
||||
gimp_quit ();
|
||||
/* Special cases: Scanline is compatible with GIMP storage */
|
||||
if (extra == 0 && bps == 8) {
|
||||
if (TIFFReadScanline (tif, d, row, 0) < 0) {
|
||||
g_error ("TIFF Bad data read on line %d\n", row);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
/* Or read in and process each sample -- slower */
|
||||
} else {
|
||||
if (TIFFReadScanline (tif, source, row, 0) < 0) {
|
||||
g_error ("TIFF Bad data read on line %d\n", row);
|
||||
gimp_quit ();
|
||||
}
|
||||
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
channel[i].pixel= channel[i].pixels + cols * (row % tile_height);
|
||||
}
|
||||
|
||||
/* Set s/bitleft ready to use NEXTSAMPLE macro */
|
||||
|
||||
s= source;
|
||||
bitsleft= 8;
|
||||
|
||||
switch (photomet) {
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(gray_val);
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(alpha_val);
|
||||
if (alpha_val)
|
||||
*d++ = (gray_val * 65025) / (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
} else {
|
||||
*d++ = (gray_val * 255) / maxval;
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(gray_val);
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(alpha_val);
|
||||
if (alpha_val)
|
||||
*d++ = ((maxval - gray_val) * 65025) / (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
} else {
|
||||
*d++ = ((maxval - gray_val) * 255) / maxval;
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(*d++);
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(*d++);
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_RGB:
|
||||
for (col = 0; col < cols; col++) {
|
||||
NEXTSAMPLE(red_val)
|
||||
NEXTSAMPLE(green_val)
|
||||
NEXTSAMPLE(blue_val)
|
||||
if (alpha) {
|
||||
NEXTSAMPLE(alpha_val)
|
||||
if (alpha_val) {
|
||||
*d++ = (red_val * 255) / alpha_val;
|
||||
*d++ = (green_val * 255) / alpha_val;
|
||||
*d++ = (blue_val * 255) / alpha_val;
|
||||
} else {
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
}
|
||||
*d++ = alpha_val;
|
||||
} else {
|
||||
*d++ = red_val;
|
||||
*d++ = green_val;
|
||||
*d++ = blue_val;
|
||||
}
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
NEXTSAMPLE(sample);
|
||||
*channel[i].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
bitsleft = 8;
|
||||
s = buf;
|
||||
d = dest + cols * (row - y) * drawable->bpp;
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
channel[k].pixel= channel[k].pixels + cols * (row - y);
|
||||
|
||||
switch (photomet)
|
||||
{
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
gray_val = sample;
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
*d++ = (gray_val * 65025) / (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
*d++ = (gray_val * 255) / maxval;
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
gray_val = sample;
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
*d++ = ((maxval - gray_val) * 65025)
|
||||
/ (alpha_val * maxval);
|
||||
else
|
||||
*d++ = 0;
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
*d++ = ((maxval - gray_val) * 255) / maxval ;
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_PALETTE:
|
||||
if (numcolors > 256)
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
red_val = redcolormap[sample];
|
||||
green_val = greencolormap[sample];
|
||||
blue_val = bluecolormap[sample];
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
{
|
||||
*d++ = (red_val * 255) / alpha_val;
|
||||
*d++ = (green_val * 255) / alpha_val;
|
||||
*d++ = (blue_val * 255) / alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
}
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = red_val;
|
||||
*d++ = green_val;
|
||||
*d++ = blue_val;
|
||||
}
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
if (alpha)
|
||||
{
|
||||
*d++ = sample;
|
||||
NEXTSAMPLE;
|
||||
*d++ = sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = sample;
|
||||
}
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PHOTOMETRIC_RGB:
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
red_val = sample;
|
||||
NEXTSAMPLE;
|
||||
green_val = sample;
|
||||
NEXTSAMPLE;
|
||||
blue_val = sample;
|
||||
if (alpha)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
alpha_val = sample;
|
||||
if (alpha_val)
|
||||
{
|
||||
*d++ = (red_val * 255) / alpha_val;
|
||||
*d++ = (green_val * 255) / alpha_val;
|
||||
*d++ = (blue_val * 255) / alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
*d++ = 0;
|
||||
}
|
||||
*d++ = alpha_val;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d++ = red_val;
|
||||
*d++ = green_val;
|
||||
*d++ = blue_val;
|
||||
}
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
{
|
||||
NEXTSAMPLE;
|
||||
*channel[k].pixel++ = sample;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_print ("unknown photometric: %d\n", photomet);
|
||||
gimp_quit ();
|
||||
}
|
||||
}
|
||||
|
||||
gimp_pixel_rgn_set_rect (&pixel_rgn, dest, 0, y, cols, yend - y);
|
||||
for (k= 0; alpha + k < num_extra; ++k)
|
||||
gimp_pixel_rgn_set_rect(&(channel[k].pixel_rgn),
|
||||
channel[k].pixels, 0, y, cols, yend -y);
|
||||
gimp_progress_update ((double) row / (double) rows);
|
||||
default:
|
||||
/* This case was handled earlier */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (((row + 1) % tile_height) == 0 || row + 1 == rows) {
|
||||
gimp_pixel_rgn_set_rect (&pixel_rgn, dest, 0, start, cols, 1+row-start);
|
||||
for (i= 0; alpha + i < extra; ++i) {
|
||||
gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
|
||||
0, start, cols, 1+row-start);
|
||||
}
|
||||
gimp_progress_update ((double) row / (double) rows);
|
||||
start= row + 1;
|
||||
}
|
||||
}
|
||||
|
||||
gimp_drawable_flush (drawable);
|
||||
gimp_drawable_detach (drawable);
|
||||
|
||||
return image_ID;
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -669,11 +566,7 @@ load_image (char *filename)
|
|||
** other special, indirect and consequential damages.
|
||||
*/
|
||||
|
||||
static gint
|
||||
save_image (char *filename,
|
||||
gint32 image_ID,
|
||||
gint32 drawable_ID)
|
||||
{
|
||||
static gint save_image (char *filename, gint32 image, gint32 layer) {
|
||||
TIFF *tif;
|
||||
unsigned short red[256];
|
||||
unsigned short grn[256];
|
||||
|
@ -720,8 +613,8 @@ save_image (char *filename,
|
|||
gimp_progress_init (name);
|
||||
free (name);
|
||||
|
||||
drawable = gimp_drawable_get (drawable_ID);
|
||||
drawable_type = gimp_drawable_type (drawable_ID);
|
||||
drawable = gimp_drawable_get (layer);
|
||||
drawable_type = gimp_drawable_type (layer);
|
||||
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
||||
|
||||
cols = drawable->width;
|
||||
|
@ -764,7 +657,7 @@ save_image (char *filename,
|
|||
bytesperrow = cols;
|
||||
alpha = 0;
|
||||
|
||||
cmap = gimp_image_get_cmap (image_ID, &colors);
|
||||
cmap = gimp_image_get_cmap (image, &colors);
|
||||
|
||||
for (i = 0; i < colors; i++)
|
||||
{
|
||||
|
@ -798,13 +691,13 @@ save_image (char *filename,
|
|||
TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField (tif, TIFFTAG_FILLORDER, fillorder);
|
||||
TIFFSetField (tif, TIFFTAG_DOCUMENTNAME, filename);
|
||||
TIFFSetField (tif, TIFFTAG_IMAGEDESCRIPTION, "created with The GIMP");
|
||||
TIFFSetField (tif, TIFFTAG_IMAGEDESCRIPTION, "Created with The GIMP");
|
||||
TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
|
||||
TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
/* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, rows / rowsperstrip ); */
|
||||
TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
|
||||
if (gimp_drawable_type (drawable_ID) == INDEXED_IMAGE)
|
||||
if (drawable_type == INDEXED_IMAGE)
|
||||
TIFFSetField (tif, TIFFTAG_COLORMAP, red, grn, blu);
|
||||
|
||||
/* array to rearrange data */
|
||||
|
|
Loading…
Reference in New Issue