guy 3bf951f42c Patch level : 10.0
Files correlati     : pdflib
Ricompilazione Demo : [ ]
Commento            :
Aggiornata pdflib.dll alla versione 7.0.4


git-svn-id: svn://10.65.10.50/trunk@18580 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-03-23 08:55:58 +00:00

1212 lines
35 KiB
C
Executable File

/*---------------------------------------------------------------------------*
| PDFlib - A library for generating PDF on the fly |
+---------------------------------------------------------------------------+
| Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+---------------------------------------------------------------------------+
| |
| This software is subject to the PDFlib license. It is NOT in the |
| public domain. Extended versions and commercial licenses are |
| available, please check http://www.pdflib.com. |
| |
*---------------------------------------------------------------------------*/
/* $Id: p_tiff.c,v 1.4 2009-03-23 08:55:35 guy Exp $
*
* TIFF processing for PDFlib
*
*/
#include "p_intern.h"
#include "p_color.h"
#include "p_image.h"
#ifndef HAVE_LIBTIFF
pdc_bool
pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff, pdc_bool check)
{
(void) p;
(void) fp;
(void) tiff;
(void) check;
return pdc_false;
}
int
pdf_process_TIFF_data(
PDF *p,
int imageslot)
{
(void) imageslot;
pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "TIFF", 0, 0, 0);
return -1;
}
#else
#include "tiffiop.h"
static tsize_t
pdf_libtiff_read(void* fd, tdata_t buf, tsize_t size)
{
pdc_file *fp = (pdc_file *) fd;
return ((tsize_t) pdc_fread(buf, 1, (size_t) size, fp));
}
static toff_t
pdf_libtiff_seek(void* fd, toff_t off, int whence)
{
pdc_file *fp = (pdc_file *) fd;
return ((toff_t) pdc_fseek(fp, (long) off, whence));
}
static int
pdf_libtiff_close(void* fd)
{
(void) fd;
/* pdc_fclose(fp); this happens in caller function */
return 0;
}
static toff_t
pdf_libtiff_size(void* fd)
{
pdc_file *fp = (pdc_file *) fd;
return (toff_t) pdc_file_size(fp);
}
static void *
pdf_libtiff_malloc(TIFF *t, tsize_t size)
{
PDF *p = (PDF*) t->pdflib_opaque;
return pdc_calloc(p->pdc, (size_t)size, "libtiff");
}
static void *
pdf_libtiff_realloc(TIFF *t, tdata_t mem, tsize_t size)
{
PDF *p = (PDF*) t->pdflib_opaque;
return(pdc_realloc(p->pdc, (void*)mem, (size_t)size, "libtiff"));
}
static void
pdf_libtiff_free(TIFF *t, tdata_t mem)
{
PDF *p = (PDF*) t->pdflib_opaque;
pdc_free(p->pdc, (void*)mem);
}
#define PDF_TIFF_LENGTH_MAX 512
static void
pdf_libtiff_error(TIFF *t, const char* module, const char* fmt, va_list ap)
{
PDF *p = (PDF*) t->pdflib_opaque;
if (pdc_logg_is_enabled(p->pdc, 5, trc_image))
{
char buffer[PDF_TIFF_LENGTH_MAX];
/* Create the message */
pdc_vsnprintf(p->pdc, buffer, PDF_TIFF_LENGTH_MAX, fmt, ap);
pdc_logg(p->pdc, "\tlibtiff(%s): %s\n", module, buffer);
}
}
static void
pdf_data_source_TIFF_init(PDF *p, PDF_data_source *src)
{
static const char *fn = "pdf_data_source_TIFF_init";
pdf_image *image;
image = (pdf_image *) src->private_data;
if (image->strips == 1)
image->info.tiff.cur_line = 0;
if (image->use_raw)
{
/* malloc is done in the fill function */
src->buffer_length = (size_t) 0;
src->buffer_start = (pdc_byte *) NULL;
}
else
{
if (image->bpc == 1)
src->buffer_length =
(size_t) (image->components * ((int) image->width+7)/8);
else
src->buffer_length =
(size_t) (image->components * image->width);
src->buffer_start = (pdc_byte *)
pdc_malloc(p->pdc, src->buffer_length, fn);
}
}
/* Convert the a and b samples of Lab data from signed to unsigned. */
static void
pdf_signed_to_unsigned(pdc_byte *buf, size_t count)
{
size_t i;
for(i=0; i < count; i+=3)
{
buf[i+1] ^= 0x80;
buf[i+2] ^= 0x80;
}
}
#define MYTIFF image->info.tiff.tif
static pdc_bool
pdf_data_source_TIFF_fill(PDF *p, PDF_data_source *src)
{
static const char *fn = "pdf_data_source_TIFF_fill";
pdf_image *image;
int col;
pdc_byte *dest;
uint16 fillorder;
uint32 *s, *bc;
image = (pdf_image *) src->private_data;
PDC_TRY(p->pdc)
{
if (image->use_raw)
{
if (image->info.tiff.cur_line == image->strips)
{
PDC_EXIT_TRY(p->pdc);
return pdc_false;
}
TIFFGetField(MYTIFF, TIFFTAG_STRIPBYTECOUNTS, &bc);
if (bc[image->info.tiff.cur_line] > src->buffer_length)
{
src->buffer_length = bc[image->info.tiff.cur_line];
src->buffer_start = (pdc_byte *)
pdc_realloc(p->pdc, src->buffer_start,
src->buffer_length, fn);
}
if (TIFFReadRawStrip(MYTIFF, (tstrip_t) image->info.tiff.cur_line,
(tdata_t) src->buffer_start,
(tsize_t) bc[image->info.tiff.cur_line]) == -1)
{
pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "TIFF",
pdf_get_image_filename(p, image), 0, 0);
}
src->next_byte = src->buffer_start;
src->bytes_available = bc[image->info.tiff.cur_line];
/* special handling for uncompressed 16-bit images */
if (MYTIFF->tif_header.tiff_magic == TIFF_LITTLEENDIAN &&
image->compression == pdf_comp_none && image->bpc == 16)
{
TIFFSwabArrayOfShort((uint16 *) src->buffer_start,
(unsigned long) src->bytes_available/2);
}
if (TIFFGetField(MYTIFF, TIFFTAG_FILLORDER, &fillorder)
&& (fillorder == FILLORDER_LSB2MSB))
{
TIFFReverseBits((unsigned char *) src->buffer_start,
(unsigned long) src->bytes_available);
}
/* The a and b values of (uncompressed) Lab must be adjusted */
if (p->colorspaces[image->colorspace].type == Lab)
{
pdf_signed_to_unsigned(src->buffer_start, src->bytes_available);
}
if (image->strips > 1)
{
/* only a single strip of a multi-strip image */
image->info.tiff.cur_line = image->strips;
}
else
image->info.tiff.cur_line++;
}
else
{
{
if (image->info.tiff.cur_line++ == image->height)
{
PDC_EXIT_TRY(p->pdc);
return pdc_false;
}
src->next_byte = src->buffer_start;
src->bytes_available = src->buffer_length;
dest = src->buffer_start;
s = image->info.tiff.raster +
((int)image->height - image->info.tiff.cur_line) *
(int) image->width;
switch (image->components)
{
case 1:
if (image->bpc == 1)
{
unsigned char mask;
memset((void*) dest, 0, src->buffer_length);
for (mask=0x80, col = 0; col < image->width; col++)
{
if (TIFFGetR(*s++) != 0)
*dest |= mask;
if ((mask>>=1) == 0)
{
mask = 0x80;
++dest;
}
}
}
else /* bpc == 8 */
{
for (col = 0; col < image->width; col++, s++)
{
*dest++ = (pdc_byte) TIFFGetR(*s);
}
}
break;
case 3:
for (col = 0; col < image->width; col++, s++)
{
*dest++ = (pdc_byte) TIFFGetR(*s);
*dest++ = (pdc_byte) TIFFGetG(*s);
*dest++ = (pdc_byte) TIFFGetB(*s);
}
break;
case 4:
for (col = 0; col < image->width; col++, s++)
{
unsigned char* t = (unsigned char*)&(*s);
*dest++ = (pdc_byte) t[0];
*dest++ = (pdc_byte) t[1];
*dest++ = (pdc_byte) t[2];
*dest++ = (pdc_byte) t[3];
}
break;
default:
pdc_error(p->pdc, PDF_E_IMAGE_BADCOMP,
pdc_errprintf(p->pdc, "%d", image->components),
pdf_get_image_filename(p, image), 0, 0);
}
}
}
}
PDC_CATCH(p->pdc)
{
image->corrupt = pdc_true;
}
return !image->corrupt;
}
static void
pdf_data_source_TIFF_terminate(PDF *p, PDF_data_source *src)
{
pdc_free(p->pdc, (void *) src->buffer_start);
}
static int
pdf_check_colormap(int n, uint16* r, uint16* g, uint16* b)
{
while (n-- > 0)
if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
return(16);
return(8);
}
pdc_bool
pdf_is_TIFF_file(PDF *p, pdc_file *fp, pdf_tiff_info *tiff_info, pdc_bool check)
{
const char *filename;
pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type TIFF...\n");
filename = pdc_file_name(fp);
tiff_info->tif = TIFFClientOpen(filename, "rc",
(void *)fp,
pdf_libtiff_read, NULL,
pdf_libtiff_seek, pdf_libtiff_close, pdf_libtiff_size,
NULL, NULL, (void *)p,
pdf_libtiff_malloc, pdf_libtiff_realloc, pdf_libtiff_free,
pdf_libtiff_error, pdf_libtiff_error);
if (tiff_info->tif == NULL)
{
pdc_fseek(fp, 0L, SEEK_SET);
return pdc_false;
}
if (check)
TIFFClose(tiff_info->tif);
return pdc_true;
}
int
pdf_process_TIFF_data(
PDF *p,
int imageslot)
{
static const char *fn = "pdf_process_TIFF_data";
uint32 width, height;
uint16 unit, bpc, compression, photometric, extra, *sinfo;
uint16 orientation, planarconfig;
uint16 *rmap, *gmap, *bmap;
tsample_t components;
pdf_image *image;
float res_x, res_y; /* sic! */
pdf_colorspace cs;
int slot;
int errint = 0;
int errcode = 0;
pdc_bool isopen = pdc_false;
int strips;
image = &p->images[imageslot];
image->info.tiff.raster = (uint32 *) NULL;
if (!pdf_is_TIFF_file(p, image->fp, &image->info.tiff, pdc_false))
{
errcode = PDF_E_IMAGE_CORRUPT;
goto PDF_TIFF_ERROR;
}
MYTIFF->tif_fd = (FILE*) image->fp;
isopen = pdc_true;
if (image->page != 1)
{
if (TIFFSetDirectory(MYTIFF, (tdir_t) (image->page - 1)) != 1 )
{
errint = image->page;
errcode = PDF_E_IMAGE_NOPAGE;
goto PDF_TIFF_ERROR;
}
}
TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_ORIENTATION, &orientation);
image->orientation = orientation;
TIFFGetField(MYTIFF, TIFFTAG_COMPRESSION, &compression);
TIFFGetField(MYTIFF, TIFFTAG_IMAGEWIDTH, &width);
image->width = (pdc_scalar) width;
TIFFGetField(MYTIFF, TIFFTAG_IMAGELENGTH, &height);
image->height = (pdc_scalar) height;
TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_BITSPERSAMPLE, &bpc);
image->bpc = bpc;
TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_SAMPLESPERPIXEL, &components);
image->components = components;
TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_EXTRASAMPLES, &extra, &sinfo);
TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_PLANARCONFIG, &planarconfig);
photometric = 255; /* dummy value */
TIFFGetField(MYTIFF, TIFFTAG_PHOTOMETRIC, &photometric);
/* fetch the resolution values if found in the file */
if (TIFFGetField(MYTIFF, TIFFTAG_XRESOLUTION, &res_x) &&
TIFFGetField(MYTIFF, TIFFTAG_YRESOLUTION, &res_y) &&
TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_RESOLUTIONUNIT, &unit) &&
res_x > 0 && res_y > 0) {
if (unit == RESUNIT_INCH) {
image->dpi_x = res_x;
image->dpi_y = res_y;
} else if (unit == RESUNIT_CENTIMETER) {
image->dpi_x = res_x * 2.54;
image->dpi_y = res_y * 2.54;
} else if (unit == RESUNIT_NONE) {
image->dpi_x = -res_x;
image->dpi_y = -res_y;
}
#define PDF_REALLY_BIG_DPI 10000
/* Guard against obviously wrong values */
if (unit != RESUNIT_NONE &&
(image->dpi_x <= 1 ||
image->dpi_y <= 1 ||
image->dpi_x > PDF_REALLY_BIG_DPI ||
image->dpi_y > PDF_REALLY_BIG_DPI))
image->dpi_x = image->dpi_y = 0; /* unknown */
}
/* ------------------------------------------------------------
* Reject unsupported flavors.
* ---------------------------------------------------------- */
/* Catch some rare properties related to compression, photometric,
* and bpc which are definitely not supported (neither in pass-through
* mode nor libtiff) in order to provide a better error message than
* the generic "Error reading data".
*/
/* Unsupported compression types */
switch ((int) compression)
{
case /* 34661 */ COMPRESSION_JBIG:
case /* 34712 */ COMPRESSION_JP2000:
case 9 /* JBIG T85 */:
case 10 /* TIFF-FX JBIG (T.82) MRC (T.43) */:
case 34715 /* TFX */:
errint = (int) compression;
errcode = PDF_E_TIFF_UNSUPP_COMPRESSION;
goto PDF_TIFF_ERROR;
break;
default:
break;
}
/* Unsupported photometric values */
switch ((int) photometric)
{
case PHOTOMETRIC_ICCLAB /* 9 */:
case PHOTOMETRIC_ITULAB /* 10 */:
errint = (int) photometric;
errcode = PDF_E_TIFF_UNSUPP_COLORSPACE;
goto PDF_TIFF_ERROR;
break;
default:
break;
}
/* 32-bit images are not supported */
if (image->bpc > 16)
{
errcode = PDF_E_TIFF_16BIT_UNSUPP;
goto PDF_TIFF_ERROR;
}
/* We don't support 16-bit CMYK unless it's uncompressed */
if (image->bpc == 16 && components == 4 && compression != COMPRESSION_NONE)
{
errcode = PDF_E_TIFF_16BITCMYK_UNSUPP;
goto PDF_TIFF_ERROR;
}
/* ------------------------------------------------------------
* We assume pass-through mode in the beginning, and disable it
* for image types where it doesn't work.
* ---------------------------------------------------------- */
image->use_raw = image->passthrough;
/* Pass-through is not implemented for tiled images */
if (TIFFIsTiled(MYTIFF))
image->use_raw = pdc_false;
/* Can't handle these colorspaces in raw mode (except with OJPEG) */
if (compression != COMPRESSION_OJPEG &&
(photometric == PHOTOMETRIC_YCBCR ||
photometric == PHOTOMETRIC_CIELAB ||
photometric == PHOTOMETRIC_MASK))
{
image->use_raw = pdc_false;
}
/* Can't pass through extra bits or use multiple data sources in raw mode
* (except with OJPEG).
*/
if (extra != 0 ||
(compression != COMPRESSION_OJPEG &&
planarconfig == PLANARCONFIG_SEPARATE && components > 1))
{
image->components -= extra; /* ignore the extra channels */
image->use_raw = pdc_false;
}
/* PDF doesn't support other values of the color depth */
if (bpc != 1 && bpc != 2 && bpc != 4 && bpc != 8 && bpc != 16)
image->use_raw = pdc_false;
/* Disable pass-through for a large number of strips to avoid
* file size bloat (due to many small Image XObjects) and
* ugly display in Acrobat (because of banding artifacts).
* The threshold for the number of strips has been determined empirically
* as a good compromise between file size and performance.
*
* We must still maintain pass-through mode for those cases where it
* is functionally more advanced, and benefit from its better performance
* for small numbers of strips.
*
* Also, we maintain pass-through mode for very large images since
* pass-through mode - especially with pixel mode (RGBA retrieval) -
* may run out of memory.
*/
/* ca. 10K x 10K pixels (nopassthrough requires up to 4 times as many bytes!) */
#define PDF_TIFF_THRESHOLD 0x6000000
strips = (int) TIFFNumberOfStrips(MYTIFF);
if (strips > 25 &&
compression != COMPRESSION_OJPEG && compression != COMPRESSION_JPEG &&
photometric != PHOTOMETRIC_PALETTE &&
image->width * image->height < PDF_TIFF_THRESHOLD)
{
image->use_raw = pdc_false;
}
if (image->bpc == 16)
{
/* PDF < 1.5 doesn't support 16-bit images, so we cannot pass through */
if (p->compatibility < PDC_1_5)
{
image->use_raw = pdc_false;
}
/*
* PDF requires big-endian 16-bit data. We therefore use passthrough
* mode only for big-endian input or uncompressed data.
*
* It's not nice to pull the endianness directly from the TIFF
* structure, but there doesn't seem to be a public interface for it.
*/
if (MYTIFF->tif_header.tiff_magic == TIFF_LITTLEENDIAN &&
(compression == COMPRESSION_DEFLATE ||
compression == COMPRESSION_ADOBE_DEFLATE))
{
image->use_raw = pdc_false;
}
/* We don't support 16-bit CMYK unless in passthrough mode.
* Compressed images have already been rejected earlier.
*/
if (components == 4 && image->use_raw == pdc_false)
{
errcode = PDF_E_TIFF_16BITCMYK_UNSUPP;
goto PDF_TIFF_ERROR;
}
}
/*
* Disable pass-through for unknown compression schemes,
* and collect the necessary parameters for well-known schemes.
*/
if (image->use_raw == pdc_true)
{
uint32 group3opts;
uint16 predictor;
toff_t jpegifoffset, jpegifbytecount;
switch ((int) compression)
{
case COMPRESSION_CCITTRLE:
case COMPRESSION_CCITTRLEW:
image->params = (char *) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING,
fn);
strcpy(image->params, "/EndOfBlock false");
strcat(image->params, "/EncodedByteAlign true");
if (photometric == PHOTOMETRIC_MINISBLACK)
strcat(image->params, "/BlackIs1 true");
image->compression = pdf_comp_ccitt;
break;
case COMPRESSION_CCITTFAX3:
image->params = (char*) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING,
fn);
strcpy(image->params, "/EndOfBlock false");
/* The following contains disabled code segments.
* Apparently, and contrary to my reading of the specs,
* the following can not be deduced from the respective
* TIFF entry or option:
* - /EncodedByteAlign can not reliably be deduced from
* GROUP3OPT_FILLBITS;
*
* From practical experience, the respective lines are
* disabled, but I don't have any clear explanation for this.
* A few TIFF images still don't work with this setting,
* unfortunately.
*/
/* SEE ABOVE!
strcat(image->params, "/DamagedRowsBeforeError 1");
*/
if (TIFFGetField(MYTIFF, TIFFTAG_GROUP3OPTIONS, &group3opts))
{
/* /K = 0 (= G3,1D) is default */
if (group3opts & GROUP3OPT_2DENCODING)
strcat(image->params, "/K 1");
/* SEE ABOVE!
if (group3opts & GROUP3OPT_FILLBITS)
strcat(image->params, "/EncodedByteAlign true");
*/
}
if (photometric == PHOTOMETRIC_MINISBLACK)
strcat(image->params, "/BlackIs1 true");
image->compression = pdf_comp_ccitt;
break;
case COMPRESSION_CCITTFAX4:
image->params = (char*) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING,
fn);
strcpy(image->params, "/K -1");
/* Required for bug #511 */
strcat(image->params, "/EndOfBlock false");
if (photometric == PHOTOMETRIC_MINISBLACK)
strcat(image->params, "/BlackIs1 true");
image->compression = pdf_comp_ccitt;
break;
case COMPRESSION_OJPEG:
/*
* Check whether a full-blown JPEG can be found inside the TIFF
*
* Heuristic:
* If we find a positive JPEGIFOFFSET there should be valid
* JFIF data; however, sometimes there isn't and we must not
*call the JPEG module. Strangely enough, various creators which
* do not emit valid JFIF do emit the JPEGIFBYTECOUNT tag.
* Therefore we use the absence of JPEGIFBYTECOUNT as a hint
* that JFIF processing might work.
*
* Known trouble-makers which include JPEGIFBYTECOUNT:
* "Oi/GFS, writer v00.06.02"
*/
if (TIFFGetField(MYTIFF, TIFFTAG_JPEGIFOFFSET, &jpegifoffset) &&
jpegifoffset != 0 &&
!TIFFGetField(MYTIFF, TIFFTAG_JPEGIFBYTECOUNT,
&jpegifbytecount))
{
/* stop TIFF processing */
TIFFClose(MYTIFF);
/* store data offset for the JPEG module (after TIFFClose()
* the image->info union is no longer used by the TIFF
* module)
*/
image->info.jpeg.jpegifoffset = jpegifoffset;
/* ...and process the data at the offset as JPEG */
pdc_logg_cond(p->pdc, 1, trc_image,
"\tTIFF with OJPEG: switching to JPEG processing...\n");
return pdf_process_JPEG_data(p, imageslot);
}
else
{
/* We must repeat the check here since we omitted the OJPEG
* case when we applied the test for the first time.
*/
if (extra != 0 ||
(planarconfig == PLANARCONFIG_SEPARATE && components > 1))
{
/* ignore the extra channels */
image->components -= extra;
}
image->use_raw = pdc_false;
}
break;
case COMPRESSION_NONE:
if (photometric == PHOTOMETRIC_MINISWHITE)
image->invert = !image->invert;
image->compression = pdf_comp_none;
break;
case COMPRESSION_LZW:
if (TIFFGetField(MYTIFF, TIFFTAG_PREDICTOR, &predictor)) {
if (predictor != pred_default && predictor != pred_tiff) {
image->use_raw = pdc_false;
break;
} else
image->predictor = (pdf_predictor) predictor;
}
if (photometric == PHOTOMETRIC_MINISWHITE)
image->invert = !image->invert;
image->compression = pdf_comp_lzw;
break;
case COMPRESSION_PACKBITS:
if (photometric == PHOTOMETRIC_MINISWHITE)
image->invert = !image->invert;
image->compression = pdf_comp_runlength;
break;
case COMPRESSION_DEFLATE:
case COMPRESSION_ADOBE_DEFLATE:
if (TIFFGetField(MYTIFF, TIFFTAG_PREDICTOR, &predictor)) {
if (predictor != pred_default && predictor != pred_tiff) {
image->use_raw = pdc_false;
break;
} else
image->predictor = (pdf_predictor) predictor;
}
if (photometric == PHOTOMETRIC_MINISWHITE)
image->invert = !image->invert;
image->compression = pdf_comp_flate;
break;
default:
image->use_raw = pdc_false;
}
}
if (image->use_raw)
{
/* pass-through mode: directly copy chunks of strip data */
image->strips = strips;
pdc_logg_cond(p->pdc, 1, trc_image, "\tpassthrough mode...\n");
}
else
{
/* libtiff cannot handle JPEG-compressed TIFFs with separate image
* planes
*/
if (planarconfig == PLANARCONFIG_SEPARATE &&
(compression == COMPRESSION_OJPEG || compression==COMPRESSION_JPEG))
{
errcode = PDF_E_TIFF_UNSUPP_SEPARATE;
goto PDF_TIFF_ERROR;
}
/* Fallback: use TIFFlib to retrieve pixel data */
/* We have special handling for preserving bpc=1 if components=1,
* and therefore don't change bpc in this case.
*/
if (!(image->components == 1 && image->bpc == 1))
{
/* Retrieve pixel data with libtiff, which converts to 8 bits. */
image->bpc = 8;
}
image->strips = 1;
image->compression = pdf_comp_none;
/* Palette images are automatically converted to RGB by TIFFlib.
* Since there are actually 1-bit images (photometric=min-is-white)
* with a palette out there (which are invalid TIFF, and are not
* converted to RGB by TIFFlib) we must also check photometric.
*/
if (image->components == 1 && photometric == PHOTOMETRIC_PALETTE &&
TIFFGetField(MYTIFF, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap))
{
image->components = 3;
image->bpc = 8;
}
pdc_logg_cond(p->pdc, 1, trc_image, "\tno passthrough mode...\n");
}
if (image->imagemask)
{
if (image->components != 1)
{
errcode = PDF_E_IMAGE_BADMASK;
goto PDF_TIFF_ERROR;
}
if (p->compatibility == PDC_1_3)
{
if (image->components != 1 || image->bpc != 1)
{
errcode = PDF_E_IMAGE_MASK1BIT13;
goto PDF_TIFF_ERROR;
}
}
else if (image->bpc > 1)
{
/* images with more than one bit will be written as /SMask,
* and don't require an /ImageMask entry.
*/
image->imagemask = pdc_false;
}
}
if (image->mask != pdc_undef)
{
if (image->strips != 1)
{
errcode = PDF_E_TIFF_MASK_MULTISTRIP;
goto PDF_TIFF_ERROR;
}
}
if (image->colorspace == pdc_undef)
{
uint16 inkset;
switch (image->components)
{
case 1:
image->colorspace = DeviceGray;
break;
case 3:
image->colorspace = DeviceRGB;
break;
case 4:
if (photometric == PHOTOMETRIC_SEPARATED)
{
/* Can't handle CMYK with mask */
if (extra != 0)
{
errint = image->components;
errcode = PDF_E_TIFF_CMYK_MASK;
goto PDF_TIFF_ERROR;
}
TIFFGetFieldDefaulted(MYTIFF, TIFFTAG_INKSET, &inkset);
if (inkset != INKSET_CMYK)
{
errint = inkset;
errcode = PDF_E_TIFF_UNSUPP_SEP_NONCMYK;
goto PDF_TIFF_ERROR;
}
image->colorspace = DeviceCMYK;
}
else
{
/* if it's not separated it must be RGB with alpha */
image->components = 3;
image->colorspace = DeviceRGB;
image->compression = pdf_comp_none;
}
break;
default:
errint = image->components;
errcode = PDF_E_IMAGE_BADCOMP;
goto PDF_TIFF_ERROR;
}
}
image->src.private_data = (void *) image;
image->src.init = pdf_data_source_TIFF_init;
image->src.fill = pdf_data_source_TIFF_fill;
image->src.terminate = pdf_data_source_TIFF_terminate;
image->in_use = pdc_true; /* mark slot as used */
image->src.next_byte = NULL;
if (image->use_raw) {
uint32 row, rowsperstrip;
int strip;
/* must handle colormap ourselves */
if (photometric == PHOTOMETRIC_PALETTE)
{
int i;
pdf_colormap colormap;
if (!TIFFGetField(MYTIFF, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap))
{
errcode = PDF_E_IMAGE_COLORMAP;
goto PDF_TIFF_ERROR;
}
/* CCITT compression implicitly carries
* photometric==PHOTOMETRIC_MINISWHITE. Although the combination
* of CCITT compression and palette probably doesn't conform
* to the TIFF spec, we accept it, but must invert the color
* palette in order to match Acrobat's behavior.
* Note that most TIFF viewers either ignore the palette in
* this case or display the image with wrong colors.
*/
if (compression == COMPRESSION_CCITTRLE ||
compression == COMPRESSION_CCITTRLEW ||
compression == COMPRESSION_CCITTFAX3 ||
compression == COMPRESSION_CCITTFAX4)
{
image->invert = !image->invert;
pdc_logg_cond(p->pdc, 1, trc_image,
"\tinverting colors for CCITT-compressed "
"image with palette...\n");
}
cs.type = Indexed;
cs.val.indexed.palette_size = 1 << bpc;
cs.val.indexed.colormap = &colormap;
cs.val.indexed.colormap_id = PDC_BAD_ID;
cs.val.indexed.base = DeviceRGB;
#define CVT(x) (uint16) ((x)>>8)
/* TODO: properly deal with 16-bit palette entries in PDF 1.5 */
if (pdf_check_colormap(cs.val.indexed.palette_size,
rmap, gmap, bmap) == 16)
{
/* convert colormap to 8 bit values */
for (i = 0; i < cs.val.indexed.palette_size; i++)
{
rmap[i] = CVT(rmap[i]);
gmap[i] = CVT(gmap[i]);
bmap[i] = CVT(bmap[i]);
}
}
#undef CVT
for (i = 0; i < cs.val.indexed.palette_size; i++)
{
colormap[i][0] = (pdc_byte) rmap[i];
colormap[i][1] = (pdc_byte) gmap[i];
colormap[i][2] = (pdc_byte) bmap[i];
}
image->components = 1;
slot = pdf_add_colorspace(p, &cs, pdc_false);
image->colorspace = slot;
}
if (image->strips > image->height)
image->strips = (int) image->height;
if (TIFFGetFieldDefaulted(MYTIFF,
TIFFTAG_ROWSPERSTRIP, &rowsperstrip) == 1 && (int)rowsperstrip!= -1)
image->rowsperstrip = (int) rowsperstrip;
else
image->rowsperstrip = (int) image->height;
/*
* The first strip must be handled separately because it carries the
* colormap for indexed images. Other strips reuse this colormap.
*/
image->info.tiff.cur_line = 0;
image->height = (pdc_scalar)
(image->rowsperstrip > (int) height ?
(int) height : image->rowsperstrip);
/*
* Images may also be written to the output before the first page
* We do this ourselves (instead of in pdf_put_image() to avoid
* many empty contents sections for multi-strip images.
*/
if (PDF_GET_STATE(p) == pdf_state_page)
pdf_end_contents_section(p);
pdf_put_image(p, imageslot, pdc_true, pdc_false);
for (row = (uint32) image->rowsperstrip, strip = 1;
row < height; row += (uint32) image->rowsperstrip, strip++)
{
image->height = (pdc_scalar) (row+image->rowsperstrip > height ?
(int) (height - row) : image->rowsperstrip);
/*
* tell pdf_data_source_TIFF_fill() to read only data of the
* current strip
*/
image->info.tiff.cur_line = strip;
pdf_put_image(p, imageslot, pdc_false, pdc_false);
/* Refresh, in case p->images reallocate */
image = &p->images[imageslot];
}
image->height = (pdc_scalar) height;
image->no -= (image->strips - 1); /* number of first strip */
/* Special handling for multi-strip images (see comment above) */
if (PDF_GET_STATE(p) == pdf_state_page)
pdf_begin_contents_section(p);
}
else /* !use_raw */
{
size_t npixels;
/*
* Retrieve full scan lines from TIFFlib for these color spaces,
* and Gray, RGB, or CMYK pixel data otherwise.
*/
if (p->colorspaces[image->colorspace].type == DeviceCMYK ||
(p->colorspaces[image->colorspace].type == ICCBased &&
image->components == 4))
{
pdc_logg_cond(p->pdc, 1, trc_image,
"\tRetrieving full scan lines in native color space...\n");
image->pixelmode = pdc_false;
}
else
{
pdc_logg_cond(p->pdc, 1, trc_image,
"\tRetrieving converted pixel data (pixel mode)...\n");
image->pixelmode = pdc_true;
}
if (planarconfig == PLANARCONFIG_SEPARATE)
{
errcode = PDF_E_TIFF_UNSUPP_SEPARATE;
goto PDF_TIFF_ERROR;
}
else if (image->pixelmode)
{
npixels = (size_t) (width * height);
image->info.tiff.raster = (uint32 *) pdc_malloc(p->pdc,
(size_t) (npixels * sizeof (uint32)), fn);
if (!TIFFReadRGBAImageOriented(MYTIFF,
width, height, image->info.tiff.raster, orientation, 1))
{
errcode = PDC_E_IO_READ;
goto PDF_TIFF_ERROR;
}
}
else
{
int linecounter = 0, sclsize = TIFFScanlineSize(MYTIFF);
npixels = (size_t) (sclsize * height);
image->info.tiff.raster = (uint32 *)pdc_malloc(p->pdc, npixels, fn);
while (linecounter < (int) height)
{
size_t ndots = (size_t)((height - linecounter - 1) * width);
if (npixels <= sizeof(uint32) * ndots)
{
errcode = PDF_E_IMAGE_CORRUPT;
goto PDF_TIFF_ERROR;
}
if (TIFFReadScanline(MYTIFF,
(tdata_t) (image->info.tiff.raster + ndots),
(uint32) linecounter, (tsample_t) 0) == -1)
{
errcode = PDC_E_IO_READ;
goto PDF_TIFF_ERROR;
}
linecounter++;
}
}
pdf_put_image(p, imageslot, pdc_true, pdc_true);
if (image->info.tiff.raster != NULL){
pdc_free(p->pdc, (void *) image->info.tiff.raster);
image->info.tiff.raster = NULL;
}
}
if (!image->corrupt)
{
TIFFClose(MYTIFF);
return imageslot;
}
PDF_TIFF_ERROR:
{
const char *stemp = NULL;
if (errcode)
stemp = pdf_get_image_filename(p, image);
if (image->info.tiff.raster != NULL)
pdc_free(p->pdc, (void *) image->info.tiff.raster);
if (isopen)
TIFFClose(MYTIFF);
switch (errcode)
{
case PDC_E_IO_READ:
case PDF_E_IMAGE_ICC:
case PDF_E_IMAGE_ICC2:
case PDF_E_IMAGE_MASK1BIT13:
case PDF_E_IMAGE_COLORIZE:
case PDF_E_TIFF_MASK_MULTISTRIP:
case PDF_E_IMAGE_COLORMAP:
case PDF_E_IMAGE_BADMASK:
case PDF_E_TIFF_CMYK_MASK:
case PDF_E_TIFF_UNSUPP_SEPARATE:
case PDF_E_TIFF_16BITCMYK_UNSUPP:
case PDF_E_TIFF_16BIT_UNSUPP:
pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0);
break;
case PDF_E_IMAGE_CORRUPT:
pdc_set_errmsg(p->pdc, errcode, "TIFF", stemp, 0, 0);
break;
case PDF_E_TIFF_UNSUPP_COLORSPACE:
case PDF_E_TIFF_UNSUPP_COMPRESSION:
case PDF_E_IMAGE_BADCOMP:
pdc_set_errmsg(p->pdc, errcode,
pdc_errprintf(p->pdc, "%d", errint), stemp, 0, 0);
break;
case PDF_E_IMAGE_NOPAGE:
pdc_set_errmsg(p->pdc, errcode,
pdc_errprintf(p->pdc, "%d", errint), "TIFF", stemp, 0);
break;
case PDF_E_TIFF_UNSUPP_SEP_NONCMYK:
pdc_set_errmsg(p->pdc, errcode,
stemp, pdc_errprintf(p->pdc, "%d", errint), 0, 0);
break;
case 0: /* error code and message already set */
break;
}
}
return -1;
}
#undef MYTIFF
#endif /* HAVE_LIBTIFF */