/* This file is part of TIFFlib Format, a File Format plugin for Adobe Photoshop Copyright (C) 2005-7 Toby Thain, toby@telegraphics.com.au This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "tifflibplugin.h" #include "version.h" extern unsigned char *indata; extern TIFF *tif; unsigned rb, rowsperstrip; tstrip_t strip; OSErr write_start(FormatRecordPtr pb, long *data){ OSErr e = noErr; unsigned i, n, pmetric = -1, imageplanes = pb->planes, comp; uint16 *p; struct revertinfo rev; // compression type should have been set by options dialog comp = getrevertinfo(pb,&rev) ? rev.comptype : COMPRESSION_NONE; // get ready for writing, and tell libtiff everything we know about the image if( (tif = TIFFFdOpen(pb->dataFork,"","w")) && TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, pb->imageSize.h) && TIFFSetField(tif, TIFFTAG_IMAGELENGTH, pb->imageSize.v) && TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, pb->planes) && TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, pb->depth) && TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) && TIFFSetField(tif, TIFFTAG_COMPRESSION, comp) && (comp != COMPRESSION_ADOBE_DEFLATE || TIFFSetField(tif, TIFFTAG_ZIPQUALITY, 9)) // pseudo-tag && TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH) && TIFFSetField(tif, TIFFTAG_XRESOLUTION, pb->imageHRes/65536.) && TIFFSetField(tif, TIFFTAG_YRESOLUTION, pb->imageVRes/65536.) && TIFFSetField(tif, TIFFTAG_SOFTWARE, "TIFFlib Plugin " VERSION_STR " http://www.telegraphics.com.au/sw/ " TIFFLIB_VERSION_STR) ) { // decide the mode-dependent fields, such as photometric interpretation switch(pb->imageMode){ case plugInModeBitmap: pmetric = PHOTOMETRIC_MINISWHITE; break; case plugInModeGrayScale: case plugInModeGray16: imageplanes = 1; case plugInModeMultichannel: case plugInModeDeepMultichannel: pmetric = PHOTOMETRIC_MINISBLACK; break; case plugInModeIndexedColor: imageplanes = 1; pmetric = PHOTOMETRIC_PALETTE; n = 1 << pb->depth; if( (p = malloc(3*n*sizeof(uint16))) ){ for(i = n; i--;){ p[i] = 0x101*pb->redLUT[i]; p[i+n] = 0x101*pb->greenLUT[i]; p[i+2*n] = 0x101*pb->blueLUT[i]; } if(!TIFFSetField(tif, TIFFTAG_COLORMAP, p, p+n, p+2*n)) e = ioErr; free(p); }else e = memFullErr; break; case plugInModeRGBColor: case plugInModeRGB48: imageplanes = 3; pmetric = PHOTOMETRIC_RGB; break; case plugInModeCMYKColor: case plugInModeCMYK64: imageplanes = 4; pmetric = PHOTOMETRIC_SEPARATED; if(!TIFFSetField(tif, TIFFTAG_INKSET, INKSET_CMYK)) e = ioErr; break; //case plugInModeLabColor: //case plugInModeLab48: default: e = formatBadParameters; } // specify that any non-image channels are "unassociated alpha" if(!e && pb->planes > imageplanes){ n = pb->planes - imageplanes; if( (p = malloc(n*sizeof(uint16))) ){ for(i = n; i--;) p[i] = EXTRASAMPLE_UNASSALPHA; if(!TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, n, p)) e = ioErr; free(p); }else e = memFullErr; } // get ready to request image data in strips; allocate buffer for it rb = TIFFScanlineSize(tif); // ((long)pb->imageSize.h*pb->planes*pb->depth+7)/8; rowsperstrip = TIFFDefaultStripSize(tif, 0); if( !e && TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, pmetric) && TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip) && (indata = malloc(TIFFStripSize(tif)+4)) ) { pb->rowBytes = rb; // request interleaved data: pb->colBytes = pb->planes << (pb->depth==16); pb->planeBytes = pb->depth==16 ? 2 : 1; /* FIXME: "Because of the implementation of the plane map, Format and Import modules should never try to work with more than 16 planes at a time. The results would be unpredictable." */ pb->loPlane = 0; pb->hiPlane = pb->planes-1; pb->data = indata; SETRECT(pb->theRect,0,0,pb->imageSize.h,rowsperstrip); strip = 0; }else e = memFullErr; } if(tif && e) TIFFClose(tif); return e; } OSErr write_continue(FormatRecordPtr pb){ long i, n = TIFFVStripSize(tif, pb->theRect.bottom - pb->theRect.top); unsigned short *p; // fix range of 16-bit data from Photoshop, from 0..0x8000 -> 0..0xffff if(pb->depth == 16) for(i = n/2, p = (unsigned short*)indata; i--; ++p) *p = fix16(*p); // CMYK data needs to be inverted; TIFF expects 255 -> 100% coverage if(pb->imageMode == plugInModeCMYKColor || pb->imageMode == plugInModeCMYK64) invertbuf(indata, n); if(TIFFWriteEncodedStrip(tif, strip++, indata, n) == -1) return ioErr; // request next strip pb->theRect.top = pb->theRect.bottom; if(pb->theRect.top < pb->imageSize.v){ pb->theRect.bottom = pb->theRect.top + rowsperstrip; if(pb->theRect.bottom > pb->imageSize.v) pb->theRect.bottom = pb->imageSize.v; }else{ pb->data = NULL; SETRECT(pb->theRect, 0,0,0,0); } return noErr; } OSErr write_finish(FormatRecordPtr pb){ free(indata); TIFFClose(tif); return noErr; }