Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <cassert>
23 :
24 : #include <vcl/salbtype.hxx>
25 : #include <vcl/dibtools.hxx>
26 : #include <tools/zcodec.hxx>
27 : #include <tools/stream.hxx>
28 : #include <tools/fract.hxx>
29 : #include <vcl/bitmapex.hxx>
30 : #include <vcl/bmpacc.hxx>
31 : #include <vcl/outdev.hxx>
32 : #include <boost/scoped_array.hpp>
33 :
34 : // - Defines -
35 :
36 : #define DIBCOREHEADERSIZE ( 12UL )
37 : #define DIBINFOHEADERSIZE ( sizeof(DIBInfoHeader) )
38 : #define DIBV5HEADERSIZE ( sizeof(DIBV5Header) )
39 :
40 : // - DIBInfoHeader and DIBV5Header
41 :
42 : typedef sal_Int32 FXPT2DOT30;
43 :
44 : struct CIEXYZ
45 : {
46 : FXPT2DOT30 aXyzX;
47 : FXPT2DOT30 aXyzY;
48 : FXPT2DOT30 aXyzZ;
49 :
50 9858 : CIEXYZ()
51 : : aXyzX(0L),
52 : aXyzY(0L),
53 9858 : aXyzZ(0L)
54 9858 : {}
55 :
56 9858 : ~CIEXYZ()
57 9858 : {}
58 : };
59 :
60 : struct CIEXYZTriple
61 : {
62 : CIEXYZ aXyzRed;
63 : CIEXYZ aXyzGreen;
64 : CIEXYZ aXyzBlue;
65 :
66 3286 : CIEXYZTriple()
67 : : aXyzRed(),
68 : aXyzGreen(),
69 3286 : aXyzBlue()
70 3286 : {}
71 :
72 3286 : ~CIEXYZTriple()
73 3286 : {}
74 : };
75 :
76 : struct DIBInfoHeader
77 : {
78 : sal_uInt32 nSize;
79 : sal_Int32 nWidth;
80 : sal_Int32 nHeight;
81 : sal_uInt16 nPlanes;
82 : sal_uInt16 nBitCount;
83 : sal_uInt32 nCompression;
84 : sal_uInt32 nSizeImage;
85 : sal_Int32 nXPelsPerMeter;
86 : sal_Int32 nYPelsPerMeter;
87 : sal_uInt32 nColsUsed;
88 : sal_uInt32 nColsImportant;
89 :
90 3286 : DIBInfoHeader()
91 : : nSize(0UL),
92 : nWidth(0UL),
93 : nHeight(0UL),
94 : nPlanes(0),
95 : nBitCount(0),
96 : nCompression(0),
97 : nSizeImage(0),
98 : nXPelsPerMeter(0UL),
99 : nYPelsPerMeter(0UL),
100 : nColsUsed(0UL),
101 3286 : nColsImportant(0UL)
102 3286 : {}
103 :
104 3286 : ~DIBInfoHeader()
105 3286 : {}
106 : };
107 :
108 : struct DIBV5Header : public DIBInfoHeader
109 : {
110 : sal_uInt32 nV5RedMask;
111 : sal_uInt32 nV5GreenMask;
112 : sal_uInt32 nV5BlueMask;
113 : sal_uInt32 nV5AlphaMask;
114 : sal_uInt32 nV5CSType;
115 : CIEXYZTriple aV5Endpoints;
116 : sal_uInt32 nV5GammaRed;
117 : sal_uInt32 nV5GammaGreen;
118 : sal_uInt32 nV5GammaBlue;
119 : sal_uInt32 nV5Intent;
120 : sal_uInt32 nV5ProfileData;
121 : sal_uInt32 nV5ProfileSize;
122 : sal_uInt32 nV5Reserved;
123 :
124 3286 : DIBV5Header()
125 : : DIBInfoHeader(),
126 : nV5RedMask(0UL),
127 : nV5GreenMask(0UL),
128 : nV5BlueMask(0UL),
129 : nV5AlphaMask(0UL),
130 : nV5CSType(0UL),
131 : aV5Endpoints(),
132 : nV5GammaRed(0UL),
133 : nV5GammaGreen(0UL),
134 : nV5GammaBlue(0UL),
135 : nV5Intent(0UL),
136 : nV5ProfileData(0UL),
137 : nV5ProfileSize(0UL),
138 3286 : nV5Reserved(0UL)
139 3286 : {}
140 :
141 3286 : ~DIBV5Header()
142 3286 : {}
143 : };
144 :
145 : namespace
146 : {
147 1728 : inline sal_uInt16 discretizeBitcount( sal_uInt16 nInputCount )
148 : {
149 : return ( nInputCount <= 1 ) ? 1 :
150 : ( nInputCount <= 4 ) ? 4 :
151 1728 : ( nInputCount <= 8 ) ? 8 : 24;
152 : }
153 :
154 2067 : inline bool isBitfieldCompression( sal_uLong nScanlineFormat )
155 : {
156 2067 : return (BMP_FORMAT_16BIT_TC_LSB_MASK == nScanlineFormat) || (BMP_FORMAT_32BIT_TC_MASK == nScanlineFormat);
157 : }
158 : }
159 :
160 1715 : bool ImplReadDIBInfoHeader(SvStream& rIStm, DIBV5Header& rHeader, bool& bTopDown, bool bMSOFormat)
161 : {
162 : // BITMAPINFOHEADER or BITMAPCOREHEADER or BITMAPV5HEADER
163 1715 : const sal_Size aStartPos(rIStm.Tell());
164 1715 : rIStm.ReadUInt32( rHeader.nSize );
165 :
166 : // BITMAPCOREHEADER
167 1715 : if ( rHeader.nSize == DIBCOREHEADERSIZE )
168 : {
169 : sal_Int16 nTmp16;
170 :
171 1 : rIStm.ReadInt16( nTmp16 ); rHeader.nWidth = nTmp16;
172 1 : rIStm.ReadInt16( nTmp16 ); rHeader.nHeight = nTmp16;
173 1 : rIStm.ReadUInt16( rHeader.nPlanes );
174 1 : rIStm.ReadUInt16( rHeader.nBitCount );
175 : }
176 1714 : else if ( bMSOFormat && rHeader.nSize == DIBINFOHEADERSIZE )
177 : {
178 0 : sal_Int16 nTmp16(0);
179 0 : rIStm.ReadInt16(nTmp16);
180 0 : rHeader.nWidth = nTmp16;
181 0 : rIStm.ReadInt16(nTmp16);
182 0 : rHeader.nHeight = nTmp16;
183 0 : sal_uInt8 nTmp8(0);
184 0 : rIStm.ReadUChar(nTmp8);
185 0 : rHeader.nPlanes = nTmp8;
186 0 : rIStm.ReadUChar(nTmp8);
187 0 : rHeader.nBitCount = nTmp8;
188 0 : rIStm.ReadInt16(nTmp16);
189 0 : rHeader.nSizeImage = nTmp16;
190 0 : rIStm.ReadInt16(nTmp16);
191 0 : rHeader.nCompression = nTmp16;
192 0 : if ( !rHeader.nSizeImage ) // uncompressed?
193 0 : rHeader.nSizeImage = ((rHeader.nWidth * rHeader.nBitCount + 31) & ~31) / 8 * rHeader.nHeight;
194 0 : rIStm.ReadInt32( rHeader.nXPelsPerMeter );
195 0 : rIStm.ReadInt32( rHeader.nYPelsPerMeter );
196 0 : rIStm.ReadUInt32( rHeader.nColsUsed );
197 0 : rIStm.ReadUInt32( rHeader.nColsImportant );
198 : }
199 : else
200 : {
201 : // BITMAPCOREHEADER, BITMAPV5HEADER or unknown. Read as far as possible
202 1714 : sal_Size nUsed(sizeof(rHeader.nSize));
203 :
204 : // read DIBInfoHeader entries
205 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nWidth ); nUsed += sizeof(rHeader.nWidth); }
206 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nHeight ); nUsed += sizeof(rHeader.nHeight); }
207 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt16( rHeader.nPlanes ); nUsed += sizeof(rHeader.nPlanes); }
208 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt16( rHeader.nBitCount ); nUsed += sizeof(rHeader.nBitCount); }
209 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nCompression ); nUsed += sizeof(rHeader.nCompression); }
210 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nSizeImage ); nUsed += sizeof(rHeader.nSizeImage); }
211 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nXPelsPerMeter ); nUsed += sizeof(rHeader.nXPelsPerMeter); }
212 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nYPelsPerMeter ); nUsed += sizeof(rHeader.nYPelsPerMeter); }
213 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nColsUsed ); nUsed += sizeof(rHeader.nColsUsed); }
214 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nColsImportant ); nUsed += sizeof(rHeader.nColsImportant); }
215 :
216 : // read DIBV5HEADER members
217 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5RedMask ); nUsed += sizeof(rHeader.nV5RedMask); }
218 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GreenMask ); nUsed += sizeof(rHeader.nV5GreenMask); }
219 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5BlueMask ); nUsed += sizeof(rHeader.nV5BlueMask); }
220 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5AlphaMask ); nUsed += sizeof(rHeader.nV5AlphaMask); }
221 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5CSType ); nUsed += sizeof(rHeader.nV5CSType); }
222 :
223 : // read contained CIEXYZTriple's
224 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzRed.aXyzX ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzX); }
225 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzRed.aXyzY ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzY); }
226 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzRed.aXyzZ ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzZ); }
227 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzGreen.aXyzX ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzX); }
228 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzGreen.aXyzY ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzY); }
229 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzGreen.aXyzZ ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzZ); }
230 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzBlue.aXyzX ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzX); }
231 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzBlue.aXyzY ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzY); }
232 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzBlue.aXyzZ ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzZ); }
233 :
234 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GammaRed ); nUsed += sizeof(rHeader.nV5GammaRed); }
235 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GammaGreen ); nUsed += sizeof(rHeader.nV5GammaGreen); }
236 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GammaBlue ); nUsed += sizeof(rHeader.nV5GammaBlue); }
237 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5Intent ); nUsed += sizeof(rHeader.nV5Intent); }
238 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5ProfileData ); nUsed += sizeof(rHeader.nV5ProfileData); }
239 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5ProfileSize ); nUsed += sizeof(rHeader.nV5ProfileSize); }
240 1714 : if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5Reserved ); nUsed += sizeof(rHeader.nV5Reserved); }
241 :
242 : // seek to EndPos
243 1714 : rIStm.Seek(aStartPos + rHeader.nSize);
244 : }
245 :
246 1715 : if ( rHeader.nHeight < 0 )
247 : {
248 0 : bTopDown = true;
249 0 : rHeader.nHeight *= -1;
250 : }
251 : else
252 : {
253 1715 : bTopDown = false;
254 : }
255 :
256 1715 : if ( rHeader.nWidth < 0 )
257 : {
258 0 : rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
259 : }
260 :
261 : // #144105# protect a little against damaged files
262 : assert(rHeader.nHeight >= 0);
263 1715 : if (rHeader.nHeight != 0 && rHeader.nWidth >= 0
264 1206 : && (rHeader.nSizeImage / 16 / static_cast<sal_uInt32>(rHeader.nHeight)
265 603 : > static_cast<sal_uInt32>(rHeader.nWidth)))
266 : {
267 1 : rHeader.nSizeImage = 0;
268 : }
269 :
270 1715 : return( ( rHeader.nPlanes == 1 ) && ( rIStm.GetError() == 0UL ) );
271 : }
272 :
273 46 : bool ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, bool bQuad )
274 : {
275 46 : const sal_uInt16 nColors = rAcc.GetPaletteEntryCount();
276 46 : const sal_uLong nPalSize = nColors * ( bQuad ? 4UL : 3UL );
277 46 : BitmapColor aPalColor;
278 :
279 92 : boost::scoped_array<sal_uInt8> pEntries(new sal_uInt8[ nPalSize ]);
280 46 : if (rIStm.Read( pEntries.get(), nPalSize ) != nPalSize)
281 : {
282 1 : return false;
283 : }
284 :
285 45 : sal_uInt8* pTmpEntry = pEntries.get();
286 5552 : for( sal_uInt16 i = 0; i < nColors; i++ )
287 : {
288 5507 : aPalColor.SetBlue( *pTmpEntry++ );
289 5507 : aPalColor.SetGreen( *pTmpEntry++ );
290 5507 : aPalColor.SetRed( *pTmpEntry++ );
291 :
292 5507 : if( bQuad )
293 5507 : pTmpEntry++;
294 :
295 5507 : rAcc.SetPaletteColor( i, aPalColor );
296 : }
297 :
298 91 : return( rIStm.GetError() == 0UL );
299 : }
300 :
301 21 : bool ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, bool bRLE4 )
302 : {
303 21 : Scanline pRLE = pBuffer;
304 21 : Scanline pEndRLE = pBuffer + rHeader.nSizeImage;
305 21 : long nY = rHeader.nHeight - 1L;
306 21 : const sal_uLong nWidth = rAcc.Width();
307 : sal_uLong nCountByte;
308 : sal_uLong nRunByte;
309 21 : sal_uLong nX = 0UL;
310 : sal_uInt8 cTmp;
311 21 : bool bEndDecoding = false;
312 :
313 16698 : do
314 : {
315 16699 : if (pRLE == pEndRLE)
316 1 : return false;
317 16698 : if( ( nCountByte = *pRLE++ ) == 0 )
318 : {
319 4344 : if (pRLE == pEndRLE)
320 0 : return false;
321 4344 : nRunByte = *pRLE++;
322 :
323 4344 : if( nRunByte > 2 )
324 : {
325 2828 : if( bRLE4 )
326 : {
327 1670 : nCountByte = nRunByte >> 1;
328 :
329 7774 : for( sal_uLong i = 0UL; i < nCountByte; i++ )
330 : {
331 6104 : if (pRLE == pEndRLE)
332 0 : return false;
333 :
334 6104 : cTmp = *pRLE++;
335 :
336 6104 : if( nX < nWidth )
337 5500 : rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
338 :
339 6104 : if( nX < nWidth )
340 5500 : rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
341 : }
342 :
343 1670 : if( nRunByte & 1 )
344 : {
345 9 : if (pRLE == pEndRLE)
346 0 : return false;
347 :
348 9 : if( nX < nWidth )
349 0 : rAcc.SetPixelIndex( nY, nX++, *pRLE >> 4 );
350 :
351 9 : pRLE++;
352 : }
353 :
354 1670 : if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
355 : {
356 605 : if (pRLE == pEndRLE)
357 0 : return false;
358 :
359 605 : pRLE++;
360 : }
361 : }
362 : else
363 : {
364 7382 : for( sal_uLong i = 0UL; i < nRunByte; i++ )
365 : {
366 6224 : if (pRLE == pEndRLE)
367 0 : return false;
368 :
369 6224 : if( nX < nWidth )
370 6224 : rAcc.SetPixelIndex( nY, nX++, *pRLE );
371 :
372 6224 : pRLE++;
373 : }
374 :
375 1158 : if( nRunByte & 1 )
376 : {
377 712 : if (pRLE == pEndRLE)
378 0 : return false;
379 :
380 712 : pRLE++;
381 : }
382 : }
383 : }
384 1516 : else if( !nRunByte )
385 : {
386 1516 : nY--;
387 1516 : nX = 0UL;
388 : }
389 0 : else if( nRunByte == 1 )
390 0 : bEndDecoding = true;
391 : else
392 : {
393 0 : if (pRLE == pEndRLE)
394 0 : return false;
395 :
396 0 : nX += *pRLE++;
397 :
398 0 : if (pRLE == pEndRLE)
399 0 : return false;
400 :
401 0 : nY -= *pRLE++;
402 : }
403 : }
404 : else
405 : {
406 12354 : if (pRLE == pEndRLE)
407 0 : return false;
408 12354 : cTmp = *pRLE++;
409 :
410 12354 : if( bRLE4 )
411 : {
412 3173 : nRunByte = nCountByte >> 1;
413 :
414 70026 : for( sal_uLong i = 0UL; i < nRunByte; i++ )
415 : {
416 66853 : if( nX < nWidth )
417 58436 : rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
418 :
419 66853 : if( nX < nWidth )
420 58434 : rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
421 : }
422 :
423 3173 : if( ( nCountByte & 1 ) && ( nX < nWidth ) )
424 2 : rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
425 : }
426 : else
427 : {
428 125110 : for( sal_uLong i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
429 115929 : rAcc.SetPixelIndex( nY, nX++, cTmp );
430 : }
431 : }
432 : }
433 33396 : while (!bEndDecoding && (nY >= 0L));
434 :
435 20 : return true;
436 : }
437 :
438 599 : bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, BitmapWriteAccess* pAccAlpha, bool bTopDown, bool& rAlphaUsed)
439 : {
440 599 : const sal_Int64 nBitsPerLine (static_cast<sal_Int64>(rHeader.nWidth) * static_cast<sal_Int64>(rHeader.nBitCount));
441 599 : if (nBitsPerLine > SAL_MAX_UINT32)
442 0 : return false;
443 :
444 599 : const sal_uLong nAlignedWidth = AlignedWidth4Bytes(static_cast<sal_uLong>(nBitsPerLine));
445 599 : sal_uInt32 nRMask(( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL);
446 599 : sal_uInt32 nGMask(( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL);
447 599 : sal_uInt32 nBMask(( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL);
448 599 : bool bNative(false);
449 599 : bool bTCMask(!pAccAlpha && ((16 == rHeader.nBitCount) || (32 == rHeader.nBitCount)));
450 599 : bool bRLE((RLE_8 == rHeader.nCompression && 8 == rHeader.nBitCount) || (RLE_4 == rHeader.nCompression && 4 == rHeader.nBitCount));
451 :
452 : // Is native format?
453 599 : switch(rAcc.GetScanlineFormat())
454 : {
455 : case( BMP_FORMAT_1BIT_MSB_PAL ):
456 : case( BMP_FORMAT_4BIT_MSN_PAL ):
457 : case( BMP_FORMAT_8BIT_PAL ):
458 : case( BMP_FORMAT_24BIT_TC_BGR ):
459 : {
460 46 : bNative = ( ( static_cast< bool >(rAcc.IsBottomUp()) != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
461 46 : break;
462 : }
463 :
464 : default:
465 : {
466 553 : break;
467 : }
468 : }
469 :
470 : // Read data
471 599 : if(bNative)
472 : {
473 10 : if (nAlignedWidth
474 10 : > std::numeric_limits<sal_Size>::max() / rHeader.nHeight)
475 : {
476 0 : return false;
477 : }
478 10 : sal_Size n = nAlignedWidth * rHeader.nHeight;
479 10 : if (rIStm.Read(rAcc.GetBuffer(), n) != n)
480 : {
481 1 : return false;
482 : }
483 : }
484 : else
485 : {
486 : // Read color mask
487 589 : if(bTCMask && BITFIELDS == rHeader.nCompression)
488 : {
489 482 : rIStm.SeekRel( -12L );
490 482 : rIStm.ReadUInt32( nRMask );
491 482 : rIStm.ReadUInt32( nGMask );
492 482 : rIStm.ReadUInt32( nBMask );
493 : }
494 :
495 589 : if(bRLE)
496 : {
497 21 : if(!rHeader.nSizeImage)
498 : {
499 0 : rHeader.nSizeImage = rIStm.remainingSize();
500 : }
501 :
502 : boost::scoped_array<sal_uInt8> pBuffer(
503 21 : new sal_uInt8[rHeader.nSizeImage]);
504 42 : if (rIStm.Read(pBuffer.get(), rHeader.nSizeImage)
505 21 : != rHeader.nSizeImage)
506 : {
507 0 : return false;
508 : }
509 21 : ImplDecodeRLE(pBuffer.get(), rHeader, rAcc, RLE_4 == rHeader.nCompression);
510 : }
511 : else
512 : {
513 568 : const long nWidth(rHeader.nWidth);
514 568 : const long nHeight(rHeader.nHeight);
515 568 : boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[nAlignedWidth]);
516 :
517 568 : const long nI(bTopDown ? 1 : -1);
518 568 : long nY(bTopDown ? 0 : nHeight - 1);
519 568 : long nCount(nHeight);
520 :
521 568 : switch(rHeader.nBitCount)
522 : {
523 : case( 1 ):
524 : {
525 : sal_uInt8* pTmp;
526 : sal_uInt8 cTmp;
527 :
528 78 : for( ; nCount--; nY += nI )
529 : {
530 71 : if (rIStm.Read( pTmp = pBuf.get(), nAlignedWidth )
531 : != nAlignedWidth)
532 : {
533 0 : return false;
534 : }
535 71 : cTmp = *pTmp++;
536 :
537 834 : for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
538 : {
539 763 : if( !nShift )
540 : {
541 : nShift = 8L,
542 39 : cTmp = *pTmp++;
543 : }
544 :
545 763 : rAcc.SetPixelIndex( nY, nX, (cTmp >> --nShift) & 1);
546 : }
547 : }
548 : }
549 7 : break;
550 :
551 : case( 4 ):
552 : {
553 : sal_uInt8* pTmp;
554 : sal_uInt8 cTmp;
555 :
556 28 : for( ; nCount--; nY += nI )
557 : {
558 26 : if (rIStm.Read( pTmp = pBuf.get(), nAlignedWidth )
559 : != nAlignedWidth)
560 : {
561 0 : return false;
562 : }
563 26 : cTmp = *pTmp++;
564 :
565 2561 : for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
566 : {
567 2535 : if( !nShift )
568 : {
569 : nShift = 2UL,
570 1248 : cTmp = *pTmp++;
571 : }
572 :
573 2535 : rAcc.SetPixelIndex( nY, nX, (cTmp >> ( --nShift << 2UL ) ) & 0x0f);
574 : }
575 : }
576 : }
577 2 : break;
578 :
579 : case( 8 ):
580 : {
581 : sal_uInt8* pTmp;
582 :
583 337 : for( ; nCount--; nY += nI )
584 : {
585 333 : if (rIStm.Read( pTmp = pBuf.get(), nAlignedWidth )
586 : != nAlignedWidth)
587 : {
588 2 : return false;
589 : }
590 :
591 95518 : for( long nX = 0L; nX < nWidth; nX++ )
592 95187 : rAcc.SetPixelIndex( nY, nX, *pTmp++ );
593 : }
594 : }
595 4 : break;
596 :
597 : case( 16 ):
598 : {
599 1 : ColorMask aMask( nRMask, nGMask, nBMask );
600 2 : BitmapColor aColor;
601 : sal_uInt16* pTmp16;
602 :
603 33 : for( ; nCount--; nY += nI )
604 : {
605 32 : if (rIStm.Read( ( pTmp16 = reinterpret_cast<sal_uInt16*>(pBuf.get()) ), nAlignedWidth )
606 : != nAlignedWidth)
607 : {
608 0 : return false;
609 : }
610 :
611 1056 : for( long nX = 0L; nX < nWidth; nX++ )
612 : {
613 1024 : aMask.GetColorFor16BitLSB( aColor, reinterpret_cast<sal_uInt8*>(pTmp16++) );
614 1024 : rAcc.SetPixel( nY, nX, aColor );
615 : }
616 1 : }
617 : }
618 1 : break;
619 :
620 : case( 24 ):
621 : {
622 67 : BitmapColor aPixelColor;
623 : sal_uInt8* pTmp;
624 :
625 3541 : for( ; nCount--; nY += nI )
626 : {
627 3474 : if (rIStm.Read( pTmp = pBuf.get(), nAlignedWidth )
628 : != nAlignedWidth)
629 : {
630 0 : return false;
631 : }
632 :
633 4668855 : for( long nX = 0L; nX < nWidth; nX++ )
634 : {
635 4665381 : aPixelColor.SetBlue( *pTmp++ );
636 4665381 : aPixelColor.SetGreen( *pTmp++ );
637 4665381 : aPixelColor.SetRed( *pTmp++ );
638 4665381 : rAcc.SetPixel( nY, nX, aPixelColor );
639 : }
640 67 : }
641 : }
642 67 : break;
643 :
644 : case( 32 ):
645 : {
646 485 : ColorMask aMask(nRMask, nGMask, nBMask);
647 970 : BitmapColor aColor;
648 : sal_uInt32* pTmp32;
649 :
650 485 : if(pAccAlpha)
651 : {
652 : sal_uInt8 aAlpha;
653 :
654 0 : for( ; nCount--; nY += nI )
655 : {
656 0 : if (rIStm.Read( ( pTmp32 = reinterpret_cast<sal_uInt32*>(pBuf.get()) ), nAlignedWidth )
657 : != nAlignedWidth)
658 : {
659 0 : return false;
660 : }
661 :
662 0 : for( long nX = 0L; nX < nWidth; nX++ )
663 : {
664 0 : aMask.GetColorAndAlphaFor32Bit( aColor, aAlpha, reinterpret_cast<sal_uInt8*>(pTmp32++) );
665 0 : rAcc.SetPixel( nY, nX, aColor );
666 0 : pAccAlpha->SetPixelIndex(nY, nX, sal_uInt8(0xff) - aAlpha);
667 0 : rAlphaUsed |= bool(0xff != aAlpha);
668 : }
669 : }
670 : }
671 : else
672 : {
673 31473 : for( ; nCount--; nY += nI )
674 : {
675 30988 : if (rIStm.Read( ( pTmp32 = reinterpret_cast<sal_uInt32*>(pBuf.get()) ), nAlignedWidth )
676 : != nAlignedWidth)
677 : {
678 0 : return false;
679 : }
680 :
681 14104084 : for( long nX = 0L; nX < nWidth; nX++ )
682 : {
683 14073096 : aMask.GetColorFor32Bit( aColor, reinterpret_cast<sal_uInt8*>(pTmp32++) );
684 14073096 : rAcc.SetPixel( nY, nX, aColor );
685 : }
686 : }
687 485 : }
688 : }
689 566 : }
690 : }
691 : }
692 :
693 596 : return( rIStm.GetError() == 0UL );
694 : }
695 :
696 1715 : bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLong nOffset, bool bMSOFormat = false )
697 : {
698 1715 : DIBV5Header aHeader;
699 1715 : const sal_uLong nStmPos = rIStm.Tell();
700 1715 : bool bRet(false);
701 1715 : bool bTopDown(false);
702 :
703 1715 : if(ImplReadDIBInfoHeader(rIStm, aHeader, bTopDown, bMSOFormat) && aHeader.nWidth && aHeader.nHeight && aHeader.nBitCount)
704 : {
705 : // In case ImplReadDIB() didn't call ImplReadDIBFileHeader() before
706 : // this method, nOffset is 0, that's OK.
707 602 : if (nOffset && aHeader.nSize > nOffset)
708 : {
709 : // Header size claims to extend into the image data.
710 : // Looks like an error.
711 0 : return false;
712 : }
713 :
714 602 : const sal_uInt16 nBitCount(discretizeBitcount(aHeader.nBitCount));
715 602 : const Size aSizePixel(aHeader.nWidth, aHeader.nHeight);
716 602 : BitmapPalette aDummyPal;
717 1204 : Bitmap aNewBmp(aSizePixel, nBitCount, &aDummyPal);
718 1204 : Bitmap aNewBmpAlpha;
719 602 : BitmapWriteAccess* pAcc = aNewBmp.AcquireWriteAccess();
720 602 : BitmapWriteAccess* pAccAlpha = 0;
721 602 : bool bAlphaPossible(pBmpAlpha && aHeader.nBitCount == 32);
722 :
723 602 : if(bAlphaPossible)
724 : {
725 0 : const bool bRedSet(0 != aHeader.nV5RedMask);
726 0 : const bool bGreenSet(0 != aHeader.nV5GreenMask);
727 0 : const bool bBlueSet(0 != aHeader.nV5BlueMask);
728 :
729 : // some clipboard entries have alpha mask on zero to say that there is
730 : // no alpha; do only use this when the other masks are set. The MS docu
731 : // says that masks are only to be set when bV5Compression is set to
732 : // BI_BITFIELDS, but there seem to exist a wild variety of usages...
733 0 : if((bRedSet || bGreenSet || bBlueSet) && (0 == aHeader.nV5AlphaMask))
734 : {
735 0 : bAlphaPossible = false;
736 : }
737 : }
738 :
739 602 : if(bAlphaPossible)
740 : {
741 0 : aNewBmpAlpha = Bitmap(aSizePixel, 8);
742 0 : pAccAlpha = aNewBmpAlpha.AcquireWriteAccess();
743 : }
744 :
745 602 : if(pAcc)
746 : {
747 599 : sal_uInt16 nColors(0);
748 : SvStream* pIStm;
749 599 : SvMemoryStream* pMemStm = NULL;
750 599 : sal_uInt8* pData = NULL;
751 :
752 599 : if (aHeader.nBitCount <= 8)
753 : {
754 46 : if(aHeader.nColsUsed)
755 : {
756 35 : nColors = (sal_uInt16)aHeader.nColsUsed;
757 : }
758 : else
759 : {
760 11 : nColors = ( 1 << aHeader.nBitCount );
761 : }
762 : }
763 :
764 599 : if(ZCOMPRESS == aHeader.nCompression)
765 : {
766 4 : ZCodec aCodec;
767 4 : sal_uInt32 nCodedSize(0);
768 4 : sal_uInt32 nUncodedSize(0);
769 4 : sal_uLong nCodedPos(0);
770 :
771 : // read coding information
772 4 : rIStm.ReadUInt32( nCodedSize ).ReadUInt32( nUncodedSize ).ReadUInt32( aHeader.nCompression );
773 4 : pData = static_cast<sal_uInt8*>(rtl_allocateMemory( nUncodedSize ));
774 :
775 : // decode buffer
776 4 : nCodedPos = rIStm.Tell();
777 4 : aCodec.BeginCompression();
778 4 : aCodec.Read( rIStm, pData, nUncodedSize );
779 4 : aCodec.EndCompression();
780 :
781 : // skip unread bytes from coded buffer
782 4 : rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
783 :
784 : // set decoded bytes to memory stream,
785 : // from which we will read the bitmap data
786 4 : pIStm = pMemStm = new SvMemoryStream;
787 4 : pMemStm->SetBuffer( pData, nUncodedSize, false, nUncodedSize );
788 4 : nOffset = 0;
789 : }
790 : else
791 : {
792 595 : pIStm = &rIStm;
793 : }
794 :
795 : // read palette
796 599 : if(nColors)
797 : {
798 46 : pAcc->SetPaletteEntryCount(nColors);
799 46 : ImplReadDIBPalette(*pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE);
800 : }
801 :
802 : // read bits
803 599 : bool bAlphaUsed(false);
804 :
805 599 : if(!pIStm->GetError())
806 : {
807 599 : if(nOffset)
808 : {
809 536 : pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
810 : }
811 :
812 599 : bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, pAccAlpha, bTopDown, bAlphaUsed);
813 :
814 599 : if(bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter)
815 : {
816 : MapMode aMapMode(
817 : MAP_MM,
818 : Point(),
819 : Fraction(1000, aHeader.nXPelsPerMeter),
820 98 : Fraction(1000, aHeader.nYPelsPerMeter));
821 :
822 98 : aNewBmp.SetPrefMapMode(aMapMode);
823 98 : aNewBmp.SetPrefSize(Size(aHeader.nWidth, aHeader.nHeight));
824 : }
825 : }
826 :
827 599 : if( pData )
828 : {
829 4 : rtl_freeMemory(pData);
830 : }
831 :
832 599 : delete pMemStm;
833 599 : Bitmap::ReleaseAccess(pAcc);
834 :
835 599 : if(bAlphaPossible)
836 : {
837 0 : Bitmap::ReleaseAccess(pAccAlpha);
838 :
839 0 : if(!bAlphaUsed)
840 : {
841 0 : bAlphaPossible = false;
842 : }
843 : }
844 :
845 599 : if(bRet)
846 : {
847 596 : rBmp = aNewBmp;
848 :
849 596 : if(bAlphaPossible)
850 : {
851 0 : *pBmpAlpha = aNewBmpAlpha;
852 : }
853 : }
854 602 : }
855 : }
856 :
857 1715 : return bRet;
858 : }
859 :
860 6616 : bool ImplReadDIBFileHeader( SvStream& rIStm, sal_uLong& rOffset )
861 : {
862 6616 : bool bRet = false;
863 :
864 6616 : const sal_uInt64 nSavedStreamPos( rIStm.Tell() );
865 6616 : const sal_uInt64 nStreamLength( rIStm.Seek( STREAM_SEEK_TO_END ) );
866 6616 : rIStm.Seek( nSavedStreamPos );
867 :
868 6616 : sal_uInt16 nTmp16 = 0;
869 6616 : rIStm.ReadUInt16( nTmp16 );
870 :
871 6616 : if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
872 : {
873 1659 : sal_uInt32 nTmp32(0);
874 1659 : if ( 0x4142 == nTmp16 )
875 : {
876 0 : rIStm.SeekRel( 12L );
877 0 : rIStm.ReadUInt16( nTmp16 );
878 0 : rIStm.SeekRel( 8L );
879 0 : rIStm.ReadUInt32( nTmp32 );
880 0 : rOffset = nTmp32 - 28UL;
881 0 : bRet = ( 0x4D42 == nTmp16 );
882 : }
883 : else // 0x4D42 == nTmp16, 'MB' from BITMAPFILEHEADER
884 : {
885 1659 : rIStm.SeekRel( 8L ); // we are on bfSize member of BITMAPFILEHEADER, forward to bfOffBits
886 1659 : rIStm.ReadUInt32( nTmp32 ); // read bfOffBits
887 1659 : rOffset = nTmp32 - 14UL; // adapt offset by sizeof(BITMAPFILEHEADER)
888 1659 : bRet = ( rIStm.GetError() == 0UL );
889 : }
890 :
891 1659 : if ( rOffset >= nStreamLength )
892 : {
893 : // Offset claims that image starts past the end of the
894 : // stream. Unlikely.
895 3 : rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
896 3 : bRet = false;
897 1659 : }
898 : }
899 : else
900 4957 : rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
901 :
902 6616 : return bRet;
903 : }
904 :
905 1055 : bool ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
906 : {
907 1055 : const sal_uInt16 nColors = rAcc.GetPaletteEntryCount();
908 1055 : const sal_uLong nPalSize = nColors * 4UL;
909 1055 : boost::scoped_array<sal_uInt8> pEntries(new sal_uInt8[ nPalSize ]);
910 1055 : sal_uInt8* pTmpEntry = pEntries.get();
911 2110 : BitmapColor aPalColor;
912 :
913 254893 : for( sal_uInt16 i = 0; i < nColors; i++ )
914 : {
915 253838 : const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
916 :
917 253838 : *pTmpEntry++ = rPalColor.GetBlue();
918 253838 : *pTmpEntry++ = rPalColor.GetGreen();
919 253838 : *pTmpEntry++ = rPalColor.GetRed();
920 253838 : *pTmpEntry++ = 0;
921 : }
922 :
923 1055 : rOStm.Write( pEntries.get(), nPalSize );
924 :
925 2110 : return( rOStm.GetError() == 0UL );
926 : }
927 :
928 984 : bool ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, bool bRLE4 )
929 : {
930 984 : const sal_uLong nWidth = rAcc.Width();
931 984 : const sal_uLong nHeight = rAcc.Height();
932 : sal_uLong nX;
933 : sal_uLong nSaveIndex;
934 : sal_uLong nCount;
935 : sal_uLong nBufCount;
936 984 : boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[ ( nWidth << 1 ) + 2 ]);
937 : sal_uInt8* pTmp;
938 : sal_uInt8 cPix;
939 : sal_uInt8 cLast;
940 : bool bFound;
941 :
942 67907 : for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
943 : {
944 66923 : pTmp = pBuf.get();
945 66923 : nX = nBufCount = 0UL;
946 :
947 1036385 : while( nX < nWidth )
948 : {
949 902539 : nCount = 1L;
950 902539 : cPix = rAcc.GetPixelIndex( nY, nX++ );
951 :
952 8902782 : while( ( nX < nWidth ) && ( nCount < 255L )
953 8000217 : && ( cPix == rAcc.GetPixelIndex( nY, nX ) ) )
954 : {
955 3131044 : nX++;
956 3131044 : nCount++;
957 : }
958 :
959 902539 : if ( nCount > 1 )
960 : {
961 523106 : *pTmp++ = (sal_uInt8) nCount;
962 523106 : *pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
963 523106 : nBufCount += 2;
964 : }
965 : else
966 : {
967 379433 : cLast = cPix;
968 379433 : nSaveIndex = nX - 1UL;
969 379433 : bFound = false;
970 :
971 3827931 : while( ( nX < nWidth ) && ( nCount < 256L )
972 3448498 : && ( cPix = rAcc.GetPixelIndex( nY, nX ) ) != cLast )
973 : {
974 1362579 : nX++; nCount++;
975 1362579 : cLast = cPix;
976 1362579 : bFound = true;
977 : }
978 :
979 379433 : if ( bFound )
980 358385 : nX--;
981 :
982 379433 : if ( nCount > 3 )
983 : {
984 183526 : *pTmp++ = 0;
985 183526 : *pTmp++ = (sal_uInt8) --nCount;
986 :
987 183526 : if( bRLE4 )
988 : {
989 0 : for ( sal_uLong i = 0; i < nCount; i++, pTmp++ )
990 : {
991 0 : *pTmp = rAcc.GetPixelIndex( nY, nSaveIndex++ ) << 4;
992 :
993 0 : if ( ++i < nCount )
994 0 : *pTmp |= rAcc.GetPixelIndex( nY, nSaveIndex++ );
995 : }
996 :
997 0 : nCount = ( nCount + 1 ) >> 1;
998 : }
999 : else
1000 : {
1001 1311408 : for( sal_uLong i = 0UL; i < nCount; i++ )
1002 1127882 : *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex++ );
1003 : }
1004 :
1005 183526 : if ( nCount & 1 )
1006 : {
1007 107898 : *pTmp++ = 0;
1008 107898 : nBufCount += ( nCount + 3 );
1009 : }
1010 : else
1011 75628 : nBufCount += ( nCount + 2 );
1012 : }
1013 : else
1014 : {
1015 195907 : *pTmp++ = 1;
1016 195907 : *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex ) << (bRLE4 ? 4 : 0);
1017 :
1018 195907 : if ( nCount == 3 )
1019 : {
1020 59838 : *pTmp++ = 1;
1021 59838 : *pTmp++ = rAcc.GetPixelIndex( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
1022 59838 : nBufCount += 4;
1023 : }
1024 : else
1025 136069 : nBufCount += 2;
1026 : }
1027 : }
1028 : }
1029 :
1030 66923 : pBuf[ nBufCount++ ] = 0;
1031 66923 : pBuf[ nBufCount++ ] = 0;
1032 :
1033 66923 : rOStm.Write( pBuf.get(), nBufCount );
1034 : }
1035 :
1036 984 : rOStm.WriteUChar( 0 );
1037 984 : rOStm.WriteUChar( 1 );
1038 :
1039 984 : return( rOStm.GetError() == 0UL );
1040 : }
1041 :
1042 1571 : bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, sal_uLong nCompression, sal_uInt32& rImageSize)
1043 : {
1044 1571 : if(!pAccAlpha && BITFIELDS == nCompression)
1045 : {
1046 516 : const ColorMask& rMask = rAcc.GetColorMask();
1047 : SVBT32 aVal32;
1048 :
1049 516 : UInt32ToSVBT32( rMask.GetRedMask(), aVal32 );
1050 516 : rOStm.Write( aVal32, 4UL );
1051 :
1052 516 : UInt32ToSVBT32( rMask.GetGreenMask(), aVal32 );
1053 516 : rOStm.Write( aVal32, 4UL );
1054 :
1055 516 : UInt32ToSVBT32( rMask.GetBlueMask(), aVal32 );
1056 516 : rOStm.Write( aVal32, 4UL );
1057 :
1058 516 : rImageSize = rOStm.Tell();
1059 :
1060 516 : if( rAcc.IsBottomUp() )
1061 516 : rOStm.Write( rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize() );
1062 : else
1063 : {
1064 0 : for( long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0L; nY-- )
1065 0 : rOStm.Write( rAcc.GetScanline( nY ), nScanlineSize );
1066 516 : }
1067 : }
1068 1055 : else if(!pAccAlpha && ((RLE_4 == nCompression) || (RLE_8 == nCompression)))
1069 : {
1070 984 : rImageSize = rOStm.Tell();
1071 984 : ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
1072 : }
1073 71 : else if(!nCompression)
1074 : {
1075 : // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are not
1076 : // handled properly below (would have to set color masks, and
1077 : // nCompression=BITFIELDS - but color mask is not set for
1078 : // formats != *_TC_*). Note that this very problem might cause
1079 : // trouble at other places - the introduction of 32 bit RGBA
1080 : // bitmaps is relatively recent.
1081 : // #i59239# discretize bitcount for aligned width to 1,4,8,24
1082 : // (other cases are not written below)
1083 71 : const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
1084 71 : const sal_uLong nAlignedWidth(AlignedWidth4Bytes(rAcc.Width() * nBitCount));
1085 71 : bool bNative(false);
1086 :
1087 71 : switch(rAcc.GetScanlineFormat())
1088 : {
1089 : case( BMP_FORMAT_1BIT_MSB_PAL ):
1090 : case( BMP_FORMAT_4BIT_MSN_PAL ):
1091 : case( BMP_FORMAT_8BIT_PAL ):
1092 : case( BMP_FORMAT_24BIT_TC_BGR ):
1093 : {
1094 71 : if(!pAccAlpha && rAcc.IsBottomUp() && (rAcc.GetScanlineSize() == nAlignedWidth))
1095 : {
1096 21 : bNative = true;
1097 : }
1098 :
1099 71 : break;
1100 : }
1101 :
1102 : default:
1103 : {
1104 0 : break;
1105 : }
1106 : }
1107 :
1108 71 : rImageSize = rOStm.Tell();
1109 :
1110 71 : if(bNative)
1111 : {
1112 21 : rOStm.Write(rAcc.GetBuffer(), nAlignedWidth * rAcc.Height());
1113 : }
1114 : else
1115 : {
1116 50 : const long nWidth(rAcc.Width());
1117 50 : const long nHeight(rAcc.Height());
1118 50 : boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[ nAlignedWidth ]);
1119 50 : switch( nBitCount )
1120 : {
1121 : case( 1 ):
1122 : {
1123 : //valgrind, zero out the trailing unused alignment bytes
1124 42 : size_t nUnusedBytes = nAlignedWidth - ((nWidth+7) / 8);
1125 42 : memset(pBuf.get() + nAlignedWidth - nUnusedBytes, 0, nUnusedBytes);
1126 :
1127 1702 : for( long nY = nHeight - 1; nY >= 0L; nY-- )
1128 : {
1129 1660 : sal_uInt8* pTmp = pBuf.get();
1130 1660 : sal_uInt8 cTmp = 0;
1131 :
1132 1430725 : for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
1133 : {
1134 1429065 : if( !nShift )
1135 : {
1136 178395 : nShift = 8L;
1137 178395 : *pTmp++ = cTmp;
1138 178395 : cTmp = 0;
1139 : }
1140 :
1141 1429065 : cTmp |= rAcc.GetPixelIndex( nY, nX ) << --nShift;
1142 : }
1143 :
1144 1660 : *pTmp = cTmp;
1145 1660 : rOStm.Write( pBuf.get(), nAlignedWidth );
1146 : }
1147 : }
1148 42 : break;
1149 :
1150 : case( 4 ):
1151 : {
1152 : //valgrind, zero out the trailing unused alignment bytes
1153 1 : size_t nUnusedBytes = nAlignedWidth - ((nWidth+1) / 2);
1154 1 : memset(pBuf.get() + nAlignedWidth - nUnusedBytes, 0, nUnusedBytes);
1155 :
1156 17 : for( long nY = nHeight - 1; nY >= 0L; nY-- )
1157 : {
1158 16 : sal_uInt8* pTmp = pBuf.get();
1159 16 : sal_uInt8 cTmp = 0;
1160 :
1161 288 : for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
1162 : {
1163 272 : if( !nShift )
1164 : {
1165 128 : nShift = 2L;
1166 128 : *pTmp++ = cTmp;
1167 128 : cTmp = 0;
1168 : }
1169 :
1170 272 : cTmp |= rAcc.GetPixelIndex( nY, nX ) << ( --nShift << 2L );
1171 : }
1172 16 : *pTmp = cTmp;
1173 16 : rOStm.Write( pBuf.get(), nAlignedWidth );
1174 : }
1175 : }
1176 1 : break;
1177 :
1178 : case( 8 ):
1179 : {
1180 765 : for( long nY = nHeight - 1; nY >= 0L; nY-- )
1181 : {
1182 758 : sal_uInt8* pTmp = pBuf.get();
1183 :
1184 132322 : for( long nX = 0L; nX < nWidth; nX++ )
1185 131564 : *pTmp++ = rAcc.GetPixelIndex( nY, nX );
1186 :
1187 758 : rOStm.Write( pBuf.get(), nAlignedWidth );
1188 : }
1189 : }
1190 7 : break;
1191 :
1192 : // #i59239# fallback to 24 bit format, if bitcount is non-default
1193 : default:
1194 : // FALLTHROUGH intended
1195 : case( 24 ):
1196 : {
1197 0 : BitmapColor aPixelColor;
1198 0 : const bool bWriteAlpha(32 == nBitCount && pAccAlpha);
1199 :
1200 0 : for( long nY = nHeight - 1; nY >= 0L; nY-- )
1201 : {
1202 0 : sal_uInt8* pTmp = pBuf.get();
1203 :
1204 0 : for( long nX = 0L; nX < nWidth; nX++ )
1205 : {
1206 : // when alpha is used, this may be non-24bit main bitmap, so use GetColor
1207 : // instead of GetPixel to ensure RGB value
1208 0 : aPixelColor = rAcc.GetColor( nY, nX );
1209 :
1210 0 : *pTmp++ = aPixelColor.GetBlue();
1211 0 : *pTmp++ = aPixelColor.GetGreen();
1212 0 : *pTmp++ = aPixelColor.GetRed();
1213 :
1214 0 : if(bWriteAlpha)
1215 : {
1216 0 : *pTmp++ = (sal_uInt8)0xff - (sal_uInt8)pAccAlpha->GetPixelIndex( nY, nX );
1217 : }
1218 : }
1219 :
1220 0 : rOStm.Write( pBuf.get(), nAlignedWidth );
1221 0 : }
1222 : }
1223 0 : break;
1224 50 : }
1225 : }
1226 : }
1227 :
1228 1571 : rImageSize = rOStm.Tell() - rImageSize;
1229 :
1230 1571 : return (!rOStm.GetError());
1231 : }
1232 :
1233 1571 : bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, bool bCompressed)
1234 : {
1235 1571 : const MapMode aMapPixel(MAP_PIXEL);
1236 3142 : DIBV5Header aHeader;
1237 1571 : sal_uLong nImageSizePos(0);
1238 1571 : sal_uLong nEndPos(0);
1239 1571 : sal_uInt32 nCompression(COMPRESS_NONE);
1240 1571 : bool bRet(false);
1241 :
1242 1571 : aHeader.nSize = pAccAlpha ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE; // size dependent on CF_DIB type to use
1243 1571 : aHeader.nWidth = rAcc.Width();
1244 1571 : aHeader.nHeight = rAcc.Height();
1245 1571 : aHeader.nPlanes = 1;
1246 :
1247 1571 : if(!pAccAlpha && isBitfieldCompression(rAcc.GetScanlineFormat()))
1248 : {
1249 516 : aHeader.nBitCount = (BMP_FORMAT_16BIT_TC_LSB_MASK == rAcc.GetScanlineFormat()) ? 16 : 32;
1250 516 : aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize();
1251 516 : nCompression = BITFIELDS;
1252 : }
1253 : else
1254 : {
1255 : // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are
1256 : // not handled properly below (would have to set color
1257 : // masks, and nCompression=BITFIELDS - but color mask is
1258 : // not set for formats != *_TC_*). Note that this very
1259 : // problem might cause trouble at other places - the
1260 : // introduction of 32 bit RGBA bitmaps is relatively
1261 : // recent.
1262 : // #i59239# discretize bitcount to 1,4,8,24 (other cases
1263 : // are not written below)
1264 1055 : const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
1265 1055 : aHeader.nBitCount = nBitCount;
1266 1055 : aHeader.nSizeImage = rAcc.Height() * AlignedWidth4Bytes(rAcc.Width() * aHeader.nBitCount);
1267 :
1268 1055 : if(bCompressed)
1269 : {
1270 1040 : if(4 == nBitCount)
1271 : {
1272 0 : nCompression = RLE_4;
1273 : }
1274 1040 : else if(8 == nBitCount)
1275 : {
1276 984 : nCompression = RLE_8;
1277 : }
1278 : }
1279 : }
1280 :
1281 1571 : if((rOStm.GetCompressMode() & SvStreamCompressFlags::ZBITMAP) && (rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40))
1282 : {
1283 971 : aHeader.nCompression = ZCOMPRESS;
1284 : }
1285 : else
1286 : {
1287 600 : aHeader.nCompression = nCompression;
1288 : }
1289 :
1290 1571 : if(rBitmap.GetPrefSize().Width() && rBitmap.GetPrefSize().Height() && (rBitmap.GetPrefMapMode() != aMapPixel))
1291 : {
1292 : // #i48108# Try to recover xpels/ypels as previously stored on
1293 : // disk. The problem with just converting maPrefSize to 100th
1294 : // mm and then relating that to the bitmap pixel size is that
1295 : // MapMode is integer-based, and suffers from roundoffs,
1296 : // especially if maPrefSize is small. Trying to circumvent
1297 : // that by performing part of the math in floating point.
1298 133 : const Size aScale100000(OutputDevice::LogicToLogic(Size(100000L, 100000L), MAP_100TH_MM, rBitmap.GetPrefMapMode()));
1299 133 : const double fBmpWidthM((double)rBitmap.GetPrefSize().Width() / aScale100000.Width());
1300 133 : const double fBmpHeightM((double)rBitmap.GetPrefSize().Height() / aScale100000.Height());
1301 :
1302 133 : if(!basegfx::fTools::equalZero(fBmpWidthM) && !basegfx::fTools::equalZero(fBmpHeightM))
1303 : {
1304 133 : aHeader.nXPelsPerMeter = basegfx::fround(rAcc.Width() / fabs(fBmpWidthM));
1305 133 : aHeader.nYPelsPerMeter = basegfx::fround(rAcc.Height() / fabs(fBmpHeightM));
1306 : }
1307 : }
1308 :
1309 1571 : aHeader.nColsUsed = ((!pAccAlpha && aHeader.nBitCount <= 8) ? rAcc.GetPaletteEntryCount() : 0);
1310 1571 : aHeader.nColsImportant = 0;
1311 :
1312 1571 : rOStm.WriteUInt32( aHeader.nSize );
1313 1571 : rOStm.WriteInt32( aHeader.nWidth );
1314 1571 : rOStm.WriteInt32( aHeader.nHeight );
1315 1571 : rOStm.WriteUInt16( aHeader.nPlanes );
1316 1571 : rOStm.WriteUInt16( aHeader.nBitCount );
1317 1571 : rOStm.WriteUInt32( aHeader.nCompression );
1318 :
1319 1571 : nImageSizePos = rOStm.Tell();
1320 1571 : rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
1321 :
1322 1571 : rOStm.WriteInt32( aHeader.nXPelsPerMeter );
1323 1571 : rOStm.WriteInt32( aHeader.nYPelsPerMeter );
1324 1571 : rOStm.WriteUInt32( aHeader.nColsUsed );
1325 1571 : rOStm.WriteUInt32( aHeader.nColsImportant );
1326 :
1327 1571 : if(pAccAlpha) // only write DIBV5 when asked to do so
1328 : {
1329 0 : aHeader.nV5CSType = 0x57696E20; // LCS_WINDOWS_COLOR_SPACE
1330 0 : aHeader.nV5Intent = 0x00000004; // LCS_GM_IMAGES
1331 :
1332 0 : rOStm.WriteUInt32( aHeader.nV5RedMask );
1333 0 : rOStm.WriteUInt32( aHeader.nV5GreenMask );
1334 0 : rOStm.WriteUInt32( aHeader.nV5BlueMask );
1335 0 : rOStm.WriteUInt32( aHeader.nV5AlphaMask );
1336 0 : rOStm.WriteUInt32( aHeader.nV5CSType );
1337 :
1338 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzRed.aXyzX );
1339 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzRed.aXyzY );
1340 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzRed.aXyzZ );
1341 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzGreen.aXyzX );
1342 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzGreen.aXyzY );
1343 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzGreen.aXyzZ );
1344 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzBlue.aXyzX );
1345 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzBlue.aXyzY );
1346 0 : rOStm.WriteInt32( aHeader.aV5Endpoints.aXyzBlue.aXyzZ );
1347 :
1348 0 : rOStm.WriteUInt32( aHeader.nV5GammaRed );
1349 0 : rOStm.WriteUInt32( aHeader.nV5GammaGreen );
1350 0 : rOStm.WriteUInt32( aHeader.nV5GammaBlue );
1351 0 : rOStm.WriteUInt32( aHeader.nV5Intent );
1352 0 : rOStm.WriteUInt32( aHeader.nV5ProfileData );
1353 0 : rOStm.WriteUInt32( aHeader.nV5ProfileSize );
1354 0 : rOStm.WriteUInt32( aHeader.nV5Reserved );
1355 : }
1356 :
1357 1571 : if(ZCOMPRESS == aHeader.nCompression)
1358 : {
1359 971 : ZCodec aCodec;
1360 1942 : SvMemoryStream aMemStm(aHeader.nSizeImage + 4096, 65535);
1361 971 : sal_uLong nCodedPos(rOStm.Tell());
1362 971 : sal_uLong nLastPos(0);
1363 971 : sal_uInt32 nCodedSize(0);
1364 971 : sal_uInt32 nUncodedSize(0);
1365 :
1366 : // write uncoded data palette
1367 971 : if(aHeader.nColsUsed)
1368 : {
1369 971 : ImplWriteDIBPalette(aMemStm, rAcc);
1370 : }
1371 :
1372 : // write uncoded bits
1373 971 : bRet = ImplWriteDIBBits(aMemStm, rAcc, pAccAlpha, nCompression, aHeader.nSizeImage);
1374 :
1375 : // get uncoded size
1376 971 : nUncodedSize = aMemStm.Tell();
1377 :
1378 : // seek over compress info
1379 971 : rOStm.SeekRel(12);
1380 :
1381 : // write compressed data
1382 971 : aCodec.BeginCompression(3);
1383 971 : aCodec.Write(rOStm, static_cast<sal_uInt8 const *>(aMemStm.GetData()), nUncodedSize);
1384 971 : aCodec.EndCompression();
1385 :
1386 : // update compress info ( coded size, uncoded size, uncoded compression )
1387 971 : nLastPos = rOStm.Tell();
1388 971 : nCodedSize = nLastPos - nCodedPos - 12;
1389 971 : rOStm.Seek(nCodedPos);
1390 971 : rOStm.WriteUInt32( nCodedSize ).WriteUInt32( nUncodedSize ).WriteUInt32( nCompression );
1391 971 : rOStm.Seek(nLastPos);
1392 :
1393 971 : if(bRet)
1394 : {
1395 971 : bRet = (ERRCODE_NONE == rOStm.GetError());
1396 971 : }
1397 : }
1398 : else
1399 : {
1400 600 : if(aHeader.nColsUsed)
1401 : {
1402 84 : ImplWriteDIBPalette(rOStm, rAcc);
1403 : }
1404 :
1405 600 : bRet = ImplWriteDIBBits(rOStm, rAcc, pAccAlpha, aHeader.nCompression, aHeader.nSizeImage);
1406 : }
1407 :
1408 1571 : nEndPos = rOStm.Tell();
1409 1571 : rOStm.Seek(nImageSizePos);
1410 1571 : rOStm.WriteUInt32( aHeader.nSizeImage );
1411 1571 : rOStm.Seek(nEndPos);
1412 :
1413 3142 : return bRet;
1414 : }
1415 :
1416 1540 : bool ImplWriteDIBFileHeader(SvStream& rOStm, BitmapReadAccess& rAcc, bool bUseDIBV5)
1417 : {
1418 1540 : const sal_uInt32 nPalCount((rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : isBitfieldCompression(rAcc.GetScanlineFormat()) ? 3UL : 0UL));
1419 1540 : const sal_uInt32 nOffset(14 + (bUseDIBV5 ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE) + nPalCount * 4UL);
1420 :
1421 1540 : rOStm.WriteUInt16( 0x4D42 ); // 'MB' from BITMAPFILEHEADER
1422 1540 : rOStm.WriteUInt32( nOffset + (rAcc.Height() * rAcc.GetScanlineSize()) );
1423 1540 : rOStm.WriteUInt16( 0 );
1424 1540 : rOStm.WriteUInt16( 0 );
1425 1540 : rOStm.WriteUInt32( nOffset );
1426 :
1427 1540 : return( rOStm.GetError() == 0UL );
1428 : }
1429 :
1430 6675 : bool ImplReadDIB(
1431 : Bitmap& rTarget, Bitmap*
1432 : pTargetAlpha,
1433 : SvStream& rIStm,
1434 : bool bFileHeader,
1435 : bool bMSOFormat=false)
1436 : {
1437 6675 : const SvStreamEndian nOldFormat(rIStm.GetEndian());
1438 6675 : const sal_uLong nOldPos(rIStm.Tell());
1439 6675 : sal_uLong nOffset(0UL);
1440 6675 : bool bRet(false);
1441 :
1442 6675 : rIStm.SetEndian(SvStreamEndian::LITTLE);
1443 :
1444 6675 : if(bFileHeader)
1445 : {
1446 6616 : if(ImplReadDIBFileHeader(rIStm, nOffset))
1447 : {
1448 1656 : bRet = ImplReadDIBBody(rIStm, rTarget, nOffset >= DIBV5HEADERSIZE ? pTargetAlpha : 0, nOffset);
1449 : }
1450 : }
1451 : else
1452 : {
1453 59 : bRet = ImplReadDIBBody(rIStm, rTarget, 0, nOffset, bMSOFormat);
1454 : }
1455 :
1456 6675 : if(!bRet)
1457 : {
1458 6079 : if(!rIStm.GetError())
1459 : {
1460 1119 : rIStm.SetError(SVSTREAM_GENERALERROR);
1461 : }
1462 :
1463 6079 : rIStm.Seek(nOldPos);
1464 : }
1465 :
1466 6675 : rIStm.SetEndian(nOldFormat);
1467 :
1468 6675 : return bRet;
1469 : }
1470 :
1471 1571 : bool ImplWriteDIB(
1472 : const Bitmap& rSource,
1473 : const Bitmap* pSourceAlpha,
1474 : SvStream& rOStm,
1475 : bool bCompressed,
1476 : bool bFileHeader)
1477 : {
1478 1571 : const Size aSizePix(rSource.GetSizePixel());
1479 1571 : bool bRet(false);
1480 :
1481 1571 : if(aSizePix.Width() && aSizePix.Height())
1482 : {
1483 1571 : BitmapReadAccess* pAcc = const_cast< Bitmap& >(rSource).AcquireReadAccess();
1484 1571 : BitmapReadAccess* pAccAlpha = 0;
1485 1571 : const SvStreamEndian nOldFormat(rOStm.GetEndian());
1486 1571 : const sal_uLong nOldPos(rOStm.Tell());
1487 :
1488 1571 : if(pSourceAlpha)
1489 : {
1490 0 : const Size aSizePixAlpha(pSourceAlpha->GetSizePixel());
1491 :
1492 0 : if(aSizePixAlpha == aSizePix)
1493 : {
1494 0 : pAccAlpha = const_cast< Bitmap* >(pSourceAlpha)->AcquireReadAccess();
1495 : }
1496 : else
1497 : {
1498 : OSL_ENSURE(false, "WriteDIB got an alpha channel, but it's pixel size differs from the base bitmap (!)");
1499 : }
1500 : }
1501 :
1502 1571 : rOStm.SetEndian(SvStreamEndian::LITTLE);
1503 :
1504 1571 : if(pAcc)
1505 : {
1506 1571 : if(bFileHeader)
1507 : {
1508 1540 : if(ImplWriteDIBFileHeader(rOStm, *pAcc, 0 != pSourceAlpha))
1509 : {
1510 1540 : bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
1511 : }
1512 : }
1513 : else
1514 : {
1515 31 : bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
1516 : }
1517 :
1518 1571 : Bitmap::ReleaseAccess(pAcc);
1519 :
1520 1571 : if(pAccAlpha)
1521 : {
1522 0 : Bitmap::ReleaseAccess(pAccAlpha);
1523 : }
1524 : }
1525 :
1526 1571 : if(!bRet)
1527 : {
1528 0 : rOStm.SetError(SVSTREAM_GENERALERROR);
1529 0 : rOStm.Seek(nOldPos);
1530 : }
1531 :
1532 1571 : rOStm.SetEndian(nOldFormat);
1533 : }
1534 :
1535 1571 : return bRet;
1536 : }
1537 :
1538 1623 : bool ReadDIB(
1539 : Bitmap& rTarget,
1540 : SvStream& rIStm,
1541 : bool bFileHeader,
1542 : bool bMSOFormat)
1543 : {
1544 1623 : return ImplReadDIB(rTarget, 0, rIStm, bFileHeader, bMSOFormat);
1545 : }
1546 :
1547 5035 : bool ReadDIBBitmapEx(
1548 : BitmapEx& rTarget,
1549 : SvStream& rIStm)
1550 : {
1551 5035 : Bitmap aBmp;
1552 5035 : bool bRetval(ImplReadDIB(aBmp, 0, rIStm, true) && !rIStm.GetError());
1553 :
1554 5035 : if(bRetval)
1555 : {
1556 : // base bitmap was read, set as return value and try to read alpha extra-data
1557 69 : const sal_uLong nStmPos(rIStm.Tell());
1558 69 : sal_uInt32 nMagic1(0);
1559 69 : sal_uInt32 nMagic2(0);
1560 :
1561 69 : rTarget = BitmapEx(aBmp);
1562 69 : rIStm.ReadUInt32( nMagic1 ).ReadUInt32( nMagic2 );
1563 69 : bRetval = (0x25091962 == nMagic1) && (0xACB20201 == nMagic2) && !rIStm.GetError();
1564 :
1565 69 : if(bRetval)
1566 : {
1567 59 : sal_uInt8 transparent = TRANSPARENT_NONE;
1568 :
1569 59 : rIStm.ReadUChar( transparent );
1570 59 : bRetval = !rIStm.GetError();
1571 :
1572 59 : if(bRetval)
1573 : {
1574 59 : switch (transparent)
1575 : {
1576 : case TRANSPARENT_BITMAP:
1577 : {
1578 17 : Bitmap aMask;
1579 :
1580 17 : bRetval = ImplReadDIB(aMask, 0, rIStm, true);
1581 :
1582 17 : if(bRetval)
1583 : {
1584 17 : if(!!aMask)
1585 : {
1586 : // do we have an alpha mask?
1587 17 : if((8 == aMask.GetBitCount()) && aMask.HasGreyPalette())
1588 : {
1589 17 : AlphaMask aAlpha;
1590 :
1591 : // create alpha mask quickly (without greyscale conversion)
1592 17 : aAlpha.ImplSetBitmap(aMask);
1593 17 : rTarget = BitmapEx(aBmp, aAlpha);
1594 : }
1595 : else
1596 : {
1597 0 : rTarget = BitmapEx(aBmp, aMask);
1598 : }
1599 : }
1600 : }
1601 17 : break;
1602 : }
1603 : case TRANSPARENT_COLOR:
1604 : {
1605 0 : Color aTransparentColor;
1606 :
1607 0 : ReadColor( rIStm, aTransparentColor );
1608 0 : bRetval = !rIStm.GetError();
1609 :
1610 0 : if(bRetval)
1611 : {
1612 0 : rTarget = BitmapEx(aBmp, aTransparentColor);
1613 : }
1614 0 : break;
1615 : }
1616 : }
1617 : }
1618 : }
1619 :
1620 69 : if(!bRetval)
1621 : {
1622 : // alpha extra data could not be read; reset, but use base bitmap as result
1623 10 : rIStm.ResetError();
1624 10 : rIStm.Seek(nStmPos);
1625 10 : bRetval = true;
1626 : }
1627 : }
1628 :
1629 5035 : return bRetval;
1630 : }
1631 :
1632 0 : bool ReadDIBV5(
1633 : Bitmap& rTarget,
1634 : Bitmap& rTargetAlpha,
1635 : SvStream& rIStm)
1636 : {
1637 0 : return ImplReadDIB(rTarget, &rTargetAlpha, rIStm, true);
1638 : }
1639 :
1640 419 : bool WriteDIB(
1641 : const Bitmap& rSource,
1642 : SvStream& rOStm,
1643 : bool bCompressed,
1644 : bool bFileHeader)
1645 : {
1646 419 : return ImplWriteDIB(rSource, 0, rOStm, bCompressed, bFileHeader);
1647 : }
1648 :
1649 631 : bool WriteDIBBitmapEx(
1650 : const BitmapEx& rSource,
1651 : SvStream& rOStm)
1652 : {
1653 631 : if(ImplWriteDIB(rSource.GetBitmap(), 0, rOStm, true, true))
1654 : {
1655 631 : rOStm.WriteUInt32( 0x25091962 );
1656 631 : rOStm.WriteUInt32( 0xACB20201 );
1657 631 : rOStm.WriteUChar( rSource.eTransparent );
1658 :
1659 631 : if(TRANSPARENT_BITMAP == rSource.eTransparent)
1660 : {
1661 521 : return ImplWriteDIB(rSource.aMask, 0, rOStm, true, true);
1662 : }
1663 110 : else if(TRANSPARENT_COLOR == rSource.eTransparent)
1664 : {
1665 0 : WriteColor( rOStm, rSource.aTransparentColor );
1666 0 : return true;
1667 : }
1668 : }
1669 :
1670 110 : return false;
1671 : }
1672 :
1673 0 : bool WriteDIBV5(
1674 : const Bitmap& rSource,
1675 : const Bitmap& rSourceAlpha,
1676 : SvStream& rOStm)
1677 : {
1678 0 : return ImplWriteDIB(rSource, &rSourceAlpha, rOStm, false, true);
1679 : }
1680 :
1681 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|