Blame src/gd_tiff.c

Packit ed3af9
/*
Packit ed3af9
   TIFF - Tagged Image File Format Encapsulation for GD Library
Packit ed3af9
Packit ed3af9
   gd_tiff.c
Packit ed3af9
   Copyright (C) Pierre-A. Joye, M. Retallack
Packit ed3af9
Packit ed3af9
   ---------------------------------------------------------------------------
Packit ed3af9
   **
Packit ed3af9
   ** Permission to use, copy, modify, and distribute this software and its
Packit ed3af9
   ** documentation for any purpose and without fee is hereby granted, provided
Packit ed3af9
   ** that the above copyright notice appear in all copies and that both that
Packit ed3af9
   ** copyright notice and this permission notice appear in supporting
Packit ed3af9
   ** documentation.  This software is provided "as is" without express or
Packit ed3af9
   ** implied warranty.
Packit ed3af9
   **
Packit ed3af9
   ---------------------------------------------------------------------------
Packit ed3af9
   Ctx code written by M. Retallack
Packit ed3af9
Packit ed3af9
   Todo:
Packit ed3af9
Packit ed3af9
   If we fail - cleanup
Packit ed3af9
   Writer: Use gd error function, overflow check may not be necessary as
Packit ed3af9
	 we write our own data (check already done)
Packit ed3af9
Packit ed3af9
   Implement 2 color black/white saving using group4 fax compression
Packit ed3af9
   Implement function to specify encoding to use when writing tiff data
Packit ed3af9
Packit ed3af9
   ----------------------------------------------------------------------------
Packit ed3af9
 */
Packit ed3af9
/* $Id$ */
Packit ed3af9
Packit ed3af9
/**
Packit ed3af9
 * File: TIFF IO
Packit ed3af9
 *
Packit ed3af9
 * Read and write TIFF images.
Packit ed3af9
 *
Packit ed3af9
 * There is only most basic support for the TIFF format available for now;
Packit ed3af9
 * for instance, multiple pages are not yet supported.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#ifdef HAVE_CONFIG_H
Packit ed3af9
#	include "config.h"
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#include "gd.h"
Packit ed3af9
#include "gd_errors.h"
Packit ed3af9
#include "gdfonts.h"
Packit ed3af9
#include <stdio.h>
Packit ed3af9
#include <stdlib.h>
Packit ed3af9
#include <limits.h>
Packit ed3af9
Packit ed3af9
#include "gdhelpers.h"
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBTIFF
Packit ed3af9
Packit ed3af9
#include "tiff.h"
Packit ed3af9
#include "tiffio.h"
Packit ed3af9
Packit ed3af9
#define GD_SUCCESS 1
Packit ed3af9
#define GD_FAILURE 0
Packit ed3af9
Packit ed3af9
#define TRUE 1
Packit ed3af9
#define FALSE 0
Packit ed3af9
Packit ed3af9
/* I define those here until the new formats
Packit ed3af9
 * are commited. We can then rely on the global
Packit ed3af9
 * def
Packit ed3af9
 */
Packit ed3af9
#define GD_PALETTE 1
Packit ed3af9
#define GD_TRUECOLOR 2
Packit ed3af9
#define GD_GRAY 3
Packit ed3af9
#define GD_INDEXED 4
Packit ed3af9
#define GD_RGB 5
Packit ed3af9
Packit ed3af9
#define MIN(a,b) (a < b) ? a : b;
Packit ed3af9
#define MAX(a,b) (a > b) ? a : b;
Packit ed3af9
Packit ed3af9
Packit ed3af9
typedef struct tiff_handle {
Packit ed3af9
	int size;
Packit ed3af9
	int pos;
Packit ed3af9
	gdIOCtx *ctx;
Packit ed3af9
	int written;
Packit ed3af9
}
Packit ed3af9
tiff_handle;
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
   Functions for reading, writing and seeking in gdIOCtx
Packit ed3af9
   This allows for non-file i/o operations with no
Packit ed3af9
   explicit use of libtiff fileio wrapper functions
Packit ed3af9
Packit ed3af9
   Note: because libtiff requires random access, but gdIOCtx
Packit ed3af9
         only supports streams, all writes are buffered
Packit ed3af9
         into memory and written out on close, also all
Packit ed3af9
         reads are done from a memory mapped version of the
Packit ed3af9
         tiff (assuming one already exists)
Packit ed3af9
*/
Packit ed3af9
Packit ed3af9
tiff_handle * new_tiff_handle(gdIOCtx *g)
Packit ed3af9
{
Packit ed3af9
	tiff_handle * t;
Packit ed3af9
Packit ed3af9
	if (!g) {
Packit ed3af9
		gd_error("Cannot create a new tiff handle, missing Ctx argument");
Packit ed3af9
		return NULL;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	t = (tiff_handle *) gdMalloc(sizeof(tiff_handle));
Packit ed3af9
	if (!t) {
Packit ed3af9
		gd_error("Failed to allocate a new tiff handle");
Packit ed3af9
		return NULL;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	t->size = 0;
Packit ed3af9
	t->pos = 0;
Packit ed3af9
	t->ctx = g;
Packit ed3af9
	t->written = 0;
Packit ed3af9
Packit ed3af9
	return t;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* TIFFReadWriteProc tiff_readproc - Will use gdIOCtx procs to read required
Packit ed3af9
   (previously written) TIFF file content */
Packit ed3af9
static tsize_t tiff_readproc(thandle_t clientdata, tdata_t data, tsize_t size)
Packit ed3af9
{
Packit ed3af9
	tiff_handle *th = (tiff_handle *)clientdata;
Packit ed3af9
	gdIOCtx *ctx = th->ctx;
Packit ed3af9
Packit ed3af9
	size = (ctx->getBuf)(ctx, data, size);
Packit ed3af9
Packit ed3af9
	return size;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* TIFFReadWriteProc tiff_writeproc - Will use gdIOCtx procs to write out
Packit ed3af9
   TIFF data */
Packit ed3af9
static tsize_t tiff_writeproc(thandle_t clientdata, tdata_t data, tsize_t size)
Packit ed3af9
{
Packit ed3af9
	tiff_handle *th = (tiff_handle *)clientdata;
Packit ed3af9
	gdIOCtx *ctx = th->ctx;
Packit ed3af9
Packit ed3af9
	size = (ctx->putBuf)(ctx, data, size);
Packit ed3af9
	if(size + th->pos>th->size) {
Packit ed3af9
		th->size = size + th->pos;
Packit ed3af9
		th->pos += size;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	return size;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* TIFFSeekProc tiff_seekproc
Packit ed3af9
 * used to move around the partially written TIFF */
Packit ed3af9
static toff_t tiff_seekproc(thandle_t clientdata, toff_t offset, int from)
Packit ed3af9
{
Packit ed3af9
	tiff_handle *th = (tiff_handle *)clientdata;
Packit ed3af9
	gdIOCtx *ctx = th->ctx;
Packit ed3af9
	int result;
Packit ed3af9
Packit ed3af9
	switch(from) {
Packit ed3af9
	default:
Packit ed3af9
	case SEEK_SET:
Packit ed3af9
		/* just use offset */
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	case SEEK_END:
Packit ed3af9
		/* invert offset, so that it is from start, not end as supplied */
Packit ed3af9
		offset = th->size + offset;
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	case SEEK_CUR:
Packit ed3af9
		/* add current position to translate it to 'from start',
Packit ed3af9
		 * not from durrent as supplied
Packit ed3af9
		 */
Packit ed3af9
		offset += th->pos;
Packit ed3af9
		break;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* now, move pos in both io context and buf */
Packit ed3af9
	if((result = (ctx->seek)(ctx, offset))) {
Packit ed3af9
		th->pos = offset;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	return result ? offset : (toff_t)-1;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* TIFFCloseProc tiff_closeproc - used to finally close the TIFF file */
Packit ed3af9
static int tiff_closeproc(thandle_t clientdata)
Packit ed3af9
{
Packit ed3af9
	(void)clientdata;
Packit ed3af9
	/*tiff_handle *th = (tiff_handle *)clientdata;
Packit ed3af9
	gdIOCtx *ctx = th->ctx;
Packit ed3af9
Packit ed3af9
	(ctx->gd_free)(ctx);*/
Packit ed3af9
Packit ed3af9
	return 0;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* TIFFSizeProc tiff_sizeproc */
Packit ed3af9
static toff_t tiff_sizeproc(thandle_t clientdata)
Packit ed3af9
{
Packit ed3af9
	tiff_handle *th = (tiff_handle *)clientdata;
Packit ed3af9
	return th->size;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* TIFFMapFileProc tiff_mapproc() */
Packit ed3af9
static int tiff_mapproc(thandle_t h, tdata_t *d, toff_t *o)
Packit ed3af9
{
Packit ed3af9
	(void)h;
Packit ed3af9
	(void)d;
Packit ed3af9
	(void)o;
Packit ed3af9
	return 0;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* TIFFUnmapFileProc tiff_unmapproc */
Packit ed3af9
static void tiff_unmapproc(thandle_t h, tdata_t d, toff_t o)
Packit ed3af9
{
Packit ed3af9
	(void)h;
Packit ed3af9
	(void)d;
Packit ed3af9
	(void)o;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*  tiffWriter
Packit ed3af9
 *  ----------
Packit ed3af9
 *  Write the gd image as a tiff file (called by gdImageTiffCtx)
Packit ed3af9
 *  Parameters are:
Packit ed3af9
 *  image:    gd image structure;
Packit ed3af9
 *  out:      the stream where to write
Packit ed3af9
 *  bitDepth: depth in bits of each pixel
Packit ed3af9
 */
Packit ed3af9
void tiffWriter(gdImagePtr image, gdIOCtx *out, int bitDepth)
Packit ed3af9
{
Packit ed3af9
	int x, y;
Packit ed3af9
	int i;
Packit ed3af9
	int r, g, b, a;
Packit ed3af9
	TIFF *tiff;
Packit ed3af9
	int width, height;
Packit ed3af9
	int color;
Packit ed3af9
	char *scan;
Packit ed3af9
	int samplesPerPixel = 3;
Packit ed3af9
	int bitsPerSample;
Packit ed3af9
	int transparentColorR = -1;
Packit ed3af9
	int transparentColorG = -1;
Packit ed3af9
	int transparentColorB = -1;
Packit ed3af9
	uint16 extraSamples[1];
Packit ed3af9
	uint16 *colorMapRed = NULL;
Packit ed3af9
	uint16 *colorMapGreen = NULL;
Packit ed3af9
	uint16 *colorMapBlue = NULL;
Packit ed3af9
Packit ed3af9
	tiff_handle *th;
Packit ed3af9
Packit ed3af9
	th = new_tiff_handle(out);
Packit ed3af9
	if (!th) {
Packit ed3af9
		return;
Packit ed3af9
	}
Packit ed3af9
	extraSamples[0] = EXTRASAMPLE_ASSOCALPHA;
Packit ed3af9
Packit ed3af9
	/* read in the width/height of gd image */
Packit ed3af9
	width = gdImageSX(image);
Packit ed3af9
	height = gdImageSY(image);
Packit ed3af9
Packit ed3af9
	/* reset clip region to whole image */
Packit ed3af9
	gdImageSetClip(image, 0, 0, width, height);
Packit ed3af9
Packit ed3af9
	/* handle old-style single-colour mapping to 100% transparency */
Packit ed3af9
	if(image->transparent != -1) {
Packit ed3af9
		/* set our 100% transparent colour value */
Packit ed3af9
		transparentColorR = gdImageRed(image, image->transparent);
Packit ed3af9
		transparentColorG = gdImageGreen(image, image->transparent);
Packit ed3af9
		transparentColorB = gdImageBlue(image, image->transparent);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* Open tiff file writing routines, but use special read/write/seek
Packit ed3af9
	 * functions so that tiff lib writes correct bits of tiff content to
Packit ed3af9
	 * correct areas of file opened and modifieable by the gdIOCtx functions
Packit ed3af9
	 */
Packit ed3af9
	tiff = TIFFClientOpen("", "w", th,	tiff_readproc,
Packit ed3af9
			      tiff_writeproc,
Packit ed3af9
			      tiff_seekproc,
Packit ed3af9
			      tiff_closeproc,
Packit ed3af9
			      tiff_sizeproc,
Packit ed3af9
			      tiff_mapproc,
Packit ed3af9
			      tiff_unmapproc);
Packit ed3af9
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width);
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height);
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC,
Packit ed3af9
		     (bitDepth == 24) ? PHOTOMETRIC_RGB : PHOTOMETRIC_PALETTE);
Packit ed3af9
Packit ed3af9
	bitsPerSample = (bitDepth == 24 || bitDepth == 8) ? 8 : 1;
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
Packit ed3af9
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_XRESOLUTION, (float)image->res_x);
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_YRESOLUTION, (float)image->res_y);
Packit ed3af9
Packit ed3af9
	/* build the color map for 8 bit images */
Packit ed3af9
	if(bitDepth != 24) {
Packit ed3af9
		colorMapRed   = (uint16 *) gdMalloc(3 * (1 << bitsPerSample));
Packit ed3af9
		if (!colorMapRed) {
Packit ed3af9
			gdFree(th);
Packit ed3af9
			return;
Packit ed3af9
		}
Packit ed3af9
		colorMapGreen = (uint16 *) gdMalloc(3 * (1 << bitsPerSample));
Packit ed3af9
		if (!colorMapGreen) {
Packit ed3af9
			gdFree(colorMapRed);
Packit ed3af9
			gdFree(th);
Packit ed3af9
			return;
Packit ed3af9
		}
Packit ed3af9
		colorMapBlue  = (uint16 *) gdMalloc(3 *  (1 << bitsPerSample));
Packit ed3af9
		if (!colorMapBlue) {
Packit ed3af9
			gdFree(colorMapRed);
Packit ed3af9
			gdFree(colorMapGreen);
Packit ed3af9
			gdFree(th);
Packit ed3af9
			return;
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		for(i = 0; i < image->colorsTotal; i++) {
Packit ed3af9
			colorMapRed[i]   = gdImageRed(image,i) + (gdImageRed(image,i) * 256);
Packit ed3af9
			colorMapGreen[i] = gdImageGreen(image,i)+(gdImageGreen(image,i)*256);
Packit ed3af9
			colorMapBlue[i]  = gdImageBlue(image,i) + (gdImageBlue(image,i)*256);
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		TIFFSetField(tiff, TIFFTAG_COLORMAP, colorMapRed, colorMapGreen,
Packit ed3af9
			     colorMapBlue);
Packit ed3af9
		samplesPerPixel = 1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* here, we check if the 'save alpha' flag is set on the source gd image */
Packit ed3af9
	if ((bitDepth == 24) &&
Packit ed3af9
	    (image->saveAlphaFlag || image->transparent != -1)) {
Packit ed3af9
		/* so, we need to store the alpha values too!
Packit ed3af9
		 * Also, tell TIFF what the extra sample means (associated alpha) */
Packit ed3af9
		samplesPerPixel = 4;
Packit ed3af9
		TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel);
Packit ed3af9
		TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, extraSamples);
Packit ed3af9
	} else {
Packit ed3af9
		TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
Packit ed3af9
Packit ed3af9
	if(overflow2(width, samplesPerPixel)) {
Packit ed3af9
		if (colorMapRed)   gdFree(colorMapRed);
Packit ed3af9
		if (colorMapGreen) gdFree(colorMapGreen);
Packit ed3af9
		if (colorMapBlue)  gdFree(colorMapBlue);
Packit ed3af9
		gdFree(th);
Packit ed3af9
		return;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if(!(scan = (char *)gdMalloc(width * samplesPerPixel))) {
Packit ed3af9
		if (colorMapRed)   gdFree(colorMapRed);
Packit ed3af9
		if (colorMapGreen) gdFree(colorMapGreen);
Packit ed3af9
		if (colorMapBlue)  gdFree(colorMapBlue);
Packit ed3af9
		gdFree(th);
Packit ed3af9
		return;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* loop through y-coords, and x-coords */
Packit ed3af9
	for(y = 0; y < height; y++) {
Packit ed3af9
		for(x = 0; x < width; x++) {
Packit ed3af9
			/* generate scan line for writing to tiff */
Packit ed3af9
			color = gdImageGetPixel(image, x, y);
Packit ed3af9
Packit ed3af9
			a = (127 - gdImageAlpha(image, color)) * 2;
Packit ed3af9
			a = (a == 0xfe) ? 0xff : a & 0xff;
Packit ed3af9
			b = gdImageBlue(image, color);
Packit ed3af9
			g = gdImageGreen(image, color);
Packit ed3af9
			r = gdImageRed(image, color);
Packit ed3af9
Packit ed3af9
			/* if this pixel has the same RGB as the transparent colour,
Packit ed3af9
			 * then set alpha fully transparent */
Packit ed3af9
			if (transparentColorR == r &&
Packit ed3af9
			    transparentColorG == g &&
Packit ed3af9
			    transparentColorB == b) {
Packit ed3af9
				a = 0x00;
Packit ed3af9
			}
Packit ed3af9
Packit ed3af9
			if(bitDepth != 24) {
Packit ed3af9
				/* write out 1 or 8 bit value in 1 byte
Packit ed3af9
				 * (currently treats 1bit as 8bit) */
Packit ed3af9
				scan[(x * samplesPerPixel) + 0] = color;
Packit ed3af9
			} else {
Packit ed3af9
				/* write out 24 bit value in 3 (or 4 if transparent) bytes */
Packit ed3af9
				if(image->saveAlphaFlag || image->transparent != -1) {
Packit ed3af9
					scan[(x * samplesPerPixel) + 3] = a;
Packit ed3af9
				}
Packit ed3af9
Packit ed3af9
				scan[(x * samplesPerPixel) + 2] = b;
Packit ed3af9
				scan[(x * samplesPerPixel) + 1] = g;
Packit ed3af9
				scan[(x * samplesPerPixel) + 0] = r;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		/* Write the scan line to the tiff */
Packit ed3af9
		if(TIFFWriteEncodedStrip(tiff, y, scan, width * samplesPerPixel) == -1) {
Packit ed3af9
			if (colorMapRed)   gdFree(colorMapRed);
Packit ed3af9
			if (colorMapGreen) gdFree(colorMapGreen);
Packit ed3af9
			if (colorMapBlue)  gdFree(colorMapBlue);
Packit ed3af9
			gdFree(th);
Packit ed3af9
			/* error handler here */
Packit ed3af9
			gd_error("Could not create TIFF\n");
Packit ed3af9
			return;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* now cloase and free up resources */
Packit ed3af9
	TIFFClose(tiff);
Packit ed3af9
	gdFree(scan);
Packit ed3af9
	gdFree(th);
Packit ed3af9
Packit ed3af9
	if(bitDepth != 24) {
Packit ed3af9
		gdFree(colorMapRed);
Packit ed3af9
		gdFree(colorMapGreen);
Packit ed3af9
		gdFree(colorMapBlue);
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
	Function: gdImageTiffCtx
Packit ed3af9
Packit ed3af9
	Write the gd image as a tiff file.
Packit ed3af9
Packit ed3af9
	Parameters:
Packit ed3af9
Packit ed3af9
		image - gd image structure;
Packit ed3af9
		out   - the stream where to write
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(void) gdImageTiffCtx(gdImagePtr image, gdIOCtx *out)
Packit ed3af9
{
Packit ed3af9
	int clipx1P, clipy1P, clipx2P, clipy2P;
Packit ed3af9
	int bitDepth = 24;
Packit ed3af9
Packit ed3af9
	/* First, switch off clipping, or we'll not get all the image! */
Packit ed3af9
	gdImageGetClip(image, &clipx1P, &clipy1P, &clipx2P, &clipy2P);
Packit ed3af9
Packit ed3af9
	/* use the appropriate routine depending on the bit depth of the image */
Packit ed3af9
	if(image->trueColor) {
Packit ed3af9
		bitDepth = 24;
Packit ed3af9
	} else if(image->colorsTotal == 2) {
Packit ed3af9
		bitDepth = 1;
Packit ed3af9
	} else {
Packit ed3af9
		bitDepth = 8;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	tiffWriter(image, out, bitDepth);
Packit ed3af9
Packit ed3af9
	/* reset clipping area to the gd image's original values */
Packit ed3af9
	gdImageSetClip(image, clipx1P, clipy1P, clipx2P, clipy2P);
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* Check if we are really in 8bit mode */
Packit ed3af9
static int checkColorMap(n, r, g, b)
Packit ed3af9
int n;
Packit ed3af9
uint16 *r, *g, *b;
Packit ed3af9
{
Packit ed3af9
	while (n-- > 0)
Packit ed3af9
		if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
Packit ed3af9
			return (16);
Packit ed3af9
	return (8);
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
Packit ed3af9
/* Read and convert a TIFF colormap */
Packit ed3af9
static int readTiffColorMap(gdImagePtr im, TIFF *tif, char is_bw, int photometric)
Packit ed3af9
{
Packit ed3af9
	uint16 *redcmap, *greencmap, *bluecmap;
Packit ed3af9
	uint16 bps;
Packit ed3af9
	int i;
Packit ed3af9
Packit ed3af9
	if (is_bw) {
Packit ed3af9
		if (photometric == PHOTOMETRIC_MINISWHITE) {
Packit ed3af9
			gdImageColorAllocate(im, 255,255,255);
Packit ed3af9
			gdImageColorAllocate(im, 0, 0, 0);
Packit ed3af9
		} else {
Packit ed3af9
			gdImageColorAllocate(im, 0, 0, 0);
Packit ed3af9
			gdImageColorAllocate(im, 255,255,255);
Packit ed3af9
		}
Packit ed3af9
	} else {
Packit ed3af9
		uint16 min_sample_val, max_sample_val;
Packit ed3af9
Packit ed3af9
		if (!TIFFGetField(tif, TIFFTAG_MINSAMPLEVALUE, &min_sample_val)) {
Packit ed3af9
			min_sample_val = 0;
Packit ed3af9
		}
Packit ed3af9
		if (!TIFFGetField(tif, TIFFTAG_MAXSAMPLEVALUE, &max_sample_val)) {
Packit ed3af9
			max_sample_val = 255;
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) {
Packit ed3af9
			/* TODO: use TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE */
Packit ed3af9
			/* Gray level palette */
Packit ed3af9
			for (i=min_sample_val; i <= max_sample_val; i++) {
Packit ed3af9
				gdImageColorAllocate(im, i,i,i);
Packit ed3af9
			}
Packit ed3af9
			return GD_SUCCESS;
Packit ed3af9
Packit ed3af9
		} else if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &redcmap, &greencmap, &bluecmap)) {
Packit ed3af9
			gd_error("Cannot read the color map");
Packit ed3af9
			return GD_FAILURE;
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps;;
Packit ed3af9
Packit ed3af9
#define	CVT(x)		(((x) * 255) / ((1L<<16)-1))
Packit ed3af9
		if (checkColorMap(1<
Packit ed3af9
			for (i = (1<<bps)-1; i > 0; i--) {
Packit ed3af9
				redcmap[i] = CVT(redcmap[i]);
Packit ed3af9
				greencmap[i] = CVT(greencmap[i]);
Packit ed3af9
				bluecmap[i] = CVT(bluecmap[i]);
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		for (i = 0; i < 256; i++) {
Packit ed3af9
			gdImageColorAllocate(im, redcmap[i], greencmap[i], bluecmap[i]);
Packit ed3af9
		}
Packit ed3af9
#undef CVT
Packit ed3af9
	}
Packit ed3af9
	return GD_SUCCESS;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
static void readTiffBw (const unsigned char *src,
Packit ed3af9
			gdImagePtr im,
Packit ed3af9
			uint16       photometric,
Packit ed3af9
			int          startx,
Packit ed3af9
			int          starty,
Packit ed3af9
			int          width,
Packit ed3af9
			int          height,
Packit ed3af9
			char         has_alpha,
Packit ed3af9
			int          extra,
Packit ed3af9
			int          align)
Packit ed3af9
{
Packit ed3af9
	int x = startx, y = starty;
Packit ed3af9
Packit ed3af9
	(void)has_alpha;
Packit ed3af9
	(void)extra;
Packit ed3af9
	(void)align;
Packit ed3af9
Packit ed3af9
	for (y = starty; y < starty + height; y++) {
Packit ed3af9
		for (x = startx; x < startx + width;) {
Packit ed3af9
			register unsigned char curr = *src++;
Packit ed3af9
			register unsigned char mask;
Packit ed3af9
Packit ed3af9
			if (photometric == PHOTOMETRIC_MINISWHITE) {
Packit ed3af9
				curr = ~curr;
Packit ed3af9
			}
Packit ed3af9
			for (mask = 0x80; mask != 0 && x < startx + width; x++, mask >>= 1) {
Packit ed3af9
				gdImageSetPixel(im, x, y, ((curr & mask) != 0)?0:1);
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
static void readTiff8bit (const unsigned char *src,
Packit ed3af9
                          gdImagePtr im,
Packit ed3af9
                          uint16       photometric,
Packit ed3af9
                          int          startx,
Packit ed3af9
                          int          starty,
Packit ed3af9
                          int          width,
Packit ed3af9
                          int          height,
Packit ed3af9
                          char         has_alpha,
Packit ed3af9
                          int          extra,
Packit ed3af9
                          int          align)
Packit ed3af9
{
Packit ed3af9
	int    red, green, blue, alpha;
Packit ed3af9
	int    x, y;
Packit ed3af9
Packit ed3af9
	(void)extra;
Packit ed3af9
	(void)align;
Packit ed3af9
Packit ed3af9
	switch (photometric) {
Packit ed3af9
	case PHOTOMETRIC_PALETTE:
Packit ed3af9
		/* Palette has no alpha (see TIFF specs for more details */
Packit ed3af9
		for (y = starty; y < starty + height; y++) {
Packit ed3af9
			for (x = startx; x < startx + width; x++) {
Packit ed3af9
				gdImageSetPixel(im, x, y,*(src++));
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	case PHOTOMETRIC_RGB:
Packit ed3af9
		if (has_alpha) {
Packit ed3af9
			gdImageAlphaBlending(im, 0);
Packit ed3af9
			gdImageSaveAlpha(im, 1);
Packit ed3af9
Packit ed3af9
			for (y = starty; y < starty + height; y++) {
Packit ed3af9
				for (x = startx; x < startx + width; x++) {
Packit ed3af9
					red   = *src++;
Packit ed3af9
					green = *src++;
Packit ed3af9
					blue  = *src++;
Packit ed3af9
					alpha = *src++;
Packit ed3af9
					red   = MIN (red, alpha);
Packit ed3af9
					blue  = MIN (blue, alpha);
Packit ed3af9
					green = MIN (green, alpha);
Packit ed3af9
Packit ed3af9
					if (alpha) {
Packit ed3af9
						gdImageSetPixel(im, x, y, gdTrueColorAlpha(red * 255 / alpha, green * 255 / alpha, blue * 255 /alpha, gdAlphaMax - (alpha >> 1)));
Packit ed3af9
					} else {
Packit ed3af9
						gdImageSetPixel(im, x, y, gdTrueColorAlpha(red, green, blue, gdAlphaMax - (alpha >> 1)));
Packit ed3af9
					}
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
Packit ed3af9
		} else {
Packit ed3af9
			for (y = 0; y < height; y++) {
Packit ed3af9
				for (x = 0; x < width; x++) {
Packit ed3af9
					register unsigned char r = *src++;
Packit ed3af9
					register unsigned char g = *src++;
Packit ed3af9
					register unsigned char b = *src++;
Packit ed3af9
Packit ed3af9
					gdImageSetPixel(im, x, y, gdTrueColor(r, g, b));
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	case PHOTOMETRIC_MINISWHITE:
Packit ed3af9
		if (has_alpha) {
Packit ed3af9
			/* We don't process the extra yet */
Packit ed3af9
		} else {
Packit ed3af9
			for (y = starty; y < starty + height; y++) {
Packit ed3af9
				for (x = startx; x < startx + width; x++) {
Packit ed3af9
					gdImageSetPixel(im, x, y, ~(*src++));
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	case PHOTOMETRIC_MINISBLACK:
Packit ed3af9
		if (has_alpha) {
Packit ed3af9
			/* We don't process the extra yet */
Packit ed3af9
		} else {
Packit ed3af9
			for (y = starty; y < height; y++) {
Packit ed3af9
				for (x = 0; x < width; x++) {
Packit ed3af9
					gdImageSetPixel(im, x, y, *src++);
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		break;
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
static int createFromTiffTiles(TIFF *tif, gdImagePtr im, uint16 bps, uint16 photometric,
Packit ed3af9
                               char has_alpha, char is_bw, int extra)
Packit ed3af9
{
Packit ed3af9
	uint16  planar;
Packit ed3af9
	int im_width, im_height;
Packit ed3af9
	int tile_width, tile_height;
Packit ed3af9
	int  x, y, height, width;
Packit ed3af9
	unsigned char *buffer;
Packit ed3af9
	int success = GD_SUCCESS;
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar)) {
Packit ed3af9
		planar = PLANARCONFIG_CONTIG;
Packit ed3af9
	}
Packit ed3af9
	if (TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &im_width) == 0 ||
Packit ed3af9
		TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &im_height) == 0 ||
Packit ed3af9
		TIFFGetField (tif, TIFFTAG_TILEWIDTH, &tile_width) ==  0 ||
Packit ed3af9
		TIFFGetField (tif, TIFFTAG_TILELENGTH, &tile_height) == 0) {
Packit ed3af9
		return FALSE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	buffer = (unsigned char *) gdMalloc (TIFFTileSize (tif));
Packit ed3af9
	if (!buffer) {
Packit ed3af9
		return FALSE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	for (y = 0; y < im_height; y += tile_height) {
Packit ed3af9
		for (x = 0; x < im_width; x += tile_width) {
Packit ed3af9
			if (TIFFReadTile(tif, buffer, x, y, 0, 0) < 0) {
Packit ed3af9
				success = GD_FAILURE;
Packit ed3af9
				goto end;
Packit ed3af9
			}
Packit ed3af9
			width = MIN(im_width - x, tile_width);
Packit ed3af9
			height = MIN(im_height - y, tile_height);
Packit ed3af9
			if (bps == 16) {
Packit ed3af9
			} else if (bps == 8) {
Packit ed3af9
				readTiff8bit(buffer, im, photometric, x, y, width, height, has_alpha, extra, 0);
Packit ed3af9
			} else if (is_bw) {
Packit ed3af9
				readTiffBw(buffer, im, photometric, x, y, width, height, has_alpha, extra, 0);
Packit ed3af9
			} else {
Packit ed3af9
				/* TODO: implement some default reader or detect this case earlier use force_rgb */
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
end:
Packit ed3af9
	gdFree(buffer);
Packit ed3af9
	return success;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
static int createFromTiffLines(TIFF *tif, gdImagePtr im, uint16 bps, uint16 photometric,
Packit ed3af9
                               char has_alpha, char is_bw, int extra)
Packit ed3af9
{
Packit ed3af9
	uint16  planar;
Packit ed3af9
	uint32 im_height, im_width, y;
Packit ed3af9
Packit ed3af9
	unsigned char *buffer;
Packit ed3af9
	int success = GD_SUCCESS;
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar)) {
Packit ed3af9
		planar = PLANARCONFIG_CONTIG;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &im_height)) {
Packit ed3af9
		gd_error("Can't fetch TIFF height\n");
Packit ed3af9
		return FALSE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &im_width)) {
Packit ed3af9
		gd_error("Can't fetch TIFF width \n");
Packit ed3af9
		return FALSE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	buffer = (unsigned char *)gdMalloc(im_width * 4);
Packit ed3af9
	if (!buffer) {
Packit ed3af9
		return GD_FAILURE;
Packit ed3af9
	}
Packit ed3af9
	if (planar == PLANARCONFIG_CONTIG) {
Packit ed3af9
		switch (bps) {
Packit ed3af9
		case 16:
Packit ed3af9
			/* TODO
Packit ed3af9
			 * or simply use force_rgba
Packit ed3af9
			 */
Packit ed3af9
			break;
Packit ed3af9
Packit ed3af9
		case 8:
Packit ed3af9
			for (y = 0; y < im_height; y++ ) {
Packit ed3af9
				if (TIFFReadScanline (tif, buffer, y, 0) < 0) {
Packit ed3af9
					gd_error("Error while reading scanline %i", y);
Packit ed3af9
					success = GD_FAILURE;
Packit ed3af9
					break;
Packit ed3af9
				}
Packit ed3af9
				/* reading one line at a time */
Packit ed3af9
				readTiff8bit(buffer, im, photometric, 0, y, im_width, 1, has_alpha, extra, 0);
Packit ed3af9
			}
Packit ed3af9
			break;
Packit ed3af9
Packit ed3af9
		default:
Packit ed3af9
			if (is_bw) {
Packit ed3af9
				for (y = 0; y < im_height; y++ ) {
Packit ed3af9
					if (TIFFReadScanline (tif, buffer, y, 0) < 0) {
Packit ed3af9
						gd_error("Error while reading scanline %i", y);
Packit ed3af9
						success = GD_FAILURE;
Packit ed3af9
						break;
Packit ed3af9
					}
Packit ed3af9
					/* reading one line at a time */
Packit ed3af9
					readTiffBw(buffer, im, photometric, 0, y, im_width, 1, has_alpha, extra, 0);
Packit ed3af9
				}
Packit ed3af9
			} else {
Packit ed3af9
				/* TODO: implement some default reader or detect this case earlier > force_rgb */
Packit ed3af9
			}
Packit ed3af9
			break;
Packit ed3af9
		}
Packit ed3af9
	} else {
Packit ed3af9
		/* TODO: implement a reader for separate panes. We detect this case earlier for now and use force_rgb */
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	gdFree(buffer);
Packit ed3af9
	return success;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
static int createFromTiffRgba(TIFF * tif, gdImagePtr im)
Packit ed3af9
{
Packit ed3af9
	int a;
Packit ed3af9
	int x, y;
Packit ed3af9
	int alphaBlendingFlag = 0;
Packit ed3af9
	int color;
Packit ed3af9
	int width = im->sx;
Packit ed3af9
	int height = im->sy;
Packit ed3af9
	uint32 *buffer;
Packit ed3af9
	uint32 rgba;
Packit ed3af9
	int success;
Packit ed3af9
Packit ed3af9
	buffer = (uint32 *) gdCalloc(sizeof(uint32), width * height);
Packit ed3af9
	if (!buffer) {
Packit ed3af9
		return GD_FAILURE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* switch off colour merging on target gd image just while we write out
Packit ed3af9
	 * content - we want to preserve the alpha data until the user chooses
Packit ed3af9
	 * what to do with the image */
Packit ed3af9
	alphaBlendingFlag = im->alphaBlendingFlag;
Packit ed3af9
	gdImageAlphaBlending(im, 0);
Packit ed3af9
Packit ed3af9
	success = TIFFReadRGBAImage(tif, width, height, buffer, 1);
Packit ed3af9
Packit ed3af9
	if (success) {
Packit ed3af9
		for(y = 0; y < height; y++) {
Packit ed3af9
			for(x = 0; x < width; x++) {
Packit ed3af9
				/* if it doesn't already exist, allocate a new colour,
Packit ed3af9
				 * else use existing one */
Packit ed3af9
				rgba = buffer[(y * width + x)];
Packit ed3af9
				a = (0xff - TIFFGetA(rgba)) / 2;
Packit ed3af9
				color = gdTrueColorAlpha(TIFFGetR(rgba), TIFFGetG(rgba), TIFFGetB(rgba), a);
Packit ed3af9
	
Packit ed3af9
				/* set pixel colour to this colour */
Packit ed3af9
				gdImageSetPixel(im, x, height - y - 1, color);
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	gdFree(buffer);
Packit ed3af9
Packit ed3af9
	/* now reset colour merge for alpha blending routines */
Packit ed3af9
	gdImageAlphaBlending(im, alphaBlendingFlag);
Packit ed3af9
	return success;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
	Function: gdImageCreateFromTiffCtx
Packit ed3af9
Packit ed3af9
	Create a gdImage from a TIFF file input from an gdIOCtx.
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(gdImagePtr) gdImageCreateFromTiffCtx(gdIOCtx *infile)
Packit ed3af9
{
Packit ed3af9
	TIFF *tif;
Packit ed3af9
	tiff_handle *th;
Packit ed3af9
Packit ed3af9
	uint16 bps, spp, photometric;
Packit ed3af9
	uint16 orientation;
Packit ed3af9
	int width, height;
Packit ed3af9
	uint16 extra, *extra_types;
Packit ed3af9
	uint16 planar;
Packit ed3af9
	char	has_alpha, is_bw, is_gray;
Packit ed3af9
	char	force_rgba = FALSE;
Packit ed3af9
	char	save_transparent;
Packit ed3af9
	int		image_type;
Packit ed3af9
	int   ret;
Packit ed3af9
	float res_float;
Packit ed3af9
Packit ed3af9
	gdImagePtr im = NULL;
Packit ed3af9
Packit ed3af9
	th = new_tiff_handle(infile);
Packit ed3af9
	if (!th) {
Packit ed3af9
		return NULL;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	tif = TIFFClientOpen("", "rb", th, tiff_readproc,
Packit ed3af9
	                     tiff_writeproc,
Packit ed3af9
	                     tiff_seekproc,
Packit ed3af9
	                     tiff_closeproc,
Packit ed3af9
	                     tiff_sizeproc,
Packit ed3af9
	                     tiff_mapproc,
Packit ed3af9
	                     tiff_unmapproc);
Packit ed3af9
Packit ed3af9
	if (!tif) {
Packit ed3af9
		gd_error("Cannot open TIFF image");
Packit ed3af9
		gdFree(th);
Packit ed3af9
		return NULL;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width)) {
Packit ed3af9
		gd_error("TIFF error, Cannot read image width");
Packit ed3af9
		goto error;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height)) {
Packit ed3af9
		gd_error("TIFF error, Cannot read image width");
Packit ed3af9
		goto error;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, &bps;;
Packit ed3af9
Packit ed3af9
	/* Unsupported bps, force to RGBA */
Packit ed3af9
	if (bps != 1 /*bps > 8 && bps != 16*/) {
Packit ed3af9
		force_rgba = TRUE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &spp;;
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types)) {
Packit ed3af9
		extra = 0;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
Packit ed3af9
		uint16 compression;
Packit ed3af9
		if (TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression) &&
Packit ed3af9
		        (compression == COMPRESSION_CCITTFAX3 ||
Packit ed3af9
		         compression == COMPRESSION_CCITTFAX4 ||
Packit ed3af9
		         compression == COMPRESSION_CCITTRLE ||
Packit ed3af9
		         compression == COMPRESSION_CCITTRLEW)) {
Packit ed3af9
			gd_error("Could not get photometric. "
Packit ed3af9
			        "Image is CCITT compressed, assuming min-is-white");
Packit ed3af9
			photometric = PHOTOMETRIC_MINISWHITE;
Packit ed3af9
		} else {
Packit ed3af9
			gd_error("Could not get photometric. "
Packit ed3af9
			        "Assuming min-is-black");
Packit ed3af9
Packit ed3af9
			photometric = PHOTOMETRIC_MINISBLACK;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
	save_transparent = FALSE;
Packit ed3af9
Packit ed3af9
	/* test if the extrasample represents an associated alpha channel... */
Packit ed3af9
	if (extra > 0 && (extra_types[0] == EXTRASAMPLE_ASSOCALPHA)) {
Packit ed3af9
		has_alpha = TRUE;
Packit ed3af9
		save_transparent = FALSE;
Packit ed3af9
		--extra;
Packit ed3af9
	} else if (extra > 0 && (extra_types[0] == EXTRASAMPLE_UNASSALPHA)) {
Packit ed3af9
		has_alpha = TRUE;
Packit ed3af9
		save_transparent = TRUE;
Packit ed3af9
		--extra;
Packit ed3af9
	} else if (extra > 0 && (extra_types[0] == EXTRASAMPLE_UNSPECIFIED)) {
Packit ed3af9
		/* assuming unassociated alpha if unspecified */
Packit ed3af9
		gd_error("alpha channel type not defined, assuming alpha is not premultiplied");
Packit ed3af9
		has_alpha = TRUE;
Packit ed3af9
		save_transparent = TRUE;
Packit ed3af9
		--extra;
Packit ed3af9
	} else {
Packit ed3af9
		has_alpha = FALSE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (photometric == PHOTOMETRIC_RGB && spp > 3 + extra) {
Packit ed3af9
		has_alpha = TRUE;
Packit ed3af9
		extra = spp - 4;
Packit ed3af9
	} else if (photometric != PHOTOMETRIC_RGB && spp > 1 + extra) {
Packit ed3af9
		has_alpha = TRUE;
Packit ed3af9
		extra = spp - 2;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	is_bw = FALSE;
Packit ed3af9
	is_gray = FALSE;
Packit ed3af9
Packit ed3af9
	switch (photometric) {
Packit ed3af9
	case PHOTOMETRIC_MINISBLACK:
Packit ed3af9
	case PHOTOMETRIC_MINISWHITE:
Packit ed3af9
		if (!has_alpha && bps == 1 && spp == 1) {
Packit ed3af9
			image_type = GD_INDEXED;
Packit ed3af9
			is_bw = TRUE;
Packit ed3af9
		} else {
Packit ed3af9
			image_type = GD_GRAY;
Packit ed3af9
		}
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	case PHOTOMETRIC_RGB:
Packit ed3af9
		image_type = GD_RGB;
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	case PHOTOMETRIC_PALETTE:
Packit ed3af9
		image_type = GD_INDEXED;
Packit ed3af9
		break;
Packit ed3af9
Packit ed3af9
	default:
Packit ed3af9
		force_rgba = TRUE;
Packit ed3af9
		break;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* Force rgba if image has 1bps, but is not bw */
Packit ed3af9
	if (bps == 1 && !is_bw) {
Packit ed3af9
		force_rgba = TRUE;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar)) {
Packit ed3af9
		planar = PLANARCONFIG_CONTIG;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* Force rgba if image plans are not contiguous */
Packit ed3af9
	if (force_rgba || planar != PLANARCONFIG_CONTIG) {
Packit ed3af9
		image_type = GD_RGB;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!force_rgba &&
Packit ed3af9
	        (image_type == GD_PALETTE || image_type == GD_INDEXED || image_type == GD_GRAY)) {
Packit ed3af9
		im = gdImageCreate(width, height);
Packit ed3af9
		if (!im) goto error;
Packit ed3af9
		readTiffColorMap(im, tif, is_bw, photometric);
Packit ed3af9
	} else {
Packit ed3af9
		im = gdImageCreateTrueColor(width, height);
Packit ed3af9
		if (!im) goto error;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
#ifdef DEBUG
Packit ed3af9
	printf("force rgba: %i\n", force_rgba);
Packit ed3af9
	printf("has_alpha: %i\n", has_alpha);
Packit ed3af9
	printf("save trans: %i\n", save_transparent);
Packit ed3af9
	printf("is_bw: %i\n", is_bw);
Packit ed3af9
	printf("is_gray: %i\n", is_gray);
Packit ed3af9
	printf("type: %i\n", image_type);
Packit ed3af9
#else
Packit ed3af9
	(void)is_gray;
Packit ed3af9
	(void)save_transparent;
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
	if (force_rgba) {
Packit ed3af9
		ret = createFromTiffRgba(tif, im);
Packit ed3af9
	} else if (TIFFIsTiled(tif)) {
Packit ed3af9
		ret = createFromTiffTiles(tif, im, bps, photometric, has_alpha, is_bw, extra);
Packit ed3af9
	} else {
Packit ed3af9
		ret = createFromTiffLines(tif, im, bps, photometric, has_alpha, is_bw, extra);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (!ret) {
Packit ed3af9
		gdImageDestroy(im);
Packit ed3af9
		im = NULL;
Packit ed3af9
		goto error;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (TIFFGetField(tif, TIFFTAG_XRESOLUTION, &res_float)) { 
Packit ed3af9
		im->res_x = (unsigned int)res_float;  //truncate
Packit ed3af9
	}
Packit ed3af9
	if (TIFFGetField(tif, TIFFTAG_YRESOLUTION, &res_float)) { 
Packit ed3af9
		im->res_y = (unsigned int)res_float;  //truncate
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation)) {
Packit ed3af9
		switch (orientation) {
Packit ed3af9
		case ORIENTATION_TOPLEFT:
Packit ed3af9
		case ORIENTATION_TOPRIGHT:
Packit ed3af9
		case ORIENTATION_BOTRIGHT:
Packit ed3af9
		case ORIENTATION_BOTLEFT:
Packit ed3af9
			break;
Packit ed3af9
Packit ed3af9
		default:
Packit ed3af9
			gd_error("Orientation %d not handled yet!", orientation);
Packit ed3af9
			break;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
error:
Packit ed3af9
	TIFFClose(tif);
Packit ed3af9
	gdFree(th);
Packit ed3af9
	return im;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
	Function: gdImageCreateFromTIFF
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(gdImagePtr) gdImageCreateFromTiff(FILE *inFile)
Packit ed3af9
{
Packit ed3af9
	gdImagePtr im;
Packit ed3af9
	gdIOCtx *in = gdNewFileCtx(inFile);
Packit ed3af9
	if (in == NULL) return NULL;
Packit ed3af9
	im = gdImageCreateFromTiffCtx(in);
Packit ed3af9
	in->gd_free(in);
Packit ed3af9
	return im;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
	Function: gdImageCreateFromTiffPtr
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(gdImagePtr) gdImageCreateFromTiffPtr(int size, void *data)
Packit ed3af9
{
Packit ed3af9
	gdImagePtr im;
Packit ed3af9
	gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
Packit ed3af9
	if (in == NULL) return NULL;
Packit ed3af9
	im = gdImageCreateFromTiffCtx(in);
Packit ed3af9
	in->gd_free(in);
Packit ed3af9
	return im;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
	Function: gdImageTiff
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(void) gdImageTiff(gdImagePtr im, FILE *outFile)
Packit ed3af9
{
Packit ed3af9
	gdIOCtx *out = gdNewFileCtx(outFile);
Packit ed3af9
	if (out == NULL) return;
Packit ed3af9
	gdImageTiffCtx(im, out); /* what's an fg again? */
Packit ed3af9
	out->gd_free(out);
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
	Function: gdImageTiffPtr
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(void *) gdImageTiffPtr(gdImagePtr im, int *size)
Packit ed3af9
{
Packit ed3af9
	void *rv;
Packit ed3af9
	gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
Packit ed3af9
	if (out == NULL) return NULL;
Packit ed3af9
	gdImageTiffCtx(im, out); /* what's an fg again? */
Packit ed3af9
	rv = gdDPExtractData(out, size);
Packit ed3af9
	out->gd_free(out);
Packit ed3af9
	return rv;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
#endif