1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * The Contents of this file are made available subject to 6*cdf0e10cSrcweir * the terms of GNU General Public License Version 2. 7*cdf0e10cSrcweir * 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * GNU General Public License, version 2 10*cdf0e10cSrcweir * ============================================= 11*cdf0e10cSrcweir * Copyright 2005 by Sun Microsystems, Inc. 12*cdf0e10cSrcweir * 901 San Antonio Road, Palo Alto, CA 94303, USA 13*cdf0e10cSrcweir * 14*cdf0e10cSrcweir * This program is free software; you can redistribute it and/or 15*cdf0e10cSrcweir * modify it under the terms of the GNU General Public License as 16*cdf0e10cSrcweir * published by the Free Software Foundation; either version 2 of 17*cdf0e10cSrcweir * the License, or (at your option) any later version. 18*cdf0e10cSrcweir * 19*cdf0e10cSrcweir * This program is distributed in the hope that it will be useful, 20*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 21*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22*cdf0e10cSrcweir * GNU General Public License for more details. 23*cdf0e10cSrcweir * 24*cdf0e10cSrcweir * You should have received a copy of the GNU General Public 25*cdf0e10cSrcweir * License along with this program; if not, write to the Free 26*cdf0e10cSrcweir * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 27*cdf0e10cSrcweir * Boston, MA 02110-1301, USA. 28*cdf0e10cSrcweir * 29*cdf0e10cSrcweir ************************************************************************/ 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include "pnghelper.hxx" 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #ifdef SYSTEM_ZLIB 34*cdf0e10cSrcweir #include "zlib.h" 35*cdf0e10cSrcweir #else 36*cdf0e10cSrcweir #define ZLIB_INTERNAL 1 37*cdf0e10cSrcweir #include <zlib/zlib.h> 38*cdf0e10cSrcweir #endif 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir using namespace pdfi; 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir // checksum helpers, courtesy of libpng.org 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir /* Table of CRCs of all 8-bit messages. */ 45*cdf0e10cSrcweir sal_uInt32 PngHelper::crc_table[256]; 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir /* Flag: has the table been computed? Initially false. */ 48*cdf0e10cSrcweir bool PngHelper::bCRCTableInit = true; 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir /* Make the table for a fast CRC. */ 51*cdf0e10cSrcweir void PngHelper::initCRCTable() 52*cdf0e10cSrcweir { 53*cdf0e10cSrcweir for (sal_uInt32 n = 0; n < 256; n++) 54*cdf0e10cSrcweir { 55*cdf0e10cSrcweir sal_uInt32 c = n; 56*cdf0e10cSrcweir for (int k = 0; k < 8; k++) 57*cdf0e10cSrcweir { 58*cdf0e10cSrcweir if (c & 1) 59*cdf0e10cSrcweir c = 0xedb88320L ^ (c >> 1); 60*cdf0e10cSrcweir else 61*cdf0e10cSrcweir c = c >> 1; 62*cdf0e10cSrcweir } 63*cdf0e10cSrcweir crc_table[n] = c; 64*cdf0e10cSrcweir } 65*cdf0e10cSrcweir bCRCTableInit = false; 66*cdf0e10cSrcweir } 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir /* Update a running CRC with the bytes buf[0..len-1]--the CRC 69*cdf0e10cSrcweir should be initialized to all 1's, and the transmitted value 70*cdf0e10cSrcweir is the 1's complement of the final running CRC (see the 71*cdf0e10cSrcweir crc() routine below)). */ 72*cdf0e10cSrcweir 73*cdf0e10cSrcweir void PngHelper::updateCRC( sal_uInt32& io_rCRC, const sal_uInt8* i_pBuf, size_t i_nLen ) 74*cdf0e10cSrcweir { 75*cdf0e10cSrcweir if( bCRCTableInit ) 76*cdf0e10cSrcweir initCRCTable(); 77*cdf0e10cSrcweir 78*cdf0e10cSrcweir sal_uInt32 nCRC = io_rCRC; 79*cdf0e10cSrcweir for( size_t n = 0; n < i_nLen; n++ ) 80*cdf0e10cSrcweir nCRC = crc_table[(nCRC ^ i_pBuf[n]) & 0xff] ^ (nCRC >> 8); 81*cdf0e10cSrcweir io_rCRC = nCRC; 82*cdf0e10cSrcweir } 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir sal_uInt32 PngHelper::getCRC( const sal_uInt8* i_pBuf, size_t i_nLen ) 85*cdf0e10cSrcweir { 86*cdf0e10cSrcweir sal_uInt32 nCRC = 0xffffffff; 87*cdf0e10cSrcweir updateCRC( nCRC, i_pBuf, i_nLen ); 88*cdf0e10cSrcweir return nCRC ^ 0xffffffff; 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir sal_uInt32 PngHelper::deflateBuffer( const Output_t* i_pBuf, size_t i_nLen, OutputBuffer& o_rOut ) 92*cdf0e10cSrcweir { 93*cdf0e10cSrcweir size_t nOrigSize = o_rOut.size(); 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir // prepare z stream 96*cdf0e10cSrcweir z_stream aStream; 97*cdf0e10cSrcweir aStream.zalloc = Z_NULL; 98*cdf0e10cSrcweir aStream.zfree = Z_NULL; 99*cdf0e10cSrcweir aStream.opaque = Z_NULL; 100*cdf0e10cSrcweir deflateInit( &aStream, Z_BEST_COMPRESSION ); 101*cdf0e10cSrcweir aStream.avail_in = uInt(i_nLen); 102*cdf0e10cSrcweir aStream.next_in = (Bytef*)i_pBuf; 103*cdf0e10cSrcweir 104*cdf0e10cSrcweir sal_uInt8 aOutBuf[ 32768 ]; 105*cdf0e10cSrcweir do 106*cdf0e10cSrcweir { 107*cdf0e10cSrcweir aStream.avail_out = sizeof( aOutBuf ); 108*cdf0e10cSrcweir aStream.next_out = aOutBuf; 109*cdf0e10cSrcweir 110*cdf0e10cSrcweir if( deflate( &aStream, Z_FINISH ) == Z_STREAM_ERROR ) 111*cdf0e10cSrcweir { 112*cdf0e10cSrcweir deflateEnd( &aStream ); 113*cdf0e10cSrcweir // scrao the data of this broken stream 114*cdf0e10cSrcweir o_rOut.resize( nOrigSize ); 115*cdf0e10cSrcweir return 0; 116*cdf0e10cSrcweir } 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir // append compressed bytes 119*cdf0e10cSrcweir sal_uInt32 nCompressedBytes = sizeof( aOutBuf ) - aStream.avail_out; 120*cdf0e10cSrcweir if( nCompressedBytes ) 121*cdf0e10cSrcweir o_rOut.insert( o_rOut.end(), aOutBuf, aOutBuf+nCompressedBytes ); 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir } while( aStream.avail_out == 0 ); 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir // cleanup 126*cdf0e10cSrcweir deflateEnd( &aStream ); 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir return sal_uInt32( o_rOut.size() - nOrigSize ); 129*cdf0e10cSrcweir } 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir void PngHelper::appendFileHeader( OutputBuffer& o_rOutputBuf ) 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir static const Output_t aHeader[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir o_rOutputBuf.insert( o_rOutputBuf.end(), aHeader, aHeader + sizeof(aHeader)/sizeof(aHeader[0]) ); 136*cdf0e10cSrcweir } 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir size_t PngHelper::startChunk( const char* pChunkName, OutputBuffer& o_rOutputBuf ) 139*cdf0e10cSrcweir { 140*cdf0e10cSrcweir size_t nIndex = sal_uInt32( o_rOutputBuf.size() ); 141*cdf0e10cSrcweir o_rOutputBuf.insert( o_rOutputBuf.end(), 4, (Output_t)0 ); 142*cdf0e10cSrcweir o_rOutputBuf.push_back( pChunkName[0] ); 143*cdf0e10cSrcweir o_rOutputBuf.push_back( pChunkName[1] ); 144*cdf0e10cSrcweir o_rOutputBuf.push_back( pChunkName[2] ); 145*cdf0e10cSrcweir o_rOutputBuf.push_back( pChunkName[3] ); 146*cdf0e10cSrcweir return nIndex; 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir 149*cdf0e10cSrcweir void PngHelper::set( sal_uInt32 i_nValue, OutputBuffer& o_rOutputBuf, size_t i_nIndex ) 150*cdf0e10cSrcweir { 151*cdf0e10cSrcweir o_rOutputBuf[ i_nIndex ] = (i_nValue & 0xff000000) >> 24; 152*cdf0e10cSrcweir o_rOutputBuf[ i_nIndex+1 ] = (i_nValue & 0x00ff0000) >> 16; 153*cdf0e10cSrcweir o_rOutputBuf[ i_nIndex+2 ] = (i_nValue & 0x0000ff00) >> 8; 154*cdf0e10cSrcweir o_rOutputBuf[ i_nIndex+3 ] = (i_nValue & 0x000000ff); 155*cdf0e10cSrcweir } 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir void PngHelper::endChunk( size_t nStart, OutputBuffer& o_rOutputBuf ) 158*cdf0e10cSrcweir { 159*cdf0e10cSrcweir if( nStart+8 > o_rOutputBuf.size() ) 160*cdf0e10cSrcweir return; // something broken is going on 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir // update chunk length 163*cdf0e10cSrcweir size_t nLen = o_rOutputBuf.size() - nStart; 164*cdf0e10cSrcweir sal_uInt32 nDataLen = sal_uInt32(nLen)-8; 165*cdf0e10cSrcweir set( nDataLen, o_rOutputBuf, nStart ); 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir // append chunk crc 168*cdf0e10cSrcweir sal_uInt32 nChunkCRC = getCRC( (sal_uInt8*)&o_rOutputBuf[nStart+4], nLen-4 ); 169*cdf0e10cSrcweir append( nChunkCRC, o_rOutputBuf ); 170*cdf0e10cSrcweir } 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir void PngHelper::appendIHDR( OutputBuffer& o_rOutputBuf, int width, int height, int depth, int colortype ) 173*cdf0e10cSrcweir { 174*cdf0e10cSrcweir size_t nStart = startChunk( "IHDR", o_rOutputBuf ); 175*cdf0e10cSrcweir append( width, o_rOutputBuf ); 176*cdf0e10cSrcweir append( height, o_rOutputBuf ); 177*cdf0e10cSrcweir o_rOutputBuf.push_back( Output_t(depth) ); 178*cdf0e10cSrcweir o_rOutputBuf.push_back( Output_t(colortype) ); 179*cdf0e10cSrcweir o_rOutputBuf.push_back( 0 ); // compression method deflate 180*cdf0e10cSrcweir o_rOutputBuf.push_back( 0 ); // filtering method 0 (default) 181*cdf0e10cSrcweir o_rOutputBuf.push_back( 0 ); // no interlacing 182*cdf0e10cSrcweir endChunk( nStart, o_rOutputBuf ); 183*cdf0e10cSrcweir } 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir void PngHelper::appendIEND( OutputBuffer& o_rOutputBuf ) 186*cdf0e10cSrcweir { 187*cdf0e10cSrcweir size_t nStart = startChunk( "IEND", o_rOutputBuf ); 188*cdf0e10cSrcweir endChunk( nStart, o_rOutputBuf ); 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir void PngHelper::createPng( OutputBuffer& o_rOutputBuf, 192*cdf0e10cSrcweir Stream* str, 193*cdf0e10cSrcweir int width, 194*cdf0e10cSrcweir int height, 195*cdf0e10cSrcweir GfxRGB& zeroColor, 196*cdf0e10cSrcweir GfxRGB& oneColor, 197*cdf0e10cSrcweir bool bIsMask 198*cdf0e10cSrcweir ) 199*cdf0e10cSrcweir { 200*cdf0e10cSrcweir appendFileHeader( o_rOutputBuf ); 201*cdf0e10cSrcweir appendIHDR( o_rOutputBuf, width, height, 1, 3 ); 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir // write palette 204*cdf0e10cSrcweir size_t nIdx = startChunk( "PLTE", o_rOutputBuf ); 205*cdf0e10cSrcweir // write colors 0 and 1 206*cdf0e10cSrcweir o_rOutputBuf.push_back(colToByte(zeroColor.r)); 207*cdf0e10cSrcweir o_rOutputBuf.push_back(colToByte(zeroColor.g)); 208*cdf0e10cSrcweir o_rOutputBuf.push_back(colToByte(zeroColor.b)); 209*cdf0e10cSrcweir o_rOutputBuf.push_back(colToByte(oneColor.r)); 210*cdf0e10cSrcweir o_rOutputBuf.push_back(colToByte(oneColor.g)); 211*cdf0e10cSrcweir o_rOutputBuf.push_back(colToByte(oneColor.b)); 212*cdf0e10cSrcweir // end PLTE chunk 213*cdf0e10cSrcweir endChunk( nIdx, o_rOutputBuf ); 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir if( bIsMask ) 216*cdf0e10cSrcweir { 217*cdf0e10cSrcweir // write tRNS chunk 218*cdf0e10cSrcweir nIdx = startChunk( "tRNS", o_rOutputBuf ); 219*cdf0e10cSrcweir o_rOutputBuf.push_back( 0xff ); 220*cdf0e10cSrcweir o_rOutputBuf.push_back( 0 ); 221*cdf0e10cSrcweir // end tRNS chunk 222*cdf0e10cSrcweir endChunk( nIdx, o_rOutputBuf ); 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir // create scan line data buffer 226*cdf0e10cSrcweir OutputBuffer aScanlines; 227*cdf0e10cSrcweir int nLineSize = (width + 7)/8; 228*cdf0e10cSrcweir aScanlines.reserve( nLineSize * height + height ); 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir str->reset(); 231*cdf0e10cSrcweir for( int y = 0; y < height; y++ ) 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir // determine filter type (none) for this scanline 234*cdf0e10cSrcweir aScanlines.push_back( 0 ); 235*cdf0e10cSrcweir for( int x = 0; x < nLineSize; x++ ) 236*cdf0e10cSrcweir aScanlines.push_back( str->getChar() ); 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir // begin IDAT chunk for scanline data 240*cdf0e10cSrcweir nIdx = startChunk( "IDAT", o_rOutputBuf ); 241*cdf0e10cSrcweir // compress scanlines 242*cdf0e10cSrcweir deflateBuffer( &aScanlines[0], aScanlines.size(), o_rOutputBuf ); 243*cdf0e10cSrcweir // end IDAT chunk 244*cdf0e10cSrcweir endChunk( nIdx, o_rOutputBuf ); 245*cdf0e10cSrcweir 246*cdf0e10cSrcweir // output IEND 247*cdf0e10cSrcweir appendIEND( o_rOutputBuf ); 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir void PngHelper::createPng( OutputBuffer& o_rOutputBuf, 251*cdf0e10cSrcweir Stream* str, 252*cdf0e10cSrcweir int width, int height, GfxImageColorMap* colorMap, 253*cdf0e10cSrcweir Stream* maskStr, 254*cdf0e10cSrcweir int maskWidth, int maskHeight, GfxImageColorMap* maskColorMap ) 255*cdf0e10cSrcweir { 256*cdf0e10cSrcweir appendFileHeader( o_rOutputBuf ); 257*cdf0e10cSrcweir appendIHDR( o_rOutputBuf, width, height, 8, 6 ); // RGBA image 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir // initialize stream 260*cdf0e10cSrcweir Guchar *p, *pm; 261*cdf0e10cSrcweir GfxRGB rgb; 262*cdf0e10cSrcweir GfxGray alpha; 263*cdf0e10cSrcweir ImageStream* imgStr = 264*cdf0e10cSrcweir new ImageStream(str, 265*cdf0e10cSrcweir width, 266*cdf0e10cSrcweir colorMap->getNumPixelComps(), 267*cdf0e10cSrcweir colorMap->getBits()); 268*cdf0e10cSrcweir imgStr->reset(); 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir // create scan line data buffer 271*cdf0e10cSrcweir OutputBuffer aScanlines; 272*cdf0e10cSrcweir aScanlines.reserve( width*height*4 + height ); 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir for( int y=0; y<height; ++y) 275*cdf0e10cSrcweir { 276*cdf0e10cSrcweir aScanlines.push_back( 0 ); 277*cdf0e10cSrcweir p = imgStr->getLine(); 278*cdf0e10cSrcweir for( int x=0; x<width; ++x) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir colorMap->getRGB(p, &rgb); 281*cdf0e10cSrcweir aScanlines.push_back(colToByte(rgb.r)); 282*cdf0e10cSrcweir aScanlines.push_back(colToByte(rgb.g)); 283*cdf0e10cSrcweir aScanlines.push_back(colToByte(rgb.b)); 284*cdf0e10cSrcweir aScanlines.push_back( 0xff ); 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir p +=colorMap->getNumPixelComps(); 287*cdf0e10cSrcweir } 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir 291*cdf0e10cSrcweir // now fill in the mask data 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir // CAUTION: originally this was done in one single loop 294*cdf0e10cSrcweir // it caused merry chaos; the reason is that maskStr and str are 295*cdf0e10cSrcweir // not independent streams, it happens that reading one advances 296*cdf0e10cSrcweir // the other, too. Hence the two passes are imperative ! 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir // initialize mask stream 299*cdf0e10cSrcweir ImageStream* imgStrMask = 300*cdf0e10cSrcweir new ImageStream(maskStr, 301*cdf0e10cSrcweir maskWidth, 302*cdf0e10cSrcweir maskColorMap->getNumPixelComps(), 303*cdf0e10cSrcweir maskColorMap->getBits()); 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir imgStrMask->reset(); 306*cdf0e10cSrcweir for( int y = 0; y < maskHeight; ++y ) 307*cdf0e10cSrcweir { 308*cdf0e10cSrcweir pm = imgStrMask->getLine(); 309*cdf0e10cSrcweir for( int x = 0; x < maskWidth; ++x ) 310*cdf0e10cSrcweir { 311*cdf0e10cSrcweir maskColorMap->getGray(pm,&alpha); 312*cdf0e10cSrcweir pm += maskColorMap->getNumPixelComps(); 313*cdf0e10cSrcweir int nIndex = (y*height/maskHeight) * (width*4+1) + // mapped line 314*cdf0e10cSrcweir (x*width/maskWidth)*4 + 1 + 3 // mapped column 315*cdf0e10cSrcweir ; 316*cdf0e10cSrcweir aScanlines[ nIndex ] = colToByte(alpha); 317*cdf0e10cSrcweir } 318*cdf0e10cSrcweir } 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir delete imgStr; 321*cdf0e10cSrcweir delete imgStrMask; 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir // begind IDAT chunk for scanline data 324*cdf0e10cSrcweir size_t nIdx = startChunk( "IDAT", o_rOutputBuf ); 325*cdf0e10cSrcweir // compress scanlines 326*cdf0e10cSrcweir deflateBuffer( &aScanlines[0], aScanlines.size(), o_rOutputBuf ); 327*cdf0e10cSrcweir // end IDAT chunk 328*cdf0e10cSrcweir endChunk( nIdx, o_rOutputBuf ); 329*cdf0e10cSrcweir // output IEND 330*cdf0e10cSrcweir appendIEND( o_rOutputBuf ); 331*cdf0e10cSrcweir } 332*cdf0e10cSrcweir 333*cdf0e10cSrcweir // one bit mask; 0 bits opaque 334*cdf0e10cSrcweir void PngHelper::createPng( OutputBuffer& o_rOutputBuf, 335*cdf0e10cSrcweir Stream* str, 336*cdf0e10cSrcweir int width, int height, GfxImageColorMap* colorMap, 337*cdf0e10cSrcweir Stream* maskStr, 338*cdf0e10cSrcweir int maskWidth, int maskHeight, 339*cdf0e10cSrcweir bool maskInvert 340*cdf0e10cSrcweir ) 341*cdf0e10cSrcweir { 342*cdf0e10cSrcweir appendFileHeader( o_rOutputBuf ); 343*cdf0e10cSrcweir appendIHDR( o_rOutputBuf, width, height, 8, 6 ); // RGBA image 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir // initialize stream 346*cdf0e10cSrcweir Guchar *p; 347*cdf0e10cSrcweir GfxRGB rgb; 348*cdf0e10cSrcweir ImageStream* imgStr = 349*cdf0e10cSrcweir new ImageStream(str, 350*cdf0e10cSrcweir width, 351*cdf0e10cSrcweir colorMap->getNumPixelComps(), 352*cdf0e10cSrcweir colorMap->getBits()); 353*cdf0e10cSrcweir imgStr->reset(); 354*cdf0e10cSrcweir 355*cdf0e10cSrcweir // create scan line data buffer 356*cdf0e10cSrcweir OutputBuffer aScanlines; 357*cdf0e10cSrcweir aScanlines.reserve( width*height*4 + height ); 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir for( int y=0; y<height; ++y) 360*cdf0e10cSrcweir { 361*cdf0e10cSrcweir aScanlines.push_back( 0 ); 362*cdf0e10cSrcweir p = imgStr->getLine(); 363*cdf0e10cSrcweir for( int x=0; x<width; ++x) 364*cdf0e10cSrcweir { 365*cdf0e10cSrcweir colorMap->getRGB(p, &rgb); 366*cdf0e10cSrcweir aScanlines.push_back(colToByte(rgb.r)); 367*cdf0e10cSrcweir aScanlines.push_back(colToByte(rgb.g)); 368*cdf0e10cSrcweir aScanlines.push_back(colToByte(rgb.b)); 369*cdf0e10cSrcweir aScanlines.push_back( 0xff ); 370*cdf0e10cSrcweir 371*cdf0e10cSrcweir p +=colorMap->getNumPixelComps(); 372*cdf0e10cSrcweir } 373*cdf0e10cSrcweir } 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir // now fill in the mask data 377*cdf0e10cSrcweir 378*cdf0e10cSrcweir // CAUTION: originally this was done in one single loop 379*cdf0e10cSrcweir // it caused merry chaos; the reason is that maskStr and str are 380*cdf0e10cSrcweir // not independent streams, it happens that reading one advances 381*cdf0e10cSrcweir // the other, too. Hence the two passes are imperative ! 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir // initialize mask stream 384*cdf0e10cSrcweir ImageStream* imgStrMask = 385*cdf0e10cSrcweir new ImageStream(maskStr, maskWidth, 1, 1); 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir imgStrMask->reset(); 388*cdf0e10cSrcweir for( int y = 0; y < maskHeight; ++y ) 389*cdf0e10cSrcweir { 390*cdf0e10cSrcweir for( int x = 0; x < maskWidth; ++x ) 391*cdf0e10cSrcweir { 392*cdf0e10cSrcweir Guchar aPixel = 0; 393*cdf0e10cSrcweir imgStrMask->getPixel( &aPixel ); 394*cdf0e10cSrcweir int nIndex = (y*height/maskHeight) * (width*4+1) + // mapped line 395*cdf0e10cSrcweir (x*width/maskWidth)*4 + 1 + 3 // mapped column 396*cdf0e10cSrcweir ; 397*cdf0e10cSrcweir if( maskInvert ) 398*cdf0e10cSrcweir aScanlines[ nIndex ] = aPixel ? 0xff : 0x00; 399*cdf0e10cSrcweir else 400*cdf0e10cSrcweir aScanlines[ nIndex ] = aPixel ? 0x00 : 0xff; 401*cdf0e10cSrcweir } 402*cdf0e10cSrcweir } 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir delete imgStr; 405*cdf0e10cSrcweir delete imgStrMask; 406*cdf0e10cSrcweir 407*cdf0e10cSrcweir // begind IDAT chunk for scanline data 408*cdf0e10cSrcweir size_t nIdx = startChunk( "IDAT", o_rOutputBuf ); 409*cdf0e10cSrcweir // compress scanlines 410*cdf0e10cSrcweir deflateBuffer( &aScanlines[0], aScanlines.size(), o_rOutputBuf ); 411*cdf0e10cSrcweir // end IDAT chunk 412*cdf0e10cSrcweir endChunk( nIdx, o_rOutputBuf ); 413*cdf0e10cSrcweir // output IEND 414*cdf0e10cSrcweir appendIEND( o_rOutputBuf ); 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir 417