/* * 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); }
int main(int argc, char* argv[]) { uint16 bitspersample, shortv; uint32 imagewidth, imagelength; uint16 config = PLANARCONFIG_CONTIG; uint32 rowsperstrip = (uint32) -1; uint16 photometric = PHOTOMETRIC_RGB; uint16 *rmap, *gmap, *bmap; uint32 row; int cmap = -1; TIFF *in, *out; int c; extern int optind; extern char* optarg; while ((c = getopt(argc, argv, "C:c:p:r:")) != -1) switch (c) { case 'C': /* force colormap interpretation */ cmap = atoi(optarg); break; case 'c': /* compression scheme */ if (!processCompressOptions(optarg)) usage(); break; case 'p': /* planar configuration */ if (streq(optarg, "separate")) config = PLANARCONFIG_SEPARATE; else if (streq(optarg, "contig")) config = PLANARCONFIG_CONTIG; else usage(); break; case 'r': /* rows/strip */ rowsperstrip = atoi(optarg); break; case '?': usage(); /*NOTREACHED*/ } if (argc - optind != 2) usage(); in = TIFFOpen(argv[optind], "r"); if (in == NULL) return (-1); if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &shortv) || shortv != PHOTOMETRIC_PALETTE) { fprintf(stderr, "%s: Expecting a palette image.\n", argv[optind]); return (-1); } if (!TIFFGetField(in, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) { fprintf(stderr, "%s: No colormap (not a valid palette image).\n", argv[optind]); return (-1); } bitspersample = 0; TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample); if (bitspersample != 8) { fprintf(stderr, "%s: Sorry, can only handle 8-bit images.\n", argv[optind]); return (-1); } out = TIFFOpen(argv[optind+1], "w"); if (out == NULL) return (-2); cpTags(in, out); TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imagewidth); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength); if (compression != (uint16)-1) TIFFSetField(out, TIFFTAG_COMPRESSION, compression); else TIFFGetField(in, TIFFTAG_COMPRESSION, &compression); switch (compression) { case COMPRESSION_JPEG: if (jpegcolormode == JPEGCOLORMODE_RGB) photometric = PHOTOMETRIC_YCBCR; else photometric = PHOTOMETRIC_RGB; TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality); TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode); break; case COMPRESSION_LZW: case COMPRESSION_DEFLATE: if (predictor != 0) TIFFSetField(out, TIFFTAG_PREDICTOR, predictor); break; } TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3); TIFFSetField(out, TIFFTAG_PLANARCONFIG, config); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip)); (void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv); if (cmap == -1) cmap = checkcmap(1<<bitspersample, rmap, gmap, bmap); if (cmap == 16) { /* * Convert 16-bit colormap to 8-bit. */ int i; for (i = (1<<bitspersample)-1; i >= 0; i--) { #define CVT(x) (((x) * 255) / ((1L<<16)-1)) rmap[i] = CVT(rmap[i]); gmap[i] = CVT(gmap[i]); bmap[i] = CVT(bmap[i]); } } { unsigned char *ibuf, *obuf; register unsigned char* pp; register uint32 x; ibuf = (unsigned char*)_TIFFmalloc(TIFFScanlineSize(in)); obuf = (unsigned char*)_TIFFmalloc(TIFFScanlineSize(out)); switch (config) { case PLANARCONFIG_CONTIG: for (row = 0; row < imagelength; row++) { if (!TIFFReadScanline(in, ibuf, row, 0)) goto done; pp = obuf; for (x = 0; x < imagewidth; x++) { *pp++ = rmap[ibuf[x]]; *pp++ = gmap[ibuf[x]]; *pp++ = bmap[ibuf[x]]; } if (!TIFFWriteScanline(out, obuf, row, 0)) goto done; } break; case PLANARCONFIG_SEPARATE: for (row = 0; row < imagelength; row++) { if (!TIFFReadScanline(in, ibuf, row, 0)) goto done; for (pp = obuf, x = 0; x < imagewidth; x++) *pp++ = rmap[ibuf[x]]; if (!TIFFWriteScanline(out, obuf, row, 0)) goto done; for (pp = obuf, x = 0; x < imagewidth; x++) *pp++ = gmap[ibuf[x]]; if (!TIFFWriteScanline(out, obuf, row, 0)) goto done; for (pp = obuf, x = 0; x < imagewidth; x++) *pp++ = bmap[ibuf[x]]; if (!TIFFWriteScanline(out, obuf, row, 0)) goto done; } break; } _TIFFfree(ibuf); _TIFFfree(obuf); } done: (void) TIFFClose(in); (void) TIFFClose(out); return (0); }
Image *Read (IStream *file, const Image::ReadOptions& options) { int nrow; int result = 0; long LineSize; TIFF *tif; Image *image ; uint16 BitsPerSample; uint16 BytesPerSample = 1; uint16 PhotometricInterpretation; uint16 SamplePerPixel; uint16 Orientation; uint32 RowsPerStrip; unsigned int width; unsigned int height; // TODO - TIFF files probably have some gamma info in them by default, but we're currently ignorant about that. // Until that is fixed, use whatever the user has chosen as default. GammaCurvePtr gamma; if (options.gammacorrect && options.defaultGamma) gamma = TranscodingGammaCurve::Get(options.workingGamma, options.defaultGamma); // [CLi] TIFF is specified to use associated (= premultiplied) alpha, so that's the preferred mode to use for the image container unless the user overrides // (e.g. to handle a non-compliant file). bool premul = true; if (options.premultiplyOverride) premul = options.premultiply; // Rather than have libTIFF complain about tags it doesn't understand, // we just suppress all the warnings. TIFFSetWarningHandler(SuppressTIFFWarnings); TIFFSetErrorHandler(SuppressTIFFWarnings); // Open and do initial processing tif = TIFFClientOpen("Dummy File Name", "r", file, Tiff_Read, Tiff_Write, Tiff_Seek, Tiff_Close, Tiff_Size, Tiff_Map, Tiff_Unmap); if (!tif) return (NULL) ; // Get basic information about the image int ExtraSamples, ExtraSampleInfo; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample); TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip); TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation); TIFFGetField(tif, TIFFTAG_ORIENTATION, &Orientation); TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel); TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &ExtraSamples, &ExtraSampleInfo); // don't support more than 16 bits per sample if (BitsPerSample == 16) { BytesPerSample = 2 ; options.warnings.push_back ("Warning: reading 16 bits/sample TIFF file; components crunched to 8"); } LineSize = TIFFScanlineSize(tif); assert (SamplePerPixel == (int) (LineSize / width) / BytesPerSample); // SamplePerPixel = (int)(LineSize / width); #if 0 // For now we are ignoring the orientation of the image... switch (Orientation) { case ORIENTATION_TOPLEFT: break; case ORIENTATION_TOPRIGHT: break; case ORIENTATION_BOTRIGHT: break; case ORIENTATION_BOTLEFT: break; case ORIENTATION_LEFTTOP: break; case ORIENTATION_RIGHTTOP: break; case ORIENTATION_RIGHTBOT: break; case ORIENTATION_LEFTBOT: break; default: break; } #endif //PhotometricInterpretation = 2 image is RGB //PhotometricInterpretation = 3 image have a color palette if (PhotometricInterpretation == PHOTOMETRIC_PALETTE && (TIFFIsTiled(tif) == 0)) { uint16 *red, *green, *blue; //load the palette int cmap_len = (1 << BitsPerSample); TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); vector<Image::RGBMapEntry> colormap ; Image::RGBMapEntry entry; // I may be mistaken, but it appears that alpha/opacity information doesn't // appear in a Paletted Tiff image. Well - if it does, it's not as easy to // get at as RGB. // Read the palette // Is the palette 16 or 8 bits ? if (checkcmap(cmap_len, red, green, blue) == 16) { for (int i=0;i<cmap_len;i++) { entry.red = IntDecode(gamma, red[i], 65535); entry.green = IntDecode(gamma, green[i], 65535); entry.blue = IntDecode(gamma, blue[i], 65535); colormap.push_back (entry); } } else { for (int i=0;i<cmap_len;i++) { entry.red = IntDecode(gamma, red[i], 255); entry.green = IntDecode(gamma, green[i], 255); entry.blue = IntDecode(gamma, blue[i], 255); colormap.push_back (entry); } } Image::ImageDataType imagetype = options.itype; if (imagetype == Image::Undefined) imagetype = Image::Colour_Map; image = Image::Create (width, height, imagetype, colormap) ; image->SetPremultiplied(premul); // specify whether the color map data has premultiplied alpha boost::scoped_array<unsigned char> buf (new unsigned char [TIFFStripSize(tif)]); //read the tiff lines and save them in the image //with RGB mode, we have to change the order of the 3 samples RGB <=> BGR for (int row=0;row<height;row+=RowsPerStrip) { nrow = (row + (int)RowsPerStrip > height ? height - row : RowsPerStrip); TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), buf.get(), nrow * LineSize); for (int l = 0, offset = 0; l < nrow ; l++, offset += LineSize) for (int x = 0 ; x < width ; x++) image->SetIndexedValue (x, row+l, buf[offset+x]) ; } } else { // Allocate the row buffers for the image boost::scoped_array<uint32> buf (new uint32 [width * height]) ; Image::ImageDataType imagetype = options.itype; if (imagetype == Image::Undefined) imagetype = ( GammaCurve::IsNeutral(gamma) ? Image::RGBA_Int8 : Image::RGBA_Gamma8 ); image = Image::Create (width, height, imagetype) ; image->SetPremultiplied(premul); // set desired storage mode regarding alpha premultiplication image->TryDeferDecoding(gamma, 255); // try to have gamma adjustment being deferred until image evaluation. TIFFReadRGBAImage(tif, width, height, buf.get(), 0); uint32 abgr, *tbuf = buf.get(); for (int i=height-1;i>=0;i--) { for (int j=0;j<width;j++) { abgr = *tbuf++; unsigned int b = (unsigned char)TIFFGetB(abgr); unsigned int g = (unsigned char)TIFFGetG(abgr); unsigned int r = (unsigned char)TIFFGetR(abgr); unsigned int a = (unsigned char)TIFFGetA(abgr); SetEncodedRGBAValue(image, j, i, gamma, 255, r, g, b, a, premul) ; } } } TIFFClose(tif); return (image) ; }
unsigned char * simage_tiff_load(std::istream& fin, int& width_ret, int& height_ret, int& numComponents_ret, uint16& bitspersample) { TIFF *in; uint16 dataType; uint16 samplesperpixel; uint16 photometric; uint32 w, h; uint16 config; uint16* red; uint16* green; uint16* blue; unsigned char *inbuf = NULL; tsize_t rowsize; uint32 row; int format; unsigned char *buffer; int width; int height; unsigned char *currPtr; TIFFSetErrorHandler(tiff_error); TIFFSetWarningHandler(tiff_warn); in = TIFFClientOpen("inputstream", "r", (thandle_t)&fin, libtiffStreamReadProc, //Custom read function libtiffStreamWriteProc, //Custom write function libtiffStreamSeekProc, //Custom seek function libtiffStreamCloseProc, //Custom close function libtiffStreamSizeProc, //Custom size function libtiffStreamMapProc, //Custom map function libtiffStreamUnmapProc); //Custom unmap function if (in == NULL) { tifferror = ERR_OPEN; return NULL; } if (TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) == 1) { if (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_PALETTE && photometric != PHOTOMETRIC_MINISWHITE && photometric != PHOTOMETRIC_MINISBLACK) { OSG_NOTICE << "Photometric type "<<photometric<<" not handled; can only handle Grayscale, RGB and Palette images" << std::endl; TIFFClose(in); tifferror = ERR_UNSUPPORTED; return NULL; } } else { tifferror = ERR_READ; TIFFClose(in); return NULL; } if (TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel) == 1) { if (samplesperpixel != 1 && samplesperpixel != 2 && samplesperpixel != 3 && samplesperpixel != 4) { OSG_DEBUG << "Bad samples/pixel" << std::endl; tifferror = ERR_UNSUPPORTED; TIFFClose(in); return NULL; } } else { tifferror = ERR_READ; TIFFClose(in); return NULL; } if (TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample) == 1) { if (bitspersample != 8 && bitspersample != 16 && bitspersample != 32) { OSG_NOTICE << "can only handle 8, 16 and 32 bit samples" << std::endl; TIFFClose(in); tifferror = ERR_UNSUPPORTED; return NULL; } } else { tifferror = ERR_READ; TIFFClose(in); return NULL; } if (TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w) != 1 || TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h) != 1 || TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config) != 1) { TIFFClose(in); tifferror = ERR_READ; return NULL; } TIFFGetField(in, TIFFTAG_DATATYPE, &dataType); OSG_INFO<<"TIFFTAG_DATATYPE="<<dataType<<std::endl; /* if (photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK) format = 1; else format = 3; */ // if it has a palette, data returned is 3 byte rgb // so set format to 3. if (photometric == PHOTOMETRIC_PALETTE) format = 3; else format = samplesperpixel * bitspersample / 8; int bytespersample = bitspersample / 8; int bytesperpixel = bytespersample * samplesperpixel; OSG_INFO<<"format="<<format<<std::endl; OSG_INFO<<"bytespersample="<<bytespersample<<std::endl; OSG_INFO<<"bytesperpixel="<<bytesperpixel<<std::endl; buffer = new unsigned char [w*h*format]; if (!buffer) { tifferror = ERR_MEM; TIFFClose(in); return NULL; } // initialize memory for(unsigned char* ptr=buffer;ptr<buffer+w*h*format;++ptr) *ptr = 0; width = w; height = h; currPtr = buffer + (h-1)*w*format; tifferror = ERR_NO_ERROR; switch (pack(photometric, config)) { case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_CONTIG): case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_CONTIG): case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_SEPARATE): case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_SEPARATE): inbuf = new unsigned char [TIFFScanlineSize(in)]; for (row = 0; row < h; row++) { if (TIFFReadScanline(in, inbuf, row, 0) < 0) { tifferror = ERR_READ; break; } invert_row(currPtr, inbuf, samplesperpixel*w, photometric == PHOTOMETRIC_MINISWHITE, bitspersample); currPtr -= format*w; } break; case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_CONTIG): case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_SEPARATE): if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue) != 1) tifferror = ERR_READ; /* */ /* Convert 16-bit colormap to 8-bit (unless it looks */ /* like an old-style 8-bit colormap). */ /* */ if (!tifferror && checkcmap(1<<bitspersample, red, green, blue) == 16) { int i; for (i = (1<<bitspersample)-1; i >= 0; i--) { red[i] = CVT(red[i]); green[i] = CVT(green[i]); blue[i] = CVT(blue[i]); } } inbuf = new unsigned char [TIFFScanlineSize(in)]; for (row = 0; row < h; row++) { if (TIFFReadScanline(in, inbuf, row, 0) < 0) { tifferror = ERR_READ; break; } remap_row(currPtr, inbuf, w, red, green, blue); currPtr -= format*w; } break; case pack(PHOTOMETRIC_RGB, PLANARCONFIG_CONTIG): inbuf = new unsigned char [TIFFScanlineSize(in)]; for (row = 0; row < h; row++) { if (TIFFReadScanline(in, inbuf, row, 0) < 0) { tifferror = ERR_READ; break; } memcpy(currPtr, inbuf, format*w); currPtr -= format*w; } break; case pack(PHOTOMETRIC_RGB, PLANARCONFIG_SEPARATE): rowsize = TIFFScanlineSize(in); inbuf = new unsigned char [format*rowsize]; for (row = 0; !tifferror && row < h; row++) { int s; for (s = 0; s < format; s++) { if (TIFFReadScanline(in, (tdata_t)(inbuf+s*rowsize), (uint32)row, (tsample_t)s) < 0) { tifferror = ERR_READ; break; } } if (!tifferror) { if (format==3) interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, w, format, bitspersample); else if (format==4) interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, inbuf+3*rowsize, w, format, bitspersample); currPtr -= format*w; } } break; default: tifferror = ERR_UNSUPPORTED; break; } if (inbuf) delete [] inbuf; TIFFClose(in); if (tifferror) { if (buffer) delete [] buffer; return NULL; } width_ret = width; height_ret = height; if (photometric == PHOTOMETRIC_PALETTE) numComponents_ret = format; else numComponents_ret = samplesperpixel; return buffer; }
int main(int argc, char* argv[]) { uint32 rowsperstrip = (uint32) -1; TIFF *in, *out; uint32 w, h; uint16 samplesperpixel; uint16 bitspersample; uint16 config; uint16 photometric; uint16* red; uint16* green; uint16* blue; tsize_t rowsize; register uint32 row; register tsample_t s; unsigned char *inbuf, *outbuf; char thing[1024]; int c; extern int optind; extern char *optarg; while ((c = getopt(argc, argv, "c:r:R:G:B:")) != -1) switch (c) { case 'c': /* compression scheme */ if (!processCompressOptions(optarg)) usage(); break; case 'r': /* rows/strip */ rowsperstrip = atoi(optarg); break; case 'R': RED = PCT(atoi(optarg)); break; case 'G': GREEN = PCT(atoi(optarg)); break; case 'B': BLUE = PCT(atoi(optarg)); break; case '?': usage(); /*NOTREACHED*/ } if (argc - optind < 2) usage(); in = TIFFOpen(argv[optind], "r"); if (in == NULL) return (-1); photometric = 0; TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric); if (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_PALETTE ) { fprintf(stderr, "%s: Bad photometric; can only handle RGB and Palette images.\n", argv[optind]); return (-1); } TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); if (samplesperpixel != 1 && samplesperpixel != 3) { fprintf(stderr, "%s: Bad samples/pixel %u.\n", argv[optind], samplesperpixel); return (-1); } TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample); if (bitspersample != 8) { fprintf(stderr, " %s: Sorry, only handle 8-bit samples.\n", argv[optind]); return (-1); } TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h); TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config); out = TIFFOpen(argv[optind+1], "w"); if (out == NULL) return (-1); cpTags(in, out); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); if (compression != (uint16) -1) { TIFFSetField(out, TIFFTAG_COMPRESSION, compression); switch (compression) { case COMPRESSION_JPEG: TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality); TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode); break; case COMPRESSION_LZW: case COMPRESSION_DEFLATE: if (predictor != 0) TIFFSetField(out, TIFFTAG_PREDICTOR, predictor); break; } } TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); sprintf(thing, "B&W version of %s", argv[optind]); TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, thing); TIFFSetField(out, TIFFTAG_SOFTWARE, "tiff2bw"); outbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out)); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, rowsperstrip)); #define pack(a,b) ((a)<<8 | (b)) switch (pack(photometric, config)) { case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_CONTIG): case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_SEPARATE): TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue); /* * Convert 16-bit colormap to 8-bit (unless it looks * like an old-style 8-bit colormap). */ if (checkcmap(in, 1<<bitspersample, red, green, blue) == 16) { int i; #define CVT(x) (((x) * 255L) / ((1L<<16)-1)) for (i = (1<<bitspersample)-1; i >= 0; i--) { red[i] = CVT(red[i]); green[i] = CVT(green[i]); blue[i] = CVT(blue[i]); } #undef CVT } inbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in)); for (row = 0; row < h; row++) { if (TIFFReadScanline(in, inbuf, row, 0) < 0) break; compresspalette(outbuf, inbuf, w, red, green, blue); if (TIFFWriteScanline(out, outbuf, row, 0) < 0) break; } break; case pack(PHOTOMETRIC_RGB, PLANARCONFIG_CONTIG): inbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in)); for (row = 0; row < h; row++) { if (TIFFReadScanline(in, inbuf, row, 0) < 0) break; compresscontig(outbuf, inbuf, w); if (TIFFWriteScanline(out, outbuf, row, 0) < 0) break; } break; case pack(PHOTOMETRIC_RGB, PLANARCONFIG_SEPARATE): rowsize = TIFFScanlineSize(in); inbuf = (unsigned char *)_TIFFmalloc(3*rowsize); for (row = 0; row < h; row++) { for (s = 0; s < 3; s++) if (TIFFReadScanline(in, inbuf+s*rowsize, row, s) < 0) return (-1); compresssep(outbuf, inbuf, inbuf+rowsize, inbuf+2*rowsize, w); if (TIFFWriteScanline(out, outbuf, row, 0) < 0) break; } break; } #undef pack TIFFClose(out); return (0); }
void PLTIFFDecoder::doLoColor (TIFF * tif, PLBmpBase * pBmp) { uint16 BitsPerSample; uint16 SamplePerPixel; int32 LineSize; int16 PhotometricInterpretation; int row; PLBYTE *pBits; TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample); TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel); TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation); if (PhotometricInterpretation!=PHOTOMETRIC_MINISWHITE && PhotometricInterpretation!=PHOTOMETRIC_MINISBLACK && PhotometricInterpretation!=PHOTOMETRIC_PALETTE) { PhotometricInterpretation = PHOTOMETRIC_MINISWHITE; Trace(2,"unexpected PhotometricInterpretation, default to PHOTOMETRIC_MINISWHITE"); } LineSize = TIFFScanlineSize(tif); //Number of bytes in one line PLPixel32 pPal[256]; pBits = new PLBYTE [LineSize]; // enough for 16-bits per pixel if (pBits == NULL) raiseError (PL_ERRNO_MEMORY, "Out of memory allocating TIFF buffer."); // phase one: build color map if (BitsPerSample < 16) { if /* monochrome (=bitonal) or grayscale */ (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE || PhotometricInterpretation == PHOTOMETRIC_MINISBLACK) { int numColors = 1 << BitsPerSample; PLBYTE step = static_cast<PLBYTE>(255 / (numColors-1)); PLBYTE *pb = (PLBYTE *) (pPal); int offset = sizeof(PLPixel32); if (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE) { pb += (numColors-1) * sizeof(PLPixel32); offset = -offset; } // warning: the following ignores possible halftone hints for (int i = 0; i < numColors; ++i, pb += offset) { pb[PL_RGBA_RED] = pb[PL_RGBA_GREEN] = pb[PL_RGBA_BLUE] = static_cast<PLBYTE>(i * step); pb[PL_RGBA_ALPHA] = 255; } } //PhotometricInterpretation = 2 image is RGB //PhotometricInterpretation = 3 image has a color palette else if (PhotometricInterpretation == PHOTOMETRIC_PALETTE) { uint16* red; uint16* green; uint16* blue; int16 Palette16Bits; // we get pointers to libtiff-owned colormaps TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); //Is the palette 16 or 8 bits ? Palette16Bits = checkcmap(1<<BitsPerSample, red, green, blue) == 16; //load the palette in the DIB for (int i = 0; i < 1<<BitsPerSample; ++i) { PLBYTE *pb = (PLBYTE *) ((pPal)+i); pb[PL_RGBA_RED ] = (PLBYTE) (Palette16Bits ? CVT( red[i]) : red[i]); pb[PL_RGBA_GREEN] = (PLBYTE) (Palette16Bits ? CVT(green[i]) : green[i]); pb[PL_RGBA_BLUE ] = (PLBYTE) (Palette16Bits ? CVT( blue[i]) : blue[i]); pb[PL_RGBA_ALPHA] = 255; } } else Trace( 2, "unexpected PhotometricInterpretation in PLTIFFDecoder::DoLoColor()" ); } // phase two: read image itself //generally, TIFF images are ordered from upper-left to bottom-right // we implicitly assume PLANARCONFIG_CONTIG PLBYTE **pLineArray = pBmp->GetLineArray(); if (BitsPerSample > 16) Trace( 2, "unexpected bit-depth in PLTIFFDecoder::DoLoColor()" ); else for ( row = 0; row < GetHeight(); ++row ) { uint16 x; int status = TIFFReadScanline( tif, pBits, row, 0 ); if (status == -1 && row < GetHeight() / 3) { delete [] pBits; // we should maybe free the BMP memory as well... raiseError (PL_ERRINTERNAL, m_szLastErr); } /* if (BitsPerSample == 1) // go ahead, waste space ;-) for (x=0; x < imageWidth; ++x) pLineArray[row][x] = pBits[x / 8] & (128 >> (x & 7)) ? 1 : 0; else */ if (BitsPerSample == 4) { for (x=0; x < GetWidth() / 2; ++x) { pLineArray[row][2*x ] = (pBits[x] & 0xf0) >> 4; pLineArray[row][2*x+1] = (pBits[x] & 0x0f); } // odd number of pixels if (GetWidth() & 1) pLineArray[row][GetWidth()-1] = (pBits[x] & 0xf0) >> 4; } else if (BitsPerSample == 16) { PLASSERT (SamplePerPixel == 1); // can't do 16-bit with alpha yet PLPixel16 **pLineArray16 = pBmp->GetLineArray16(); memcpy( pLineArray16[row], pBits, LineSize ); } else //if (BitsPerSample == 8 || BitsPerSample == 1) if (SamplePerPixel == 1) memcpy( pLineArray[row], pBits, LineSize ); else { // We've got an 8 bit image with an alpha channel. // Ignore the alpha channel. PLASSERT (BitsPerSample == 8); for (x=0; x < GetWidth(); ++x) pLineArray[row][x] = pBits[x*2]; } }
HDIB LoadTIFFinDIB(LPSTR lpFileName) { TIFF *tif; unsigned long imageLength; unsigned long imageWidth; unsigned int BitsPerSample; unsigned long LineSize; unsigned int SamplePerPixel; unsigned long RowsPerStrip; int PhotometricInterpretation; long nrow; unsigned long row; char *buf; LPBITMAPINFOHEADER lpDIB; HDIB hDIB; char *lpBits; HGLOBAL hStrip; int i,l; int Align; tif = TIFFOpen(lpFileName, "r"); if (!tif) goto TiffOpenError; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample); TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip); TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip); TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation); LineSize = TIFFScanlineSize(tif); //Number of byte in ine line SamplePerPixel = (int) (LineSize/imageWidth); //Align = Number of byte to add at the end of each line of the DIB Align = 4 - (LineSize % 4); if (Align == 4) Align = 0; //Create a new DIB hDIB = CreateDIB((DWORD) imageWidth, (DWORD) imageLength, (WORD) (BitsPerSample*SamplePerPixel)); lpDIB = (LPBITMAPINFOHEADER) GlobalLock(hDIB); if (!lpDIB) goto OutOfDIBMemory; if (lpDIB) lpBits = FindDIBBits((LPSTR) lpDIB); //In the tiff file the lines are save from up to down //In a DIB the lines must be save from down to up if (lpBits) { lpBits = FindDIBBits((LPSTR) lpDIB); lpBits+=((imageWidth*SamplePerPixel)+Align)*(imageLength-1); //now lpBits pointe on the bottom line hStrip = GlobalAlloc(GHND,TIFFStripSize(tif)); buf = GlobalLock(hStrip); if (!buf) goto OutOfBufMemory; //PhotometricInterpretation = 2 image is RGB //PhotometricInterpretation = 3 image have a color palette if (PhotometricInterpretation == 3) { uint16* red; uint16* green; uint16* blue; int16 i; LPBITMAPINFO lpbmi; int Palette16Bits; TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); //Is the palette 16 or 8 bits ? if (checkcmap(1<<BitsPerSample, red, green, blue) == 16) Palette16Bits = TRUE; else Palette16Bits = FALSE; lpbmi = (LPBITMAPINFO)lpDIB; //load the palette in the DIB for (i = (1<<BitsPerSample)-1; i >= 0; i--) { if (Palette16Bits) { lpbmi->bmiColors[i].rgbRed =(BYTE) CVT(red[i]); lpbmi->bmiColors[i].rgbGreen = (BYTE) CVT(green[i]); lpbmi->bmiColors[i].rgbBlue = (BYTE) CVT(blue[i]); } else { lpbmi->bmiColors[i].rgbRed = (BYTE) red[i]; lpbmi->bmiColors[i].rgbGreen = (BYTE) green[i]; lpbmi->bmiColors[i].rgbBlue = (BYTE) blue[i]; } } } //read the tiff lines and save them in the DIB //with RGB mode, we have to change the order of the 3 samples RGB <=> BGR for (row = 0; row < imageLength; row += RowsPerStrip) { nrow = (row + RowsPerStrip > imageLength ? imageLength - row : RowsPerStrip); if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), buf, nrow*LineSize)==-1) { goto TiffReadError; } else { for (l = 0; l < nrow; l++) { if (SamplePerPixel == 3) for (i=0; i< (int) (imageWidth); i++) { lpBits[i*SamplePerPixel+0]=buf[l*LineSize+i*Sample PerPixel+2]; lpBits[i*SamplePerPixel+1]=buf[l*LineSize+i*Sample PerPixel+1]; lpBits[i*SamplePerPixel+2]=buf[l*LineSize+i*Sample PerPixel+0]; } else memcpy(lpBits, &buf[(int) (l*LineSize)], (int) imageWidth*SamplePerPixel); lpBits-=imageWidth*SamplePerPixel+Align; } } } GlobalUnlock(hStrip); GlobalFree(hStrip); GlobalUnlock(hDIB); TIFFClose(tif); }
boolean TIFFRasterImpl::gt(u_long w, u_long h) { u_short minsamplevalue; u_short maxsamplevalue; u_short planarconfig; RGBvalue* Map = nil; if (!TIFFGetField(tif_, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue)) { minsamplevalue = 0; } if (!TIFFGetField(tif_, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue)) { maxsamplevalue = (1<<bitspersample_)-1; } switch (photometric_) { case PHOTOMETRIC_RGB: if (minsamplevalue == 0 && maxsamplevalue == 255) { break; } /* fall thru... */ case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISWHITE: { register int x, range; range = maxsamplevalue - minsamplevalue; Map = new RGBvalue[range + 1]; if (Map == nil) { TIFFError( TIFFFileName(tif_), "No space for photometric conversion table" ); return false; } if (photometric_ == PHOTOMETRIC_MINISWHITE) { for (x = 0; x <= range; x++) { Map[x] = ((range - x) * 255) / range; } } else { for (x = 0; x <= range; x++) { Map[x] = (x * 255) / range; } } if (photometric_ != PHOTOMETRIC_RGB && bitspersample_ != 8) { /* * Use photometric mapping table to construct * unpacking tables for samples < 8 bits. */ if (!makebwmap(Map)) { return false; } delete Map; /* no longer need Map, free it */ Map = nil; } break; } case PHOTOMETRIC_PALETTE: if (!TIFFGetField( tif_, TIFFTAG_COLORMAP, &redcmap_, &greencmap_, &bluecmap_) ) { TIFFError(TIFFFileName(tif_), "Missing required \"Colormap\" tag"); return (false); } /* * Convert 16-bit colormap to 8-bit (unless it looks * like an old-style 8-bit colormap). */ if ( checkcmap( 1 << bitspersample_, redcmap_, greencmap_, bluecmap_ ) == 16 ) { int i; for (i = (1 << bitspersample_) - 1; i > 0; i--) { #define CVT(x) (((x) * 255) / ((1L<<16)-1)) redcmap_[i] = (u_short) CVT(redcmap_[i]); greencmap_[i] = (u_short) CVT(greencmap_[i]); bluecmap_[i] = (u_short) CVT(bluecmap_[i]); } } if (bitspersample_ <= 8) { /* * Use mapping table and colormap to construct * unpacking tables for samples < 8 bits. */ if (!makecmap(redcmap_, greencmap_, bluecmap_)) { return false; } } break; } TIFFGetField(tif_, TIFFTAG_PLANARCONFIG, &planarconfig); boolean e; if (planarconfig == PLANARCONFIG_SEPARATE && samplesperpixel_ > 1) { e = TIFFIsTiled(tif_) ? gtTileSeparate(Map, h, w) : gtStripSeparate(Map, h, w); } else { e = TIFFIsTiled(tif_) ? gtTileContig(Map, h, w) : gtStripContig(Map, h, w); } delete Map; return e; }
static void PS_Lvl2colorspace(FILE* fd, TIFF* tif) { uint16 *rmap, *gmap, *bmap; int i, num_colors; const char * colorspace_p; switch ( photometric ) { case PHOTOMETRIC_SEPARATED: colorspace_p = "CMYK"; break; case PHOTOMETRIC_RGB: colorspace_p = "RGB"; break; default: colorspace_p = "Gray"; } /* * Set up PostScript Level 2 colorspace according to * section 4.8 in the PostScript refenence manual. */ fputs("% PostScript Level 2 only.\n", fd); if (photometric != PHOTOMETRIC_PALETTE) { if (photometric == PHOTOMETRIC_YCBCR) { /* MORE CODE HERE */ } fprintf(fd, "/Device%s setcolorspace\n", colorspace_p ); return; } /* * Set up an indexed/palette colorspace */ num_colors = (1 << bitspersample); if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) { TIFFError(filename, "Palette image w/o \"Colormap\" tag"); return; } if (checkcmap(tif, num_colors, rmap, gmap, bmap) == 16) { /* * Convert colormap to 8-bits values. */ #define CVT(x) (((x) * 255) / ((1L<<16)-1)) for (i = 0; i < num_colors; i++) { rmap[i] = CVT(rmap[i]); gmap[i] = CVT(gmap[i]); bmap[i] = CVT(bmap[i]); } #undef CVT } fprintf(fd, "[ /Indexed /DeviceRGB %d", num_colors - 1); if (ascii85) { Ascii85Init(); fputs("\n<~", fd); ascii85breaklen -= 2; } else fputs(" <", fd); for (i = 0; i < num_colors; i++) { if (ascii85) { Ascii85Put(rmap[i], fd); Ascii85Put(gmap[i], fd); Ascii85Put(bmap[i], fd); } else { fputs((i % 8) ? " " : "\n ", fd); fprintf(fd, "%02x%02x%02x", rmap[i], gmap[i], bmap[i]); } } if (ascii85) Ascii85Flush(fd); else fputs(">\n", fd); fputs("] setcolorspace\n", fd); }
void PSDataPalette(FILE* fd, TIFF* tif, uint32 w, uint32 h) { uint16 *rmap, *gmap, *bmap; uint32 row; int breaklen = MAXLINE, cc, nc; unsigned char *tf_buf; unsigned char *cp, c; (void) w; if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) { TIFFError(filename, "Palette image w/o \"Colormap\" tag"); return; } switch (bitspersample) { case 8: case 4: case 2: case 1: break; default: TIFFError(filename, "Depth %d not supported", bitspersample); return; } nc = 3 * (8 / bitspersample); tf_buf = (unsigned char *) _TIFFmalloc(tf_bytesperrow); if (tf_buf == NULL) { TIFFError(filename, "No space for scanline buffer"); return; } if (checkcmap(tif, 1<<bitspersample, rmap, gmap, bmap) == 16) { int i; #define CVT(x) (((x) * 255) / ((1U<<16)-1)) for (i = (1<<bitspersample)-1; i >= 0; i--) { rmap[i] = CVT(rmap[i]); gmap[i] = CVT(gmap[i]); bmap[i] = CVT(bmap[i]); } #undef CVT } for (row = 0; row < h; row++) { if (TIFFReadScanline(tif, tf_buf, row, 0) < 0) break; for (cp = tf_buf, cc = 0; cc < tf_bytesperrow; cc++) { DOBREAK(breaklen, nc, fd); switch (bitspersample) { case 8: c = *cp++; PUTRGBHEX(c, fd); break; case 4: c = *cp++; PUTRGBHEX(c&0xf, fd); c >>= 4; PUTRGBHEX(c, fd); break; case 2: c = *cp++; PUTRGBHEX(c&0x3, fd); c >>= 2; PUTRGBHEX(c&0x3, fd); c >>= 2; PUTRGBHEX(c&0x3, fd); c >>= 2; PUTRGBHEX(c, fd); break; case 1: c = *cp++; PUTRGBHEX(c&0x1, fd); c >>= 1; PUTRGBHEX(c&0x1, fd); c >>= 1; PUTRGBHEX(c&0x1, fd); c >>= 1; PUTRGBHEX(c&0x1, fd); c >>= 1; PUTRGBHEX(c&0x1, fd); c >>= 1; PUTRGBHEX(c&0x1, fd); c >>= 1; PUTRGBHEX(c&0x1, fd); c >>= 1; PUTRGBHEX(c, fd); break; } } } _TIFFfree((char *) tf_buf); }