u_long TIFFRasterImpl::setorientation(u_long h) { u_long y; if (!TIFFGetField(tif_, TIFFTAG_ORIENTATION, &orientation_)) { orientation_ = ORIENTATION_TOPLEFT; } switch (orientation_) { case ORIENTATION_BOTRIGHT: case ORIENTATION_RIGHTBOT: /* XXX */ case ORIENTATION_LEFTBOT: /* XXX */ TIFFWarning(TIFFFileName(tif_), "using bottom-left orientation"); orientation_ = ORIENTATION_BOTLEFT; /* fall thru... */ case ORIENTATION_BOTLEFT: y = 0; break; case ORIENTATION_TOPRIGHT: case ORIENTATION_RIGHTTOP: /* XXX */ case ORIENTATION_LEFTTOP: /* XXX */ default: TIFFWarning(TIFFFileName(tif_), "using top-left orientation"); orientation_ = ORIENTATION_TOPLEFT; /* fall thru... */ case ORIENTATION_TOPLEFT: y = h-1; break; } return y; }
/* * Hacked from the tif_getimage.c file. */ static uint32 setorientation(TIFFRGBAImage* img, uint32 h) { TIFF* tif = img->tif; uint32 y; switch (img->orientation) { case ORIENTATION_BOTRIGHT: case ORIENTATION_RIGHTBOT: /* XXX */ case ORIENTATION_LEFTBOT: /* XXX */ TIFFWarning(TIFFFileName(tif), "using bottom-left orientation"); img->orientation = ORIENTATION_BOTLEFT; /* fall thru... */ case ORIENTATION_BOTLEFT: y = 0; break; case ORIENTATION_TOPRIGHT: case ORIENTATION_RIGHTTOP: /* XXX */ case ORIENTATION_LEFTTOP: /* XXX */ default: TIFFWarning(TIFFFileName(tif), "using top-left orientation"); img->orientation = ORIENTATION_TOPLEFT; /* fall thru... */ case ORIENTATION_TOPLEFT: y = h-1; break; } return (y); }
static int cpData(TIFF *in, TIFF *out, const uint32_t nrow) { tsize_t scSize = TIFFScanlineSize(in); tdata_t buf = _TIFFmalloc(scSize); if (!buf) return 0; _TIFFmemset(buf, 0, scSize); for (uint32_t irow = 0; irow < nrow; irow++) { try { if (TIFFReadScanline(in, buf, irow, 0) < 0) { throw -1; } if (TIFFWriteScanline(out, buf, irow, 0) < 0) { throw -2; } } catch (int err) { if (err == -1) { std::cerr << "Cannot read scanline " << irow; std::cerr << " from " << TIFFFileName(in) << std::endl; } else if (err == -2) { std::cerr << "Cannot write scanline " << irow; std::cerr << " to " << TIFFFileName(out) << std::endl; } else { std::cerr << "Unknown error during row copy" << std::endl; } _TIFFfree(buf); return 0; } } _TIFFfree(buf); return 1; }
static int tiffcvt(TIFF* in, TIFF* out) { uint32 width, height; /* image width & height */ uint32* raster; /* retrieve RGBA image */ uint16 shortv; float floatv; char *stringv; uint32 longv; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32)); if (raster == 0) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return (0); } if (!TIFFReadRGBAImage(in, width, height, raster, 0)) { _TIFFfree(raster); return (0); } CopyField(TIFFTAG_SUBFILETYPE, longv); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(out, TIFFTAG_IMAGELENGTH, height); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_COMPRESSION, compression); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR); if (compression == COMPRESSION_JPEG) TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW); CopyField(TIFFTAG_FILLORDER, shortv); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3); CopyField(TIFFTAG_XRESOLUTION, floatv); CopyField(TIFFTAG_YRESOLUTION, floatv); CopyField(TIFFTAG_RESOLUTIONUNIT, shortv); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); { char buf[2048]; char *cp = strrchr(TIFFFileName(in), '/'); sprintf(buf, "YCbCr conversion of %s", cp ? cp+1 : TIFFFileName(in)); TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, buf); } TIFFSetField(out, TIFFTAG_SOFTWARE, TIFFGetVersion()); CopyField(TIFFTAG_DOCUMENTNAME, stringv); TIFFSetField(out, TIFFTAG_REFERENCEBLACKWHITE, refBlackWhite); TIFFSetField(out, TIFFTAG_YCBCRSUBSAMPLING, horizSubSampling, vertSubSampling); TIFFSetField(out, TIFFTAG_YCBCRPOSITIONING, YCBCRPOSITION_CENTERED); TIFFSetField(out, TIFFTAG_YCBCRCOEFFICIENTS, ycbcrCoeffs); rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); return (cvtRaster(out, raster, width, height)); }
void printTIF(TIFF* tif, int pageNumber) { uint32 w, h; uint16 unit; float xres, yres; tstrip_t s, ns; TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres)) { TIFFWarning(TIFFFileName(tif), "No x-resolution, assuming %g dpi", defxres); xres = defxres; } if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres)) { TIFFWarning(TIFFFileName(tif), "No y-resolution, assuming %g lpi", defyres); yres = defyres; /* XXX */ } if (TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &unit) && unit == RESUNIT_CENTIMETER) { xres *= 25.4; yres *= 25.4; } printf("%%%%Page: \"%d\" %d\n", pageNumber, pageNumber); printf("/$pageTop save def gsave\n"); if (scaleToPage) { float yscale = pageHeight / (h/yres); float xscale = pageWidth / (w/xres); printf("%d %d translate\n", (int) (((basePageWidth - pageWidth) * points) * half), (int)((yscale*(h/yres)*points) + (basePageHeight - pageHeight) * points * half) ); printf("%g %g scale\n", (72.*xscale)/xres, -(72.*yscale)/yres); } else { printf("%d %d translate\n", (int) ((basePageWidth - pageWidth) * points * half), (int)((72.*h/yres) + (basePageHeight - pageHeight) * points * half) ); printf("%g %g scale\n", 72./xres, -72./yres); } printf("0 setgray\n"); TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, printruns); ns = TIFFNumberOfStrips(tif); row = 0; for (s = 0; s < ns; s++) (void) TIFFReadEncodedStrip(tif, s, (tdata_t) NULL, (tsize_t) -1); printf("p\n"); printf("grestore $pageTop restore\n"); totalPages++; }
int TIFFImageIterGet(TIFFImageIter* img, void *udata, uint32 w, uint32 h) { if (img->get == NULL) { TIFFError(TIFFFileName(img->tif), "No \"get\" routine setup"); return (0); } if (img->callback.any == NULL) { TIFFError(TIFFFileName(img->tif), "No \"put\" routine setupl; probably can not handle image format"); return (0); } return (*img->get)(img, udata, w, h); }
int TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { if (img->get == NULL) { TIFFError(TIFFFileName(img->tif), "No \"get\" routine setup"); return (0); } if (img->put.any == NULL) { TIFFError(TIFFFileName(img->tif), "No \"put\" routine setupl; probably can not handle image format"); return (0); } return (*img->get)(img, raster, w, h); }
/* * Get a strip-organized image that has * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 */ boolean TIFFRasterImpl::gtStripContig( const RGBvalue* Map, u_long h, u_long w ) { u_char* buf = new u_char[TIFFStripSize(tif_)]; if (buf == nil) { TIFFError(TIFFFileName(tif_), "No space for strip buffer"); return (false); } tileContigRoutine put = pickTileContigCase(Map); u_long y = setorientation(h); int toskew = (int)(orientation_ == ORIENTATION_TOPLEFT ? -w + -w : -w + w); u_long rowsperstrip = (u_long) -1L; TIFFGetField(tif_, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); u_long imagewidth; TIFFGetField(tif_, TIFFTAG_IMAGEWIDTH, &imagewidth); int scanline = TIFFScanlineSize(tif_); int fromskew = (int)(w < imagewidth ? imagewidth - w : 0); for (u_long row = 0; row < h; row += rowsperstrip) { u_int nrow = u_int(row + rowsperstrip > h ? h - row : rowsperstrip); if (TIFFReadEncodedStrip( tif_, TIFFComputeStrip(tif_, row, 0), buf, nrow*scanline) < 0 ) { break; } (this->*put)(raster_ + y*w, buf, Map, w, nrow, fromskew, toskew); y += (orientation_ == ORIENTATION_TOPLEFT ? -nrow : nrow); } delete buf; return true; }
/* * Construct a mapping table to convert from the range * of the data samples to [0,255] --for display. This * process also handles inverting B&W images when needed. */ static int setupMap(TIFFRGBAImage* img) { int32 x, range; range = (int32)((1L<<img->bitspersample)-1); img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue)); if (img->Map == NULL) { TIFFError(TIFFFileName(img->tif), "No space for photometric conversion table"); return (0); } if (img->photometric == PHOTOMETRIC_MINISWHITE) { for (x = 0; x <= range; x++) img->Map[x] = ((range - x) * 255) / range; } else { for (x = 0; x <= range; x++) img->Map[x] = (x * 255) / range; } if (img->bitspersample <= 8 && (img->photometric == PHOTOMETRIC_MINISBLACK || img->photometric == PHOTOMETRIC_MINISWHITE)) { /* * Use photometric mapping table to construct * unpacking tables for samples <= 8 bits. */ if (!makebwmap(img)) return (0); /* no longer need Map, free it */ _TIFFfree(img->Map), img->Map = NULL; } return (1); }
/* * Get an tile-organized image that has * SamplesPerPixel > 1 * PlanarConfiguration separated * We assume that all such images are RGB. */ static int gtTileSeparate(TIFFImageIter* img, void *udata, uint32 w, uint32 h) { TIFF* tif = img->tif; ImageIterTileSeparateRoutine callback = img->callback.separate; uint16 orientation; uint32 col, row; uint32 tw, th; u_char* buf; u_char* r; u_char* g; u_char* b; u_char* a; tsize_t tilesize; int32 fromskew; int alpha = img->alpha; uint32 nrow; tilesize = TIFFTileSize(tif); buf = (u_char*) _TIFFmalloc(4*tilesize); if (buf == 0) { TIFFError(TIFFFileName(tif), "No space for tile buffer"); return (0); } r = buf; g = r + tilesize; b = g + tilesize; a = b + tilesize; if (!alpha) memset(a, 0xff, tilesize); TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); orientation = img->orientation; for (row = 0; row < h; row += th) { nrow = (row + th > h ? h - row : th); for (col = 0; col < w; col += tw) { if (TIFFReadTile(tif, r, col, row,0,0) < 0 && img->stoponerr) break; if (TIFFReadTile(tif, g, col, row,0,1) < 0 && img->stoponerr) break; if (TIFFReadTile(tif, b, col, row,0,2) < 0 && img->stoponerr) break; if (alpha && TIFFReadTile(tif,a,col,row,0,3) < 0 && img->stoponerr) break; if (col + tw > w) { /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ uint32 npix = w - col; fromskew = tw - npix; (*callback)(img, udata, col, row, npix, nrow, fromskew, r, g, b, a); } else { (*callback)(img, udata, col, row, tw, nrow, 0, r, g, b, a); } } } _TIFFfree(buf); return (1); }
static int cpTiles(TIFF* in, TIFF* out) { tsize_t bufsize = TIFFTileSize(in); unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); if (buf) { ttile_t t, nt = TIFFNumberOfTiles(in); tsize_t *bytecounts; TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts); for (t = 0; t < nt; t++) { if (bytecounts[t] > bufsize) { buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[t]); if (!buf) goto bad; bufsize = bytecounts[t]; } if (TIFFReadRawTile(in, t, buf, bytecounts[t]) < 0 || TIFFWriteRawTile(out, t, buf, bytecounts[t]) < 0) { _TIFFfree(buf); return 0; } } _TIFFfree(buf); return 1; } bad: TIFFError(TIFFFileName(in), "Can't allocate space for tile buffer."); return (0); }
/* * Construct any mapping table used * by the associated put routine. */ static int buildMap(TIFFRGBAImage* img) { switch (img->photometric) { case PHOTOMETRIC_RGB: case PHOTOMETRIC_YCBCR: case PHOTOMETRIC_SEPARATED: if (img->bitspersample == 8) break; /* fall thru... */ case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISWHITE: if (!setupMap(img)) return (0); break; case PHOTOMETRIC_PALETTE: /* * Convert 16-bit colormap to 8-bit (unless it looks * like an old-style 8-bit colormap). */ if (checkcmap(img) == 16) cvtcmap(img); else TIFFWarning(TIFFFileName(img->tif), "Assuming 8-bit colormap"); /* * Use mapping table and colormap to construct * unpacking tables for samples < 8 bits. */ if (img->bitspersample <= 8 && !makecmap(img)) return (0); break; } return (1); }
static int cpStrips(TIFF* in, TIFF* out) { tsize_t bufsize = TIFFStripSize(in); unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize); if (buf) { tstrip_t s, ns = TIFFNumberOfStrips(in); tsize_t *bytecounts; TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts); for (s = 0; s < ns; s++) { if (bytecounts[s] > bufsize) { buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[s]); if (!buf) goto bad; bufsize = bytecounts[s]; } if (TIFFReadRawStrip(in, s, buf, bytecounts[s]) < 0 || TIFFWriteRawStrip(out, s, buf, bytecounts[s]) < 0) { _TIFFfree(buf); return 0; } } _TIFFfree(buf); return 1; } bad: TIFFError(TIFFFileName(in), "Can't allocate space for strip buffer."); return 0; }
/* * Get a strip-organized image that has * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 */ static int gtStripContig(TIFFImageIter* img, void *udata, uint32 w, uint32 h) { TIFF* tif = img->tif; ImageIterTileContigRoutine callback = img->callback.contig; uint16 orientation; uint32 row, nrow; u_char* buf; uint32 rowsperstrip; uint32 imagewidth = img->width; tsize_t scanline; int32 fromskew; buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif)); if (buf == 0) { TIFFError(TIFFFileName(tif), "No space for strip buffer"); return (0); } orientation = img->orientation; TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += rowsperstrip) { nrow = (row + rowsperstrip > h ? h - row : rowsperstrip); if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), buf, nrow*scanline) < 0 && img->stoponerr) break; (*callback)(img, udata, 0, row, w, nrow, fromskew, buf); } _TIFFfree(buf); return (1); }
int main(int argc, char* argv[]) { TIFF *tif1, *tif2; int c, dirnum; extern int optind; while ((c = getopt(argc, argv, "ltz")) != -1) switch (c) { case 'l': stopondiff = 0; break; case 'z': stopondiff += 100; break; case 't': stoponfirsttag = 0; break; case '?': usage(); /*NOTREACHED*/ } if (argc - optind < 2) usage(); tif1 = TIFFOpen(argv[optind], "r"); if (tif1 == NULL) return (-1); tif2 = TIFFOpen(argv[optind+1], "r"); if (tif2 == NULL) return (-2); dirnum = 0; while (tiffcmp(tif1, tif2)) { if (!TIFFReadDirectory(tif1)) { if (!TIFFReadDirectory(tif2)) break; printf("No more directories for %s\n", TIFFFileName(tif1)); return (1); } else if (!TIFFReadDirectory(tif2)) { printf("No more directories for %s\n", TIFFFileName(tif2)); return (1); } printf("Directory %d:\n", ++dirnum); } return (0); }
static int checkcmap(TIFF* tif, int n, uint16* r, uint16* g, uint16* b) { while (n-- > 0) if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) return (16); TIFFWarning(TIFFFileName(tif), "Assuming 8-bit colormap"); return (8); }
int main(int argc, char* argv[]) { TIFF* in; TIFF* out; int c; while ((c = getopt(argc, argv, "w:h:c:")) != -1) { switch (c) { case 'w': tnw = strtoul(optarg, NULL, 0); break; case 'h': tnh = strtoul(optarg, NULL, 0); break; case 'c': contrast = streq(optarg, "exp50") ? EXP50 : streq(optarg, "exp60") ? EXP60 : streq(optarg, "exp70") ? EXP70 : streq(optarg, "exp80") ? EXP80 : streq(optarg, "exp90") ? EXP90 : streq(optarg, "exp") ? EXP : streq(optarg, "linear")? LINEAR : EXP; break; default: usage(); } } if (argc-optind != 2) usage(); out = TIFFOpen(argv[optind+1], "w"); if (out == NULL) return 2; in = TIFFOpen(argv[optind], "r"); if( in == NULL ) return 2; thumbnail = (uint8*) _TIFFmalloc(tnw * tnh); if (!thumbnail) { TIFFError(TIFFFileName(in), "Can't allocate space for thumbnail buffer."); return 1; } if (in != NULL) { initScale(); do { if (!generateThumbnail(in, out)) goto bad; if (!cpIFD(in, out) || !TIFFWriteDirectory(out)) goto bad; } while (TIFFReadDirectory(in)); (void) TIFFClose(in); } (void) TIFFClose(out); return 0; bad: (void) TIFFClose(out); return 1; }
/* * Get a strip-organized image with * SamplesPerPixel > 1 * PlanarConfiguration separated * We assume that all such images are RGB. */ static int gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { TIFF* tif = img->tif; tileSeparateRoutine put = img->put.separate; uint16 orientation; u_char *buf; u_char *r, *g, *b, *a; uint32 row, y, nrow; tsize_t scanline; uint32 rowsperstrip; uint32 imagewidth = img->width; tsize_t stripsize; int32 fromskew, toskew; int alpha = img->alpha; stripsize = TIFFStripSize(tif); r = buf = (u_char *)_TIFFmalloc(4*stripsize); if (buf == 0) { TIFFError(TIFFFileName(tif), "No space for tile buffer"); return (0); } g = r + stripsize; b = g + stripsize; a = b + stripsize; if (!alpha) memset(a, 0xff, stripsize); y = setorientation(img, h); orientation = img->orientation; toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? w+w : w-w); TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += rowsperstrip) { nrow = (row + rowsperstrip > h ? h - row : rowsperstrip); if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), r, nrow*scanline) < 0 && img->stoponerr) break; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1), g, nrow*scanline) < 0 && img->stoponerr) break; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2), b, nrow*scanline) < 0 && img->stoponerr) break; if (alpha && (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 3), a, nrow*scanline) < 0 && img->stoponerr)) break; (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, r, g, b, a); y += (orientation == ORIENTATION_TOPLEFT ? -(int32) nrow : (int32) nrow); } _TIFFfree(buf); return (1); }
static void cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type) { switch (type) { case TIFF_SHORT: if (count == 1) { uint16 shortv; CopyField(tag, shortv); } else if (count == 2) { uint16 shortv1, shortv2; CopyField2(tag, shortv1, shortv2); } else if (count == 4) { uint16 *tr, *tg, *tb, *ta; CopyField4(tag, tr, tg, tb, ta); } else if (count == (uint16) -1) { uint16 shortv1; uint16* shortav; CopyField2(tag, shortv1, shortav); } break; case TIFF_LONG: { uint32 longv; CopyField(tag, longv); } break; case TIFF_RATIONAL: if (count == 1) { float floatv; CopyField(tag, floatv); } else if (count == (uint16) -1) { float* floatav; CopyField(tag, floatav); } break; case TIFF_ASCII: { char* stringv; CopyField(tag, stringv); } break; case TIFF_DOUBLE: if (count == 1) { double doublev; CopyField(tag, doublev); } else if (count == (uint16) -1) { double* doubleav; CopyField(tag, doubleav); } break; default: TIFFError(TIFFFileName(in), "Data type %d is not supported, tag %d skipped.", tag, type); } }
/* * Get an tile-organized image that has * SamplesPerPixel > 1 * PlanarConfiguration separated * We assume that all such images are RGB. */ boolean TIFFRasterImpl::gtTileSeparate( const RGBvalue* Map, u_long h, u_long w ) { u_long tilesize = TIFFTileSize(tif_); u_char* buf = new u_char[3*tilesize]; if (buf == nil) { TIFFError(TIFFFileName(tif_), "No space for tile buffer"); return false; } u_char* r = buf; u_char* g = r + tilesize; u_char* b = g + tilesize; tileSeparateRoutine put = pickTileSeparateCase(Map); u_long tw; TIFFGetField(tif_, TIFFTAG_TILEWIDTH, &tw); u_long th; TIFFGetField(tif_, TIFFTAG_TILELENGTH, &th); u_long y = setorientation(h); int toskew = (int)(orientation_ == ORIENTATION_TOPLEFT ? -tw+-w : -tw+w); for (u_long row = 0; row < h; row += th) { u_long nrow = (row + th > h ? h - row : th); for (u_long col = 0; col < w; col += tw) { if (TIFFReadTile(tif_, r, col, row, 0, 0) < 0) { break; } if (TIFFReadTile(tif_, g, col, row, 0, 1) < 0) { break; } if (TIFFReadTile(tif_, b, col, row, 0, 2) < 0) { break; } if (col + tw > w) { /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ u_long npix = w - col; int fromskew = (int)(tw - npix); (this->*put)( raster_ + y*w + col, r, g, b, Map, npix, nrow, fromskew, toskew + fromskew ); } else (this->*put)( raster_ + y*w + col, r, g, b, Map, tw, nrow, 0, toskew ); } y += (orientation_ == ORIENTATION_TOPLEFT ? -nrow : nrow); } delete buf; return true; }
/* * Get a strip-organized image with * SamplesPerPixel > 1 * PlanarConfiguration separated * We assume that all such images are RGB. */ static int gtStripSeparate(TIFFImageIter* img, void *udata, uint32 w, uint32 h) { TIFF* tif = img->tif; ImageIterTileSeparateRoutine callback = img->callback.separate; uint16 orientation; u_char *buf; u_char *r, *g, *b, *a; uint32 row, nrow; tsize_t scanline; uint32 rowsperstrip; uint32 imagewidth = img->width; tsize_t stripsize; int32 fromskew; int alpha = img->alpha; stripsize = TIFFStripSize(tif); r = buf = (u_char *)_TIFFmalloc(4*stripsize); if (buf == 0) { TIFFError(TIFFFileName(tif), "No space for tile buffer"); return (0); } g = r + stripsize; b = g + stripsize; a = b + stripsize; if (!alpha) memset(a, 0xff, stripsize); orientation = img->orientation; TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += rowsperstrip) { nrow = (row + rowsperstrip > h ? h - row : rowsperstrip); if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), r, nrow*scanline) < 0 && img->stoponerr) break; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1), g, nrow*scanline) < 0 && img->stoponerr) break; if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2), b, nrow*scanline) < 0 && img->stoponerr) break; if (alpha && (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 3), a, nrow*scanline) < 0 && img->stoponerr)) break; (*callback)(img, udata, 0, row, w, nrow, fromskew, r, g, b, a); } _TIFFfree(buf); return (1); }
/* * Palette images with <= 8 bits/sample are handled * with a table to avoid lots of shifts and masks. The table * is setup so that put*cmaptile (below) can retrieve 8/bitspersample * pixel values simply by indexing into the table with one * number. */ static int makecmap(TIFFRGBAImage* img) { int bitspersample = img->bitspersample; int nsamples = 8 / bitspersample; uint16* r = img->redcmap; uint16* g = img->greencmap; uint16* b = img->bluecmap; uint32 *p; int i; img->PALmap = (uint32**) _TIFFmalloc( 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); if (img->PALmap == NULL) { TIFFError(TIFFFileName(img->tif), "No space for Palette mapping table"); return (0); } p = (uint32*)(img->PALmap + 256); for (i = 0; i < 256; i++) { TIFFRGBValue c; img->PALmap[i] = p; #define CMAP(x) c = x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff); switch (bitspersample) { case 1: CMAP(i>>7); CMAP((i>>6)&1); CMAP((i>>5)&1); CMAP((i>>4)&1); CMAP((i>>3)&1); CMAP((i>>2)&1); CMAP((i>>1)&1); CMAP(i&1); break; case 2: CMAP(i>>6); CMAP((i>>4)&3); CMAP((i>>2)&3); CMAP(i&3); break; case 4: CMAP(i>>4); CMAP(i&0xf); break; case 8: CMAP(i); break; } #undef CMAP } return (1); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int TiffUtilities::readTiffAsGrayScale(TIFF* in, TiffImage* data) { unsigned char* raster; /* retrieve RGBA image */ int32_t pixel_count; unsigned char* src = static_cast<unsigned char*>(NULL); unsigned char* dst = static_cast<unsigned char*>(NULL); tsize_t totalBytes; unsigned char r, g, b; float R,G,B; // This will eventually be TOO much data but we need it to read the initial data totalBytes = data->width * data->height * 4; raster = (unsigned char*)_TIFFmalloc( totalBytes ); if (raster == NULL) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return 0; } // TIFFReadRGBAImageOriented converts non 8bit images including: // Grayscale, bilevel, CMYK, and YCbCR transparently into 32bit RGBA // samples /* Read the image in one chunk into an RGBA array */ if (!TIFFReadRGBAImageOriented(in, (data->width), (data->height), (unsigned int*)(raster), ORIENTATION_TOPLEFT, 0)) { _TIFFfree(raster); return 0; } // Collapse the data down to a single channel, that will end up // being the grayscale values pixel_count = (data->height) * (data->width); // The collapse is done IN PLACE src = raster; dst = raster; while (pixel_count > 0) { PIXEL24_TO_GREYVALUE(src, *(dst)); dst++; src += 4; //skip ahead by 4 bytes because we read the raw array into an RGBA array. pixel_count--; } (void) TIFFClose(in); // Close the tiff structures data->imageData = raster; return 1; }
/* * Get a strip-organized image that has * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 * * Hacked from the tif_getimage.c file. * * This is set up to allow us to just copy the data to the raster * for 1-bit bitmaps */ static int getStripContig1Bit(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { TIFF* tif = img->tif; tileContigRoutine put = img->put.contig; uint16 orientation; uint32 row, y, nrow, rowstoread; uint32 pos; u_char* buf; uint32 rowsperstrip; uint32 imagewidth = img->width; tsize_t scanline; int32 fromskew, toskew; tstrip_t strip; tsize_t stripsize; u_char* braster = (u_char*)raster; // byte wide raster uint32 wb = WIDTHBYTES(w); int ret = 1; buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif)); if (buf == 0) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); return (0); } y = setorientation(img, h); orientation = img->orientation; toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? wb+wb : wb-wb); TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0)/8; for (row = 0; row < h; row += nrow) { rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; nrow = (row + rowstoread > h ? h - row : rowstoread); strip = TIFFComputeStrip(tif,row+img->row_offset, 0); stripsize = ((row + img->row_offset)%rowsperstrip + nrow) * scanline; if (TIFFReadEncodedStrip(tif, strip, buf, stripsize ) < 0 && img->stoponerr) { ret = 0; break; } pos = ((row + img->row_offset) % rowsperstrip) * scanline; (*put)(img, (uint32*)(braster+y*wb), 0, y, w, nrow, fromskew, toskew, buf + pos); y += (orientation == ORIENTATION_TOPLEFT ?-(int32) nrow : (int32) nrow); } _TIFFfree(buf); return (ret); }
/* * Greyscale images with less than 8 bits/sample are handled * with a table to avoid lots of shifts and masks. The table * is setup so that put*bwtile (below) can retrieve 8/bitspersample * pixel values simply by indexing into the table with one * number. */ static int makebwmap(TIFFRGBAImage* img) { TIFFRGBValue* Map = img->Map; int bitspersample = img->bitspersample; int nsamples = 8 / bitspersample; int i; uint32* p; img->BWmap = (uint32**) _TIFFmalloc( 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); if (img->BWmap == NULL) { TIFFError(TIFFFileName(img->tif), "No space for B&W mapping table"); return (0); } p = (uint32*)(img->BWmap + 256); for (i = 0; i < 256; i++) { TIFFRGBValue c; img->BWmap[i] = p; switch (bitspersample) { #define GREY(x) c = Map[x]; *p++ = PACK(c,c,c); case 1: GREY(i>>7); GREY((i>>6)&1); GREY((i>>5)&1); GREY((i>>4)&1); GREY((i>>3)&1); GREY((i>>2)&1); GREY((i>>1)&1); GREY(i&1); break; case 2: GREY(i>>6); GREY((i>>4)&3); GREY((i>>2)&3); GREY(i&3); break; case 4: GREY(i>>4); GREY(i&0xf); break; case 8: GREY(i); break; } #undef GREY } return (1); }
/* * Palette images with <= 8 bits/sample are handled * with a table to avoid lots of shifts and masks. The table * is setup so that put*cmaptile (below) can retrieve 8/bitspersample_ * pixel values simply by indexing into the table with one * number. */ boolean TIFFRasterImpl::makecmap( const u_short* rmap, const u_short* gmap, const u_short* bmap ) { register int i; int nsamples = 8 / bitspersample_; register u_long *p; PALmap_ = (u_long **)malloc( 256*sizeof (u_long *)+(256*nsamples*sizeof(u_long)) ); if (PALmap_ == nil) { TIFFError(TIFFFileName(tif_), "No space for Palette mapping table"); return (false); } p = (u_long *)(PALmap_ + 256); for (i = 0; i < 256; i++) { PALmap_[i] = p; #define CMAP(x) \ c = x; *p++ = PACK(rmap[c]&0xff, gmap[c]&0xff, bmap[c]&0xff); switch (bitspersample_) { register RGBvalue c; case 1: CMAP(i>>7); CMAP((i>>6)&1); CMAP((i>>5)&1); CMAP((i>>4)&1); CMAP((i>>3)&1); CMAP((i>>2)&1); CMAP((i>>1)&1); CMAP(i&1); break; case 2: CMAP(i>>6); CMAP((i>>4)&3); CMAP((i>>2)&3); CMAP(i&3); break; case 4: CMAP(i>>4); CMAP(i&0xf); break; case 8: CMAP(i); break; } #undef CMAP } return (true); }
/* * Get an tile-organized image that has * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 */ static int gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { TIFF* tif = img->tif; tileContigRoutine put = img->put.contig; uint16 orientation; uint32 col, row, y; uint32 tw, th; u_char* buf; int32 fromskew, toskew; uint32 nrow; buf = (u_char*) _TIFFmalloc(TIFFTileSize(tif)); if (buf == 0) { TIFFError(TIFFFileName(tif), "No space for tile buffer"); return (0); } TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); y = setorientation(img, h); orientation = img->orientation; toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? tw+w : tw-w); for (row = 0; row < h; row += th) { nrow = (row + th > h ? h - row : th); for (col = 0; col < w; col += tw) { if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0 && img->stoponerr) break; if (col + tw > w) { /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ uint32 npix = w - col; fromskew = tw - npix; (*put)(img, raster+y*w+col, col, y, npix, nrow, fromskew, toskew + fromskew, buf); } else { (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf); } } y += (orientation == ORIENTATION_TOPLEFT ? -(int32) nrow : (int32) nrow); } _TIFFfree(buf); return (1); }
static void CheckAndCorrectColormap(TIFF* tif, int n, uint16* r, uint16* g, uint16* b) { int i; for (i = 0; i < n; i++) if (r[i] >= 256 || g[i] >= 256 || b[i] >= 256) return; TIFFWarning(TIFFFileName(tif), "Scaling 8-bit colormap"); #define CVT(x) (((x) * ((1L<<16)-1)) / 255) for (i = 0; i < n; i++) { r[i] = CVT(r[i]); g[i] = CVT(g[i]); b[i] = CVT(b[i]); } #undef CVT }
/* Variant of TIFFReadEncodedTile() that does * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has * succeeded. This avoid excessive memory allocation in case of truncated * file. * * calls regular TIFFReadEncodedTile() if *buf != NULL */ tmsize_t _TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, void **buf, tmsize_t bufsizetoalloc, tmsize_t size_to_read) { static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer"; TIFFDirectory *td = &tif->tif_dir; tmsize_t tilesize = tif->tif_tilesize; if( *buf != NULL ) { return TIFFReadEncodedTile(tif, tile, *buf, size_to_read); } if (!TIFFCheckRead(tif, 1)) return ((tmsize_t)(-1)); if (tile >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "%lu: Tile out of range, max %lu", (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tmsize_t)(-1)); } if (!TIFFFillTile(tif,tile)) return((tmsize_t)(-1)); *buf = _TIFFmalloc(bufsizetoalloc); if (*buf == NULL) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); return((tmsize_t)(-1)); } _TIFFmemset(*buf, 0, bufsizetoalloc); if (size_to_read == (tmsize_t)(-1)) size_to_read = tilesize; else if (size_to_read > tilesize) size_to_read = tilesize; if( (*tif->tif_decodetile)(tif, (uint8*) *buf, size_to_read, (uint16)(tile/td->td_stripsperimage))) { (*tif->tif_postdecode)(tif, (uint8*) *buf, size_to_read); return (size_to_read); } else return ((tmsize_t)(-1)); }
/* * Read the specified image into an ABGR-format raster. */ int TIFFReadImageIter(TIFF* tif, uint32 rwidth, uint32 rheight, uint8* raster, int stop) { char emsg[1024]; TIFFImageIter img; int ok; if (TIFFImageIterBegin(&img, tif, stop, emsg)) { /* XXX verify rwidth and rheight against width and height */ ok = TIFFImageIterGet(&img, raster, rwidth, img.height); TIFFImageIterEnd(&img); } else { TIFFError(TIFFFileName(tif), emsg); ok = 0; } return (ok); }