/*---------------------------------------------------------------------------* | 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.2 2009/10/20 18:14:16 scuri 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 */