/* This file is part of icoformat, a Windows Icon (ICO) File Format plugin for Adobe Photoshop Copyright (C) 2002-2010 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 "icoformat.h" #include "ico_io.h" static unsigned char *est_indata; static int est_inrb; OSErr estimate_start(FormatRecordPtr pb, intptr_t *data) { est_indata = NULL; switch(pb->imageMode){ case plugInModeBitmap: G(ncols) = 2; G(nbits) = 1; G(black) = 1; break; case plugInModeGrayScale: case plugInModeIndexedColor: // for palette images, we must examine the image data to count colours // set things up to get image data (in Continue callback) est_inrb = pb->imageSize.h; if( (est_indata = (unsigned char*)malloc(est_inrb*pb->imageSize.v)) ){ SETRECT(pb->theRect, 0, 0, pb->imageSize.h, pb->imageSize.v); pb->loPlane = pb->hiPlane = 0; // first plane only pb->colBytes = 1; pb->rowBytes = est_inrb; pb->planeBytes = 1; pb->data = est_indata; // ncols and nbits will be computed in Continue and Finish phases respectively return noErr; } return memFullErr; case plugInModeRGBColor: G(ncols) = 0; G(nbits) = LAYERTRANS || pb->planes > 4 ? 32 : 24; } estimate_finish(pb, data); // don't need image data pb->data = NULL; SETRECT(pb->theRect, 0, 0, 0, 0); return noErr; } OSErr estimate_continue(FormatRecordPtr pb, intptr_t *data) { int i, j; unsigned char *inrow, *in, hist[0x100]; char s[0x100]; // for each colour index, set a flag if it's used memset(hist, 0, 0x100); for(j = pb->imageSize.v, inrow = est_indata; j--; inrow += est_inrb) for(i = pb->imageSize.h, in = inrow; i--;) hist[*in++] = 1; if(pb->transparentIndex < 256) hist[pb->transparentIndex] = 0; // always ignore transparent value G(black) = -1; // count how many flags are set (add them up) for(i = j = 0; i < 0x100; ++i){ if(G(black) == -1 && !pb->redLUT[i] && !pb->greenLUT[i] && !pb->blueLUT[i]){ G(black) = i; ++hist[i]; /* ensure black gets retained */ //sprintf(s,"found black at index %d", i);dbg(s); } if(hist[i]){ G(oldindex)[j] = i; // maps from 'new' image values to old G(newindex)[i] = j; // and vice versa //sprintf(s,"mapping index %d to %d", i, j);dbg(s); ++j; }else G(newindex)[i] = UNUSED_INDEX; // flag unused indices } /* if black isn't in the palette & the palette isn't full, add it */ if(G(black) == -1){ if(j < 256) G(black) = j++; }else G(black) = G(newindex)[G(black)]; // find its remapped index G(ncols) = j; // tell Photoshop we're finished with image data pb->data = NULL; SETRECT(pb->theRect, 0, 0, 0, 0); return noErr; } OSErr estimate_finish(FormatRecordPtr pb, intptr_t *data) { if(G(ncols)){ if(G(ncols) > 16) G(nbits) = 8; else if(G(ncols) > 2) G(nbits) = 4; else G(nbits) = 1; G(ctabsize) = 1 << G(nbits); // full size colour table for this bit depth }else G(ctabsize) = 0; // 24 bits/pixel, no colour table // tell Photoshop how large we expect the file will be (we know this exactly) pb->minDataBytes = pb->maxDataBytes = SIZEOF_ICONDIR + SIZEOF_ICONDIRENTRY + iconbytes(pb, data); pb->minRsrcBytes = pb->maxRsrcBytes = 0; if(est_indata) free(est_indata); return noErr; }