GImage *GImageReadTiff(char *filename) { TIFF* tif; uint32 w, h, i,j; uint32 *ipt, *fpt; size_t npixels; uint32* raster; GImage *ret=NULL; struct _GImage *base; if ( libtiff==NULL ) if ( !loadtiff()) return( NULL ); tif = _TIFFOpen(filename, "r"); if (tif==NULL ) return( ret ); _TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); _TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); npixels = w * h; raster = (uint32*) galloc(npixels * sizeof (uint32)); if (raster != NULL) { if (_TIFFReadRGBAImage(tif, w, h, raster, 0)) { ret = GImageCreate(it_true,w,h); if ( ret!=NULL ) { base = ret->u.image; for ( i=0; i<h; ++i ) { ipt = (uint32 *) (base->data+i*base->bytes_per_line); fpt = raster+(h-1-i)*w; for ( j=0; j<w; ++j ) *ipt++ = COLOR_CREATE( TIFFGetR(fpt[j]), TIFFGetG(fpt[j]), TIFFGetB(fpt[j])); } } } gfree(raster); } _TIFFClose(tif); return( ret ); }
int SaveTiffEx ( const char *pFileName, const MinImg *pImg, const ExtImgProps *pProps, int page ) { #ifndef WITH_TIFF return NOT_IMPLEMENTED; #else if (!pImg || !pFileName || page < 0) return BAD_ARGS; if (!pImg->pScan0) return BAD_ARGS; TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); int nPages = GetTiffPages(pFileName); if (nPages == FILE_ERROR) nPages = 0; if (page > nPages || page < 0) return BAD_ARGS; scoped_cpp_array<TiffData> tiff_pages(new TiffData[nPages]); if (page < nPages) { scoped_tiff_handle pTIF(TIFFOpen(pFileName, "r")); if (!pTIF) return FILE_ERROR; for (int k = 0; k < nPages; k++) { TiffData &data = tiff_pages[k]; TIFFSetDirectory(pTIF, k); int &nc = data.samples_per_pixel; int typ = PLANARCONFIG_CONTIG; _TIFFGetField(pTIF, TIFFTAG_SAMPLESPERPIXEL, &nc, 1); if (nc > 1) _TIFFGetField(pTIF, TIFFTAG_PLANARCONFIG, &typ, PLANARCONFIG_CONTIG); if (typ != PLANARCONFIG_CONTIG) return NOT_IMPLEMENTED; int &bpc = data.bytes_per_sample; _TIFFGetField(pTIF, TIFFTAG_IMAGEWIDTH, &data.width, 0); _TIFFGetField(pTIF, TIFFTAG_IMAGELENGTH, &data.height, 0); _TIFFGetField(pTIF, TIFFTAG_BITSPERSAMPLE, &bpc, 0); if (bpc != 1 && bpc & 7) return NOT_IMPLEMENTED; bpc = bpc >> 3; int &metr = data.photometric; _TIFFGetField(pTIF, TIFFTAG_PHOTOMETRIC, &metr, PHOTOMETRIC_MINISWHITE); if (metr == PHOTOMETRIC_MINISWHITE && bpc > 0) return NOT_IMPLEMENTED; _TIFFGetField(pTIF, TIFFTAG_SAMPLEFORMAT, &data.sample_format, SAMPLEFORMAT_UINT); _TIFFGetField(pTIF, TIFFTAG_XRESOLUTION, &data.xresolution, 0.0f); _TIFFGetField(pTIF, TIFFTAG_YRESOLUTION, &data.yresolution, 0.0f); _TIFFGetField(pTIF, TIFFTAG_RESOLUTIONUNIT, &data.resolution_unit, RESUNIT_INCH); _TIFFGetField(pTIF, TIFFTAG_COMPRESSION, &data.compression_type, COMPRESSION_NONE); _TIFFGetField(pTIF, TIFFTAG_JPEGQUALITY, &data.jpeg_quality, 100); const tsize_t scanLen = TIFFScanlineSize(pTIF); data.scan_lines = new uint8_t[data.height * scanLen]; data.scanLen = scanLen; for (int y = 0; y < data.height; y++) { void * pScanLine = data.scan_lines + y * scanLen; SHOULD_WORK(TIFFReadScanline(pTIF, pScanLine, y)); } } }
int LoadTiff ( const MinImg *pImg, const char *pFileName, int page ) { #ifndef WITH_TIFF return NOT_IMPLEMENTED; #else if (!pImg || !pFileName || page < 0) return BAD_ARGS; if (!pImg->pScan0) return BAD_ARGS; TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); scoped_tiff_handle pTIF(TIFFOpen(pFileName, "r")); if (!pTIF) return FILE_ERROR; const int nPages = TIFFNumberOfDirectories(pTIF); if (page >= nPages) return BAD_ARGS; TIFFSetDirectory(pTIF, page); int nc = 0, typ = PLANARCONFIG_CONTIG; _TIFFGetField(pTIF, TIFFTAG_SAMPLESPERPIXEL, &nc, 1); if (nc > 1) _TIFFGetField(pTIF, TIFFTAG_PLANARCONFIG, &typ, PLANARCONFIG_CONTIG); if (typ != PLANARCONFIG_CONTIG) return NOT_IMPLEMENTED; int wd = 0, ht = 0, bpc = 0; _TIFFGetField(pTIF, TIFFTAG_IMAGEWIDTH, &wd, 0); _TIFFGetField(pTIF, TIFFTAG_IMAGELENGTH, &ht, 0); _TIFFGetField(pTIF, TIFFTAG_BITSPERSAMPLE, &bpc, 0); if (bpc != 1 && bpc & 7) return NOT_IMPLEMENTED; bpc = bpc >> 3; if (pImg->channels != nc) return BAD_ARGS; if (bpc == 0 && pImg->channelDepth > 1) return BAD_ARGS; if (bpc > 0 && pImg->channelDepth != bpc) return BAD_ARGS; if (pImg->height < ht || pImg->width < wd) return BAD_ARGS; int metr = 0; _TIFFGetField(pTIF, TIFFTAG_PHOTOMETRIC, &metr, PHOTOMETRIC_MINISWHITE); if (metr == PHOTOMETRIC_MINISWHITE && bpc > 0) return NOT_IMPLEMENTED; int dtyp = SAMPLEFORMAT_UINT; _TIFFGetField(pTIF, TIFFTAG_SAMPLEFORMAT, &dtyp, SAMPLEFORMAT_UINT); switch (dtyp) { case SAMPLEFORMAT_UINT: if (pImg->format != FMT_UINT) return BAD_ARGS; break; case SAMPLEFORMAT_INT: if (pImg->format != FMT_INT) return BAD_ARGS; break; case SAMPLEFORMAT_IEEEFP: if (pImg->format != FMT_REAL) return BAD_ARGS; break; default: return NOT_IMPLEMENTED; } const tsize_t scanLen = TIFFScanlineSize(pTIF); scoped_scanline pScanLine(_TIFFmalloc(scanLen)); if (!pScanLine) return NO_MEMORY; const int byteWidth = pImg->channelDepth > 0 ? pImg->width * pImg->channels * pImg->channelDepth : (pImg->width * pImg->channels + 7) >> 3; if (byteWidth < scanLen) return INTERNAL_ERROR; bool invert = (metr == PHOTOMETRIC_MINISWHITE); uint8_t *pScanLineUint8 = (uint8_t *)((void *)(pScanLine)); for (int y = 0; y < ht; y++) { SHOULD_WORK(TIFFReadScanline(pTIF, pScanLine, y)); if (bpc == 0 && bpc == pImg->channelDepth) CopyBits(pImg->pScan0 + pImg->stride * y, pScanLineUint8, wd, invert); else if (bpc == 0 && bpc < pImg->channelDepth) UnpackLine(pImg->pScan0 + pImg->stride * y, pScanLineUint8, wd, invert); else memcpy(pImg->pScan0 + pImg->stride * y, pScanLine, scanLen); } return NO_ERRORS; #endif // WITH_TIFF }
int GetTiffPropsEx ( MinImg *pImg, ExtImgProps *pProps, const char *pFileName, int page ) { #ifndef WITH_TIFF return NOT_IMPLEMENTED; #else if (!pFileName || page < 0) return BAD_ARGS; if (pImg && pImg->pScan0) return BAD_ARGS; TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); scoped_tiff_handle pTIF(TIFFOpen(pFileName, "r")); if (!pTIF) return FILE_ERROR; const int nPages = TIFFNumberOfDirectories(pTIF); if (page >= nPages) return BAD_ARGS; TIFFSetDirectory(pTIF, page); if (pImg) { int nc = 0, typ = PLANARCONFIG_CONTIG; _TIFFGetField(pTIF, TIFFTAG_SAMPLESPERPIXEL, &nc, 1); if (nc > 1) _TIFFGetField(pTIF, TIFFTAG_PLANARCONFIG, &typ, PLANARCONFIG_CONTIG); if (typ != PLANARCONFIG_CONTIG) return NOT_IMPLEMENTED; int wd = 0, ht = 0, bpc = 0; _TIFFGetField(pTIF, TIFFTAG_IMAGEWIDTH, &wd, 0); _TIFFGetField(pTIF, TIFFTAG_IMAGELENGTH, &ht, 0); _TIFFGetField(pTIF, TIFFTAG_BITSPERSAMPLE, &bpc, 0); if (bpc != 1 && bpc & 7) return NOT_IMPLEMENTED; bpc = bpc >> 3; int dtyp = 0; _TIFFGetField(pTIF, TIFFTAG_SAMPLEFORMAT, &dtyp, 0); switch (dtyp) { case 0: case SAMPLEFORMAT_UINT: dtyp = FMT_UINT; break; case SAMPLEFORMAT_INT: dtyp = FMT_INT; break; case SAMPLEFORMAT_IEEEFP: dtyp = FMT_REAL; break; default: return NOT_IMPLEMENTED; } pImg->width = wd; pImg->height = ht; pImg->channels = nc; pImg->channelDepth = bpc; pImg->format = (MinFmt)dtyp; pImg->stride = 0; } if (pProps) { pProps->iff = IFF_TIFF; pProps->comp = IFC_NONE; int compression = 0; _TIFFGetField(pTIF, TIFFTAG_COMPRESSION, &compression, COMPRESSION_NONE); switch(compression) { case COMPRESSION_LZW: pProps->comp = IFC_LZW; break; case COMPRESSION_DEFLATE: pProps->comp = IFC_DEFLATE; break; case COMPRESSION_PACKBITS: pProps->comp = IFC_PACKBITS; break; case COMPRESSION_JPEG: pProps->comp = IFC_JPEG; break; case COMPRESSION_CCITTRLE: pProps->comp = IFC_RLE; break; case COMPRESSION_CCITTFAX3: pProps->comp = IFC_GROUP3; break; case COMPRESSION_CCITTFAX4: pProps->comp = IFC_GROUP4; break; default: pProps->comp = IFC_NONE; } int unit = 0; _TIFFGetField(pTIF, TIFFTAG_XRESOLUTION, &pProps->xDPI, 0.f); _TIFFGetField(pTIF, TIFFTAG_YRESOLUTION, &pProps->yDPI, 0.f); _TIFFGetField(pTIF, TIFFTAG_RESOLUTIONUNIT, &unit, 0); switch (unit) { case RESUNIT_INCH: break; case RESUNIT_CENTIMETER: pProps->xDPI *= 2.54f; pProps->yDPI *= 2.54f; break; default: pProps->xDPI = 0.f; pProps->yDPI = 0.f; } } return NO_ERRORS; #endif // WITH_TIFF }