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 :
21 : #include <ctype.h>
22 :
23 : #include <rtl/crc.h>
24 : #include <rtl/strbuf.hxx>
25 :
26 : #include <tools/stream.hxx>
27 : #include <tools/debug.hxx>
28 : #include <tools/rc.h>
29 :
30 : #include <vcl/salbtype.hxx>
31 : #include <vcl/outdev.hxx>
32 : #include <vcl/alpha.hxx>
33 : #include <vcl/bitmapex.hxx>
34 : #include <vcl/pngread.hxx>
35 : #include <vcl/svapp.hxx>
36 : #include <vcl/bmpacc.hxx>
37 : #include <vcl/virdev.hxx>
38 :
39 : #include <image.h>
40 : #include <impimagetree.hxx>
41 :
42 15830 : BitmapEx::BitmapEx() :
43 : eTransparent( TRANSPARENT_NONE ),
44 15830 : bAlpha ( sal_False )
45 : {
46 15830 : }
47 :
48 4201 : BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) :
49 : aBitmap ( rBitmapEx.aBitmap ),
50 : aMask ( rBitmapEx.aMask ),
51 : aBitmapSize ( rBitmapEx.aBitmapSize ),
52 : aTransparentColor ( rBitmapEx.aTransparentColor ),
53 : eTransparent ( rBitmapEx.eTransparent ),
54 4201 : bAlpha ( rBitmapEx.bAlpha )
55 : {
56 4201 : }
57 :
58 0 : BitmapEx::BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize ) :
59 : eTransparent( TRANSPARENT_NONE ),
60 0 : bAlpha ( sal_False )
61 : {
62 0 : if( rBitmapEx.IsEmpty() )
63 0 : return;
64 :
65 0 : aBitmap = Bitmap( aSize, rBitmapEx.aBitmap.GetBitCount() );
66 0 : aBitmapSize = aSize;
67 0 : if( rBitmapEx.IsAlpha() )
68 : {
69 0 : bAlpha = sal_True;
70 0 : aMask = AlphaMask( aSize ).ImplGetBitmap();
71 : }
72 0 : else if( rBitmapEx.IsTransparent() )
73 0 : aMask = Bitmap( aSize, rBitmapEx.aMask.GetBitCount() );
74 :
75 0 : Rectangle aDestRect( Point( 0, 0 ), aSize );
76 0 : Rectangle aSrcRect( aSrc, aSize );
77 0 : CopyPixel( aDestRect, aSrcRect, &rBitmapEx );
78 : }
79 :
80 743 : BitmapEx::BitmapEx( const ResId& rResId ) :
81 : eTransparent( TRANSPARENT_NONE ),
82 743 : bAlpha ( sal_False )
83 : {
84 743 : static ImplImageTreeSingletonRef aImageTree;
85 743 : ResMgr* pResMgr = NULL;
86 :
87 743 : ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
88 743 : pResMgr->ReadLong();
89 743 : pResMgr->ReadLong();
90 :
91 743 : const String aFileName( pResMgr->ReadString() );
92 743 : ::rtl::OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName();
93 :
94 743 : if( !aImageTree->loadImage( aFileName, aCurrentSymbolsStyle, *this, true ) )
95 : {
96 : #ifdef DBG_UTIL
97 : rtl::OStringBuffer aErrorStr(RTL_CONSTASCII_STRINGPARAM(
98 : "BitmapEx::BitmapEx( const ResId& rResId ): could not load image <"));
99 : aErrorStr.append(rtl::OUStringToOString(aFileName, RTL_TEXTENCODING_ASCII_US)).append('>');
100 : OSL_FAIL(aErrorStr.getStr());
101 : #endif
102 743 : }
103 743 : }
104 :
105 794 : BitmapEx::BitmapEx( const Bitmap& rBmp ) :
106 : aBitmap ( rBmp ),
107 794 : aBitmapSize ( aBitmap.GetSizePixel() ),
108 : eTransparent( TRANSPARENT_NONE ),
109 1588 : bAlpha ( sal_False )
110 : {
111 794 : }
112 :
113 66 : BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
114 : aBitmap ( rBmp ),
115 : aMask ( rMask ),
116 66 : aBitmapSize ( aBitmap.GetSizePixel() ),
117 66 : eTransparent ( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
118 198 : bAlpha ( sal_False )
119 : {
120 : DBG_ASSERT( !rMask || rBmp.GetSizePixel() == rMask.GetSizePixel(),
121 : "BitmapEx::BitmapEx(): size mismatch for bitmap and mask." );
122 :
123 : // #105489# Ensure a mask is exactly one bit deep
124 66 : if( !!aMask && aMask.GetBitCount() != 1 )
125 : {
126 : OSL_TRACE("BitmapEx: forced mask to monochrome");
127 0 : aMask.ImplMakeMono( 255 );
128 : }
129 66 : }
130 :
131 60 : BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
132 : aBitmap ( rBmp ),
133 60 : aMask ( rAlphaMask.ImplGetBitmap() ),
134 60 : aBitmapSize ( aBitmap.GetSizePixel() ),
135 60 : eTransparent ( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
136 240 : bAlpha ( !rAlphaMask ? sal_False : sal_True )
137 : {
138 : DBG_ASSERT( !rAlphaMask || rBmp.GetSizePixel() == rAlphaMask.GetSizePixel(),
139 : "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
140 :
141 : // #i75531# the workaround below can go when
142 : // X11SalGraphics::drawAlphaBitmap()'s render acceleration
143 : // can handle the bitmap depth mismatch directly
144 60 : if( aBitmap.GetBitCount() < aMask.GetBitCount() )
145 0 : aBitmap.Convert( BMP_CONVERSION_24BIT );
146 60 : }
147 :
148 0 : BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
149 : aBitmap ( rBmp ),
150 0 : aBitmapSize ( aBitmap.GetSizePixel() ),
151 : aTransparentColor ( rTransparentColor ),
152 : eTransparent ( TRANSPARENT_BITMAP ),
153 0 : bAlpha ( sal_False )
154 : {
155 0 : aMask = aBitmap.CreateMask( aTransparentColor );
156 :
157 : DBG_ASSERT( rBmp.GetSizePixel() == aMask.GetSizePixel(),
158 : "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
159 0 : }
160 :
161 21210 : BitmapEx::~BitmapEx()
162 : {
163 21210 : }
164 :
165 3027 : BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
166 : {
167 3027 : if( &rBitmapEx != this )
168 : {
169 3027 : aBitmap = rBitmapEx.aBitmap;
170 3027 : aMask = rBitmapEx.aMask;
171 3027 : aBitmapSize = rBitmapEx.aBitmapSize;
172 3027 : aTransparentColor = rBitmapEx.aTransparentColor;
173 3027 : eTransparent = rBitmapEx.eTransparent;
174 3027 : bAlpha = rBitmapEx.bAlpha;
175 : }
176 :
177 3027 : return *this;
178 : }
179 :
180 19 : sal_Bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
181 : {
182 19 : if( eTransparent != rBitmapEx.eTransparent )
183 0 : return sal_False;
184 :
185 19 : if( aBitmap != rBitmapEx.aBitmap )
186 0 : return sal_False;
187 :
188 19 : if( aBitmapSize != rBitmapEx.aBitmapSize )
189 0 : return sal_False;
190 :
191 19 : if( eTransparent == TRANSPARENT_NONE )
192 15 : return sal_True;
193 :
194 4 : if( eTransparent == TRANSPARENT_COLOR )
195 0 : return aTransparentColor == rBitmapEx.aTransparentColor;
196 :
197 4 : return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
198 : }
199 :
200 0 : sal_Bool BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
201 : {
202 : return( rBmpEx.eTransparent == eTransparent &&
203 : rBmpEx.bAlpha == bAlpha &&
204 0 : rBmpEx.aBitmap.IsEqual( aBitmap ) &&
205 0 : rBmpEx.aMask.IsEqual( aMask ) );
206 : }
207 :
208 4460 : sal_Bool BitmapEx::IsEmpty() const
209 : {
210 4460 : return( aBitmap.IsEmpty() && aMask.IsEmpty() );
211 : }
212 :
213 15758 : void BitmapEx::SetEmpty()
214 : {
215 15758 : aBitmap.SetEmpty();
216 15758 : aMask.SetEmpty();
217 15758 : eTransparent = TRANSPARENT_NONE;
218 15758 : bAlpha = sal_False;
219 15758 : }
220 :
221 15744 : void BitmapEx::Clear()
222 : {
223 15744 : SetEmpty();
224 15744 : }
225 :
226 858 : sal_Bool BitmapEx::IsTransparent() const
227 : {
228 858 : return( eTransparent != TRANSPARENT_NONE );
229 : }
230 :
231 472 : sal_Bool BitmapEx::IsAlpha() const
232 : {
233 472 : return( IsTransparent() && bAlpha );
234 : }
235 :
236 2332 : Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
237 : {
238 2332 : Bitmap aRetBmp( aBitmap );
239 :
240 2332 : if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
241 : {
242 0 : Bitmap aTempMask;
243 :
244 0 : if( eTransparent == TRANSPARENT_COLOR )
245 0 : aTempMask = aBitmap.CreateMask( aTransparentColor );
246 : else
247 0 : aTempMask = aMask;
248 :
249 0 : if( !IsAlpha() )
250 0 : aRetBmp.Replace( aTempMask, *pTransReplaceColor );
251 : else
252 0 : aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
253 : }
254 :
255 2332 : return aRetBmp;
256 : }
257 :
258 7 : Bitmap BitmapEx::GetMask() const
259 : {
260 7 : Bitmap aRet( aMask );
261 :
262 7 : if( IsAlpha() )
263 0 : aRet.ImplMakeMono( 255 );
264 :
265 7 : return aRet;
266 : }
267 :
268 2 : AlphaMask BitmapEx::GetAlpha() const
269 : {
270 2 : if( IsAlpha() )
271 : {
272 2 : AlphaMask aAlpha;
273 2 : aAlpha.ImplSetBitmap( aMask );
274 2 : return aAlpha;
275 : }
276 : else
277 : {
278 0 : return aMask;
279 : }
280 : }
281 :
282 135 : sal_uLong BitmapEx::GetSizeBytes() const
283 : {
284 135 : sal_uLong nSizeBytes = aBitmap.GetSizeBytes();
285 :
286 135 : if( eTransparent == TRANSPARENT_BITMAP )
287 21 : nSizeBytes += aMask.GetSizeBytes();
288 :
289 135 : return nSizeBytes;
290 : }
291 :
292 100 : sal_uLong BitmapEx::GetChecksum() const
293 : {
294 100 : sal_uInt32 nCrc = aBitmap.GetChecksum();
295 : SVBT32 aBT32;
296 :
297 100 : UInt32ToSVBT32( (long) eTransparent, aBT32 );
298 100 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
299 :
300 100 : UInt32ToSVBT32( (long) bAlpha, aBT32 );
301 100 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
302 :
303 100 : if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
304 : {
305 21 : UInt32ToSVBT32( aMask.GetChecksum(), aBT32 );
306 21 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
307 : }
308 :
309 100 : return nCrc;
310 : }
311 :
312 11 : void BitmapEx::SetSizePixel( const Size& rNewSize )
313 : {
314 11 : Scale( rNewSize );
315 11 : }
316 :
317 0 : sal_Bool BitmapEx::Invert()
318 : {
319 0 : sal_Bool bRet = sal_False;
320 :
321 0 : if( !!aBitmap )
322 : {
323 0 : bRet = aBitmap.Invert();
324 :
325 0 : if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
326 0 : aTransparentColor = BitmapColor( aTransparentColor ).Invert();
327 : }
328 :
329 0 : return bRet;
330 : }
331 :
332 1 : sal_Bool BitmapEx::Mirror( sal_uLong nMirrorFlags )
333 : {
334 1 : sal_Bool bRet = sal_False;
335 :
336 1 : if( !!aBitmap )
337 : {
338 1 : bRet = aBitmap.Mirror( nMirrorFlags );
339 :
340 1 : if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
341 0 : aMask.Mirror( nMirrorFlags );
342 : }
343 :
344 1 : return bRet;
345 : }
346 :
347 1072 : sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
348 : {
349 1072 : sal_Bool bRet = sal_False;
350 :
351 1072 : if( !!aBitmap )
352 : {
353 0 : bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
354 :
355 0 : if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
356 0 : aMask.Scale( rScaleX, rScaleY, BMP_SCALE_FAST );
357 :
358 0 : aBitmapSize = aBitmap.GetSizePixel();
359 :
360 : DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
361 : "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
362 : }
363 :
364 1072 : return bRet;
365 : }
366 :
367 11 : sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
368 : {
369 : sal_Bool bRet;
370 :
371 11 : if( aBitmapSize.Width() && aBitmapSize.Height() )
372 : {
373 0 : bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
374 0 : (double) rNewSize.Height() / aBitmapSize.Height(),
375 0 : nScaleFlag );
376 : }
377 : else
378 11 : bRet = sal_True;
379 :
380 11 : return bRet;
381 : }
382 :
383 0 : sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
384 : {
385 0 : sal_Bool bRet = sal_False;
386 :
387 0 : if( !!aBitmap )
388 : {
389 0 : const sal_Bool bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
390 :
391 0 : if( bTransRotate )
392 : {
393 0 : if( eTransparent == TRANSPARENT_COLOR )
394 0 : bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
395 : else
396 : {
397 0 : bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
398 :
399 0 : if( eTransparent == TRANSPARENT_NONE )
400 : {
401 0 : aMask = Bitmap( aBitmapSize, 1 );
402 0 : aMask.Erase( COL_BLACK );
403 0 : eTransparent = TRANSPARENT_BITMAP;
404 : }
405 :
406 0 : if( bRet && !!aMask )
407 0 : aMask.Rotate( nAngle10, COL_WHITE );
408 : }
409 : }
410 : else
411 : {
412 0 : bRet = aBitmap.Rotate( nAngle10, rFillColor );
413 :
414 0 : if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
415 0 : aMask.Rotate( nAngle10, COL_WHITE );
416 : }
417 :
418 0 : aBitmapSize = aBitmap.GetSizePixel();
419 :
420 : DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
421 : "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask." );
422 : }
423 :
424 0 : return bRet;
425 : }
426 :
427 56 : sal_Bool BitmapEx::Crop( const Rectangle& rRectPixel )
428 : {
429 56 : sal_Bool bRet = sal_False;
430 :
431 56 : if( !!aBitmap )
432 : {
433 0 : bRet = aBitmap.Crop( rRectPixel );
434 :
435 0 : if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
436 0 : aMask.Crop( rRectPixel );
437 :
438 0 : aBitmapSize = aBitmap.GetSizePixel();
439 :
440 : DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
441 : "BitmapEx::Crop(): size mismatch for bitmap and alpha mask." );
442 : }
443 :
444 56 : return bRet;
445 : }
446 :
447 0 : sal_Bool BitmapEx::Convert( BmpConversion eConversion )
448 : {
449 0 : return( !!aBitmap ? aBitmap.Convert( eConversion ) : sal_False );
450 : }
451 :
452 0 : sal_Bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
453 : {
454 0 : return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : sal_False );
455 : }
456 :
457 0 : sal_Bool BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor, sal_Bool bExpandTransparent )
458 : {
459 0 : sal_Bool bRet = sal_False;
460 :
461 0 : if( !!aBitmap )
462 : {
463 0 : bRet = aBitmap.Expand( nDX, nDY, pInitColor );
464 :
465 0 : if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
466 : {
467 0 : Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
468 0 : aMask.Expand( nDX, nDY, &aColor );
469 : }
470 :
471 0 : aBitmapSize = aBitmap.GetSizePixel();
472 :
473 : DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
474 : "BitmapEx::Expand(): size mismatch for bitmap and alpha mask." );
475 : }
476 :
477 0 : return bRet;
478 : }
479 :
480 11 : sal_Bool BitmapEx::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
481 : const BitmapEx* pBmpExSrc )
482 : {
483 11 : sal_Bool bRet = sal_False;
484 :
485 11 : if( !pBmpExSrc || pBmpExSrc->IsEmpty() )
486 : {
487 11 : if( !aBitmap.IsEmpty() )
488 : {
489 0 : bRet = aBitmap.CopyPixel( rRectDst, rRectSrc );
490 :
491 0 : if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
492 0 : aMask.CopyPixel( rRectDst, rRectSrc );
493 : }
494 : }
495 : else
496 : {
497 0 : if( !aBitmap.IsEmpty() )
498 : {
499 0 : bRet = aBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aBitmap );
500 :
501 0 : if( bRet )
502 : {
503 0 : if( pBmpExSrc->IsAlpha() )
504 : {
505 0 : if( IsAlpha() )
506 : // cast to use the optimized AlphaMask::CopyPixel
507 0 : ((AlphaMask*) &aMask)->CopyPixel( rRectDst, rRectSrc, (AlphaMask*)&pBmpExSrc->aMask );
508 0 : else if( IsTransparent() )
509 : {
510 0 : AlphaMask* pAlpha = new AlphaMask( aMask );
511 :
512 0 : aMask = pAlpha->ImplGetBitmap();
513 0 : delete pAlpha;
514 0 : bAlpha = sal_True;
515 0 : aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
516 : }
517 : else
518 : {
519 0 : sal_uInt8 cBlack = 0;
520 0 : AlphaMask* pAlpha = new AlphaMask( GetSizePixel(), &cBlack );
521 :
522 0 : aMask = pAlpha->ImplGetBitmap();
523 0 : delete pAlpha;
524 0 : eTransparent = TRANSPARENT_BITMAP;
525 0 : bAlpha = sal_True;
526 0 : aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
527 : }
528 : }
529 0 : else if( pBmpExSrc->IsTransparent() )
530 : {
531 0 : if( IsAlpha() )
532 : {
533 0 : AlphaMask aAlpha( pBmpExSrc->aMask );
534 0 : aMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() );
535 : }
536 0 : else if( IsTransparent() )
537 0 : aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
538 : else
539 : {
540 0 : aMask = Bitmap( GetSizePixel(), 1 );
541 0 : aMask.Erase( Color( COL_BLACK ) );
542 0 : eTransparent = TRANSPARENT_BITMAP;
543 0 : aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
544 : }
545 : }
546 0 : else if( IsAlpha() )
547 : {
548 0 : sal_uInt8 cBlack = 0;
549 0 : const AlphaMask aAlphaSrc( pBmpExSrc->GetSizePixel(), &cBlack );
550 :
551 0 : aMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() );
552 : }
553 0 : else if( IsTransparent() )
554 : {
555 0 : Bitmap aMaskSrc( pBmpExSrc->GetSizePixel(), 1 );
556 :
557 0 : aMaskSrc.Erase( Color( COL_BLACK ) );
558 0 : aMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc );
559 : }
560 : }
561 : }
562 : }
563 :
564 11 : return bRet;
565 : }
566 :
567 11 : sal_Bool BitmapEx::Erase( const Color& rFillColor )
568 : {
569 11 : sal_Bool bRet = sal_False;
570 :
571 11 : if( !!aBitmap )
572 : {
573 0 : bRet = aBitmap.Erase( rFillColor );
574 :
575 0 : if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
576 : {
577 : // #104416# Respect transparency on fill color
578 0 : if( rFillColor.GetTransparency() )
579 : {
580 0 : const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() );
581 0 : aMask.Erase( aFill );
582 : }
583 : else
584 : {
585 0 : const Color aBlack( COL_BLACK );
586 0 : aMask.Erase( aBlack );
587 : }
588 : }
589 : }
590 :
591 11 : return bRet;
592 : }
593 :
594 0 : sal_Bool BitmapEx::Dither( sal_uLong nDitherFlags )
595 : {
596 0 : return( !!aBitmap ? aBitmap.Dither( nDitherFlags ) : sal_False );
597 : }
598 :
599 0 : sal_Bool BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
600 : {
601 0 : return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : sal_False );
602 : }
603 :
604 0 : sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, const sal_uLong* pTols )
605 : {
606 0 : return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (sal_uLong*) pTols ) : sal_False );
607 : }
608 :
609 0 : sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
610 : short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
611 : double fGamma, sal_Bool bInvert )
612 : {
613 0 : return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
614 : nChannelRPercent, nChannelGPercent, nChannelBPercent,
615 0 : fGamma, bInvert ) : sal_False );
616 : }
617 :
618 0 : sal_Bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
619 : {
620 0 : return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : sal_False );
621 : }
622 :
623 0 : void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
624 : {
625 0 : pOutDev->DrawBitmapEx( rDestPt, *this );
626 0 : }
627 :
628 8 : void BitmapEx::Draw( OutputDevice* pOutDev,
629 : const Point& rDestPt, const Size& rDestSize ) const
630 : {
631 8 : pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
632 8 : }
633 :
634 0 : BitmapEx BitmapEx:: AutoScaleBitmap(BitmapEx & aBitmap, const long aStandardSize)
635 : {
636 0 : Point aEmptyPoint(0,0);
637 0 : double imgposX = 0;
638 0 : double imgposY = 0;
639 0 : BitmapEx aRet = aBitmap;
640 0 : double imgOldWidth = aRet.GetSizePixel().Width();
641 0 : double imgOldHeight =aRet.GetSizePixel().Height();
642 :
643 0 : Size aScaledSize;
644 0 : if (imgOldWidth >= aStandardSize || imgOldHeight >= aStandardSize)
645 : {
646 0 : sal_Int32 imgNewWidth = 0;
647 0 : sal_Int32 imgNewHeight = 0;
648 0 : if (imgOldWidth >= imgOldHeight)
649 : {
650 0 : imgNewWidth = aStandardSize;
651 0 : imgNewHeight = sal_Int32(imgOldHeight / (imgOldWidth / aStandardSize) + 0.5);
652 0 : imgposX = 0;
653 0 : imgposY = (aStandardSize - (imgOldHeight / (imgOldWidth / aStandardSize) + 0.5)) / 2 + 0.5;
654 : }
655 : else
656 : {
657 0 : imgNewHeight = aStandardSize;
658 0 : imgNewWidth = sal_Int32(imgOldWidth / (imgOldHeight / aStandardSize) + 0.5);
659 0 : imgposY = 0;
660 0 : imgposX = (aStandardSize - (imgOldWidth / (imgOldHeight / aStandardSize) + 0.5)) / 2 + 0.5;
661 : }
662 :
663 0 : aScaledSize = Size( imgNewWidth, imgNewHeight );
664 0 : aRet.Scale( aScaledSize, BMP_SCALE_BEST );
665 : }
666 : else
667 : {
668 0 : imgposX = (aStandardSize - imgOldWidth) / 2 + 0.5;
669 0 : imgposY = (aStandardSize - imgOldHeight) / 2 + 0.5;
670 : }
671 :
672 0 : Size aStdSize( aStandardSize, aStandardSize );
673 0 : Rectangle aRect(aEmptyPoint, aStdSize );
674 :
675 0 : VirtualDevice aVirDevice( *Application::GetDefaultDevice(), 0, 1 );
676 0 : aVirDevice.SetOutputSizePixel( aStdSize );
677 0 : aVirDevice.SetFillColor( COL_TRANSPARENT );
678 0 : aVirDevice.SetLineColor( COL_TRANSPARENT );
679 :
680 : //draw a rect into virDevice
681 0 : aVirDevice.DrawRect( aRect );
682 0 : Point aPointPixel( (long)imgposX, (long)imgposY );
683 0 : aVirDevice.DrawBitmapEx( aPointPixel, aRet );
684 0 : aRet = aVirDevice.GetBitmapEx( aEmptyPoint, aStdSize );
685 :
686 0 : return aRet;
687 : }
688 :
689 0 : sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
690 : {
691 0 : sal_uInt8 nTransparency(0xff);
692 :
693 0 : if(!aBitmap.IsEmpty())
694 : {
695 0 : if(nX >= 0 && nX < aBitmapSize.Width() && nY >= 0 && nY < aBitmapSize.Height())
696 : {
697 0 : switch(eTransparent)
698 : {
699 : case TRANSPARENT_NONE:
700 : {
701 : // not transparent, ergo all covered
702 0 : nTransparency = 0x00;
703 0 : break;
704 : }
705 : case TRANSPARENT_COLOR:
706 : {
707 0 : Bitmap aTestBitmap(aBitmap);
708 0 : BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
709 :
710 0 : if(pRead)
711 : {
712 0 : const Color aColor = pRead->GetColor(nY, nX);
713 :
714 : // if color is not equal to TransparentColor, we are not transparent
715 0 : if(aColor != aTransparentColor)
716 : {
717 0 : nTransparency = 0x00;
718 : }
719 :
720 0 : aTestBitmap.ReleaseAccess(pRead);
721 : }
722 0 : break;
723 : }
724 : case TRANSPARENT_BITMAP:
725 : {
726 0 : if(!aMask.IsEmpty())
727 : {
728 0 : Bitmap aTestBitmap(aMask);
729 0 : BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
730 :
731 0 : if(pRead)
732 : {
733 0 : const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
734 :
735 0 : if(bAlpha)
736 : {
737 0 : nTransparency = aBitmapColor.GetIndex();
738 : }
739 : else
740 : {
741 0 : if(0x00 == aBitmapColor.GetIndex())
742 : {
743 0 : nTransparency = 0x00;
744 : }
745 : }
746 :
747 0 : aTestBitmap.ReleaseAccess(pRead);
748 0 : }
749 : }
750 0 : break;
751 : }
752 : }
753 : }
754 : }
755 :
756 0 : return nTransparency;
757 : }
758 :
759 0 : SvStream& operator<<( SvStream& rOStm, const BitmapEx& rBitmapEx )
760 : {
761 0 : rBitmapEx.aBitmap.Write( rOStm );
762 :
763 0 : rOStm << (sal_uInt32) 0x25091962;
764 0 : rOStm << (sal_uInt32) 0xACB20201;
765 0 : rOStm << (sal_uInt8) rBitmapEx.eTransparent;
766 :
767 0 : if( rBitmapEx.eTransparent == TRANSPARENT_BITMAP )
768 0 : rBitmapEx.aMask.Write( rOStm );
769 0 : else if( rBitmapEx.eTransparent == TRANSPARENT_COLOR )
770 0 : rOStm << rBitmapEx.aTransparentColor;
771 :
772 0 : return rOStm;
773 : }
774 :
775 2294 : SvStream& operator>>( SvStream& rIStm, BitmapEx& rBitmapEx )
776 : {
777 2294 : Bitmap aBmp;
778 :
779 2294 : rIStm >> aBmp;
780 :
781 2294 : if( !rIStm.GetError() )
782 : {
783 4 : const sal_uLong nStmPos = rIStm.Tell();
784 4 : sal_uInt32 nMagic1 = 0;
785 4 : sal_uInt32 nMagic2 = 0;
786 :
787 4 : rIStm >> nMagic1 >> nMagic2;
788 :
789 4 : if( ( nMagic1 != 0x25091962 ) || ( nMagic2 != 0xACB20201 ) || rIStm.GetError() )
790 : {
791 4 : rIStm.ResetError();
792 4 : rIStm.Seek( nStmPos );
793 4 : rBitmapEx = aBmp;
794 : }
795 : else
796 : {
797 0 : sal_uInt8 bTransparent = false;
798 :
799 0 : rIStm >> bTransparent;
800 :
801 0 : if( bTransparent == (sal_uInt8) TRANSPARENT_BITMAP )
802 : {
803 0 : Bitmap aMask;
804 :
805 0 : rIStm >> aMask;
806 :
807 0 : if( !!aMask)
808 : {
809 : // do we have an alpha mask?
810 0 : if( ( 8 == aMask.GetBitCount() ) && aMask.HasGreyPalette() )
811 : {
812 0 : AlphaMask aAlpha;
813 :
814 : // create alpha mask quickly (without greyscale conversion)
815 0 : aAlpha.ImplSetBitmap( aMask );
816 0 : rBitmapEx = BitmapEx( aBmp, aAlpha );
817 : }
818 : else
819 0 : rBitmapEx = BitmapEx( aBmp, aMask );
820 : }
821 : else
822 0 : rBitmapEx = aBmp;
823 : }
824 0 : else if( bTransparent == (sal_uInt8) TRANSPARENT_COLOR )
825 : {
826 0 : Color aTransparentColor;
827 :
828 0 : rIStm >> aTransparentColor;
829 0 : rBitmapEx = BitmapEx( aBmp, aTransparentColor );
830 : }
831 : else
832 0 : rBitmapEx = aBmp;
833 : }
834 : }
835 :
836 2294 : return rIStm;
837 : }
838 :
839 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|