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 <rtl/crc.h>
22 : #include <tools/stream.hxx>
23 : #include <tools/poly.hxx>
24 : #include <tools/rc.h>
25 : #include <vcl/salbtype.hxx>
26 : #include <vcl/bmpacc.hxx>
27 : #include <vcl/outdev.hxx>
28 : #include <vcl/bitmap.hxx>
29 : #include <vcl/bitmapex.hxx>
30 : #include <vcl/svapp.hxx>
31 : #include <vcl/image.hxx>
32 :
33 : #include <impbmp.hxx>
34 : #include <salbmp.hxx>
35 :
36 : // ----------
37 : // - Bitmap -
38 : // ----------
39 :
40 37820 : Bitmap::Bitmap() :
41 37820 : mpImpBmp( NULL )
42 : {
43 37820 : }
44 :
45 : // ------------------------------------------------------------------
46 :
47 261 : Bitmap::Bitmap( const ResId& rResId ) :
48 261 : mpImpBmp( NULL )
49 : {
50 261 : const BitmapEx aBmpEx( rResId );
51 :
52 261 : if( !aBmpEx.IsEmpty() )
53 0 : *this = aBmpEx.GetBitmap();
54 261 : }
55 :
56 : // ------------------------------------------------------------------
57 :
58 14135 : Bitmap::Bitmap( const Bitmap& rBitmap ) :
59 : maPrefMapMode ( rBitmap.maPrefMapMode ),
60 14135 : maPrefSize ( rBitmap.maPrefSize )
61 : {
62 14135 : mpImpBmp = rBitmap.mpImpBmp;
63 :
64 14135 : if ( mpImpBmp )
65 1399 : mpImpBmp->ImplIncRefCount();
66 14135 : }
67 :
68 : // ------------------------------------------------------------------
69 :
70 0 : Bitmap::Bitmap( SalBitmap* pSalBitmap )
71 : {
72 0 : mpImpBmp = new ImpBitmap();
73 0 : mpImpBmp->ImplSetSalBitmap( pSalBitmap );
74 0 : maPrefMapMode = MapMode( MAP_PIXEL );
75 0 : maPrefSize = mpImpBmp->ImplGetSize();
76 0 : }
77 :
78 : // ------------------------------------------------------------------
79 :
80 249 : Bitmap::Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal )
81 : {
82 249 : if( rSizePixel.Width() && rSizePixel.Height() )
83 : {
84 193 : BitmapPalette aPal;
85 193 : BitmapPalette* pRealPal = NULL;
86 :
87 193 : if( nBitCount <= 8 )
88 : {
89 156 : if( !pPal )
90 : {
91 91 : if( 1 == nBitCount )
92 : {
93 64 : aPal.SetEntryCount( 2 );
94 64 : aPal[ 0 ] = Color( COL_BLACK );
95 64 : aPal[ 1 ] = Color( COL_WHITE );
96 : }
97 27 : else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
98 : {
99 27 : aPal.SetEntryCount( 1 << nBitCount );
100 27 : aPal[ 0 ] = Color( COL_BLACK );
101 27 : aPal[ 1 ] = Color( COL_BLUE );
102 27 : aPal[ 2 ] = Color( COL_GREEN );
103 27 : aPal[ 3 ] = Color( COL_CYAN );
104 27 : aPal[ 4 ] = Color( COL_RED );
105 27 : aPal[ 5 ] = Color( COL_MAGENTA );
106 27 : aPal[ 6 ] = Color( COL_BROWN );
107 27 : aPal[ 7 ] = Color( COL_GRAY );
108 27 : aPal[ 8 ] = Color( COL_LIGHTGRAY );
109 27 : aPal[ 9 ] = Color( COL_LIGHTBLUE );
110 27 : aPal[ 10 ] = Color( COL_LIGHTGREEN );
111 27 : aPal[ 11 ] = Color( COL_LIGHTCYAN );
112 27 : aPal[ 12 ] = Color( COL_LIGHTRED );
113 27 : aPal[ 13 ] = Color( COL_LIGHTMAGENTA );
114 27 : aPal[ 14 ] = Color( COL_YELLOW );
115 27 : aPal[ 15 ] = Color( COL_WHITE );
116 :
117 : // Dither-Palette erzeugen
118 27 : if( 8 == nBitCount )
119 : {
120 26 : sal_uInt16 nActCol = 16;
121 :
122 182 : for( sal_uInt16 nB = 0; nB < 256; nB += 51 )
123 1092 : for( sal_uInt16 nG = 0; nG < 256; nG += 51 )
124 6552 : for( sal_uInt16 nR = 0; nR < 256; nR += 51 )
125 5616 : aPal[ nActCol++ ] = BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB );
126 :
127 : // Standard-Office-Farbe setzen
128 26 : aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
129 : }
130 : }
131 : }
132 : else
133 65 : pRealPal = (BitmapPalette*) pPal;
134 : }
135 :
136 193 : mpImpBmp = new ImpBitmap;
137 193 : mpImpBmp->ImplCreate( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
138 : }
139 : else
140 56 : mpImpBmp = NULL;
141 249 : }
142 :
143 : // ------------------------------------------------------------------
144 :
145 102972 : Bitmap::~Bitmap()
146 : {
147 51486 : ImplReleaseRef();
148 51486 : }
149 :
150 : // ------------------------------------------------------------------
151 :
152 10 : const BitmapPalette& Bitmap::GetGreyPalette( int nEntries )
153 : {
154 10 : static BitmapPalette aGreyPalette2;
155 10 : static BitmapPalette aGreyPalette4;
156 10 : static BitmapPalette aGreyPalette16;
157 10 : static BitmapPalette aGreyPalette256;
158 :
159 : // create greyscale palette with 2, 4, 16 or 256 entries
160 10 : if( 2 == nEntries || 4 == nEntries || 16 == nEntries || 256 == nEntries )
161 : {
162 10 : if( 2 == nEntries )
163 : {
164 0 : if( !aGreyPalette2.GetEntryCount() )
165 : {
166 0 : aGreyPalette2.SetEntryCount( 2 );
167 0 : aGreyPalette2[ 0 ] = BitmapColor( 0, 0, 0 );
168 0 : aGreyPalette2[ 1 ] = BitmapColor( 255, 255, 255 );
169 : }
170 :
171 0 : return aGreyPalette2;
172 : }
173 10 : else if( 4 == nEntries )
174 : {
175 0 : if( !aGreyPalette4.GetEntryCount() )
176 : {
177 0 : aGreyPalette4.SetEntryCount( 4 );
178 0 : aGreyPalette4[ 0 ] = BitmapColor( 0, 0, 0 );
179 0 : aGreyPalette4[ 1 ] = BitmapColor( 85, 85, 85 );
180 0 : aGreyPalette4[ 2 ] = BitmapColor( 170, 170, 170 );
181 0 : aGreyPalette4[ 3 ] = BitmapColor( 255, 255, 255 );
182 : }
183 :
184 0 : return aGreyPalette4;
185 : }
186 10 : else if( 16 == nEntries )
187 : {
188 0 : if( !aGreyPalette16.GetEntryCount() )
189 : {
190 0 : sal_uInt8 cGrey = 0, cGreyInc = 17;
191 :
192 0 : aGreyPalette16.SetEntryCount( 16 );
193 :
194 0 : for( sal_uInt16 i = 0; i < 16; i++, cGrey = sal::static_int_cast<sal_uInt8>(cGrey + cGreyInc) )
195 0 : aGreyPalette16[ i ] = BitmapColor( cGrey, cGrey, cGrey );
196 : }
197 :
198 0 : return aGreyPalette16;
199 : }
200 : else
201 : {
202 10 : if( !aGreyPalette256.GetEntryCount() )
203 : {
204 4 : aGreyPalette256.SetEntryCount( 256 );
205 :
206 1028 : for( sal_uInt16 i = 0; i < 256; i++ )
207 1024 : aGreyPalette256[ i ] = BitmapColor( (sal_uInt8) i, (sal_uInt8) i, (sal_uInt8) i );
208 : }
209 :
210 10 : return aGreyPalette256;
211 : }
212 : }
213 : else
214 : {
215 : OSL_FAIL( "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)" );
216 0 : return aGreyPalette2;
217 : }
218 : }
219 :
220 : // ------------------------------------------------------------------
221 :
222 0 : bool BitmapPalette::IsGreyPalette() const
223 : {
224 0 : const int nEntryCount = GetEntryCount();
225 0 : if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
226 0 : return true;
227 : // see above: only certain entry values will result in a valid call to GetGreyPalette
228 0 : if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 )
229 : {
230 0 : const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount );
231 0 : if( rGreyPalette == *this )
232 0 : return true;
233 : }
234 :
235 0 : bool bRet = false;
236 : // TODO: is it worth to compare the entries for the general case?
237 0 : if (nEntryCount == 2)
238 : {
239 0 : const BitmapColor& rCol0(mpBitmapColor[0]);
240 0 : const BitmapColor& rCol1(mpBitmapColor[1]);
241 0 : bRet = rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() &&
242 0 : rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue();
243 : }
244 0 : return bRet;
245 : }
246 :
247 : // ------------------------------------------------------------------
248 :
249 7384 : Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
250 : {
251 7384 : maPrefSize = rBitmap.maPrefSize;
252 7384 : maPrefMapMode = rBitmap.maPrefMapMode;
253 :
254 7384 : if ( rBitmap.mpImpBmp )
255 1104 : rBitmap.mpImpBmp->ImplIncRefCount();
256 :
257 7384 : ImplReleaseRef();
258 7384 : mpImpBmp = rBitmap.mpImpBmp;
259 :
260 7384 : return *this;
261 : }
262 :
263 : // ------------------------------------------------------------------
264 :
265 0 : sal_Bool Bitmap::IsEqual( const Bitmap& rBmp ) const
266 : {
267 0 : return( IsSameInstance( rBmp ) ||
268 0 : ( rBmp.GetSizePixel() == GetSizePixel() &&
269 0 : rBmp.GetBitCount() == GetBitCount() &&
270 0 : rBmp.GetChecksum() == GetChecksum() ) );
271 : }
272 :
273 : // ------------------------------------------------------------------
274 :
275 31516 : void Bitmap::SetEmpty()
276 : {
277 31516 : maPrefMapMode = MapMode();
278 31516 : maPrefSize = Size();
279 :
280 31516 : ImplReleaseRef();
281 31516 : mpImpBmp = NULL;
282 31516 : }
283 :
284 : // ------------------------------------------------------------------
285 :
286 3323 : Size Bitmap::GetSizePixel() const
287 : {
288 3323 : return( mpImpBmp ? mpImpBmp->ImplGetSize() : Size() );
289 : }
290 : // ------------------------------------------------------------------
291 :
292 25 : void Bitmap::SetSourceSizePixel( const Size& rSize)
293 : {
294 25 : if( mpImpBmp )
295 25 : mpImpBmp->ImplSetSourceSize( rSize);
296 25 : }
297 :
298 : // ------------------------------------------------------------------
299 :
300 423 : sal_uInt16 Bitmap::GetBitCount() const
301 : {
302 423 : return( mpImpBmp ? mpImpBmp->ImplGetBitCount() : 0 );
303 : }
304 :
305 : // ------------------------------------------------------------------
306 :
307 0 : sal_Bool Bitmap::HasGreyPalette() const
308 : {
309 0 : const sal_uInt16 nBitCount = GetBitCount();
310 0 : sal_Bool bRet = nBitCount == 1 ? sal_True : sal_False;
311 :
312 0 : BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
313 :
314 0 : if( pRAcc )
315 : {
316 0 : bRet = pRAcc->HasPalette() && pRAcc->GetPalette().IsGreyPalette();
317 0 : ( (Bitmap*) this )->ReleaseAccess( pRAcc );
318 : }
319 :
320 0 : return bRet;
321 : }
322 :
323 : // ------------------------------------------------------------------
324 :
325 124 : sal_uLong Bitmap::GetChecksum() const
326 : {
327 124 : sal_uLong nRet = 0UL;
328 :
329 124 : if( mpImpBmp )
330 : {
331 124 : nRet = mpImpBmp->ImplGetChecksum();
332 :
333 124 : if( !nRet )
334 : {
335 44 : BitmapReadAccess* pRAcc = ( (Bitmap*) this )->AcquireReadAccess();
336 :
337 44 : if( pRAcc && pRAcc->Width() && pRAcc->Height() )
338 : {
339 44 : sal_uInt32 nCrc = 0;
340 : SVBT32 aBT32;
341 :
342 44 : pRAcc->ImplZeroInitUnusedBits();
343 :
344 44 : UInt32ToSVBT32( pRAcc->Width(), aBT32 );
345 44 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
346 :
347 44 : UInt32ToSVBT32( pRAcc->Height(), aBT32 );
348 44 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
349 :
350 44 : UInt32ToSVBT32( pRAcc->GetBitCount(), aBT32 );
351 44 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
352 :
353 44 : UInt32ToSVBT32( pRAcc->GetColorMask().GetRedMask(), aBT32 );
354 44 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
355 :
356 44 : UInt32ToSVBT32( pRAcc->GetColorMask().GetGreenMask(), aBT32 );
357 44 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
358 :
359 44 : UInt32ToSVBT32( pRAcc->GetColorMask().GetBlueMask(), aBT32 );
360 44 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
361 :
362 44 : if( pRAcc->HasPalette() )
363 : {
364 28 : nCrc = rtl_crc32( nCrc, pRAcc->GetPalette().ImplGetColorBuffer(),
365 56 : pRAcc->GetPaletteEntryCount() * sizeof( BitmapColor ) );
366 : }
367 :
368 44 : nCrc = rtl_crc32( nCrc, pRAcc->GetBuffer(), pRAcc->GetScanlineSize() * pRAcc->Height() );
369 :
370 44 : mpImpBmp->ImplSetChecksum( nRet = nCrc );
371 : }
372 :
373 44 : if (pRAcc) ( (Bitmap*) this )->ReleaseAccess( pRAcc );
374 : }
375 : }
376 :
377 124 : return nRet;
378 : }
379 :
380 : // ------------------------------------------------------------------
381 :
382 90455 : void Bitmap::ImplReleaseRef()
383 : {
384 90455 : if( mpImpBmp )
385 : {
386 2702 : if( mpImpBmp->ImplGetRefCount() > 1UL )
387 2462 : mpImpBmp->ImplDecRefCount();
388 : else
389 : {
390 240 : delete mpImpBmp;
391 240 : mpImpBmp = NULL;
392 : }
393 : }
394 90455 : }
395 :
396 : // ------------------------------------------------------------------
397 :
398 263 : void Bitmap::ImplMakeUnique()
399 : {
400 263 : if( mpImpBmp && mpImpBmp->ImplGetRefCount() > 1UL )
401 : {
402 3 : ImpBitmap* pOldImpBmp = mpImpBmp;
403 :
404 3 : pOldImpBmp->ImplDecRefCount();
405 :
406 3 : mpImpBmp = new ImpBitmap;
407 3 : mpImpBmp->ImplCreate( *pOldImpBmp );
408 : }
409 263 : }
410 :
411 : // ------------------------------------------------------------------
412 :
413 1 : void Bitmap::ImplAssignWithSize( const Bitmap& rBitmap )
414 : {
415 1 : const Size aOldSizePix( GetSizePixel() );
416 1 : const Size aNewSizePix( rBitmap.GetSizePixel() );
417 1 : const MapMode aOldMapMode( maPrefMapMode );
418 1 : Size aNewPrefSize;
419 :
420 1 : if( ( aOldSizePix != aNewSizePix ) && aOldSizePix.Width() && aOldSizePix.Height() )
421 : {
422 0 : aNewPrefSize.Width() = FRound( maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width() );
423 0 : aNewPrefSize.Height() = FRound( maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height() );
424 : }
425 : else
426 1 : aNewPrefSize = maPrefSize;
427 :
428 1 : *this = rBitmap;
429 :
430 1 : maPrefSize = aNewPrefSize;
431 1 : maPrefMapMode = aOldMapMode;
432 1 : }
433 :
434 : // ------------------------------------------------------------------
435 :
436 1336 : ImpBitmap* Bitmap::ImplGetImpBitmap() const
437 : {
438 1336 : return mpImpBmp;
439 : }
440 :
441 : // ------------------------------------------------------------------
442 :
443 69 : void Bitmap::ImplSetImpBitmap( ImpBitmap* pImpBmp )
444 : {
445 69 : if( pImpBmp != mpImpBmp )
446 : {
447 69 : ImplReleaseRef();
448 69 : mpImpBmp = pImpBmp;
449 : }
450 69 : }
451 :
452 : // ------------------------------------------------------------------
453 :
454 129 : BitmapReadAccess* Bitmap::AcquireReadAccess()
455 : {
456 129 : BitmapReadAccess* pReadAccess = new BitmapReadAccess( *this );
457 :
458 129 : if( !*pReadAccess )
459 : {
460 0 : delete pReadAccess;
461 0 : pReadAccess = NULL;
462 : }
463 :
464 129 : return pReadAccess;
465 : }
466 :
467 : // ------------------------------------------------------------------
468 :
469 263 : BitmapWriteAccess* Bitmap::AcquireWriteAccess()
470 : {
471 263 : BitmapWriteAccess* pWriteAccess = new BitmapWriteAccess( *this );
472 :
473 263 : if( !*pWriteAccess )
474 : {
475 3 : delete pWriteAccess;
476 3 : pWriteAccess = NULL;
477 : }
478 :
479 263 : return pWriteAccess;
480 : }
481 :
482 : // ------------------------------------------------------------------
483 :
484 389 : void Bitmap::ReleaseAccess( BitmapReadAccess* pBitmapAccess )
485 : {
486 389 : delete pBitmapAccess;
487 389 : }
488 :
489 : // ------------------------------------------------------------------
490 :
491 136 : sal_Bool Bitmap::Erase( const Color& rFillColor )
492 : {
493 136 : if( !(*this) )
494 56 : return sal_True;
495 :
496 80 : BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
497 80 : sal_Bool bRet = sal_False;
498 :
499 80 : if( pWriteAcc )
500 : {
501 79 : const sal_uLong nFormat = pWriteAcc->GetScanlineFormat();
502 79 : sal_uInt8 cIndex = 0;
503 79 : sal_Bool bFast = sal_False;
504 :
505 79 : switch( nFormat )
506 : {
507 : case( BMP_FORMAT_1BIT_MSB_PAL ):
508 : case( BMP_FORMAT_1BIT_LSB_PAL ):
509 : {
510 6 : cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
511 6 : cIndex = ( cIndex ? 255 : 0 );
512 6 : bFast = sal_True;
513 : }
514 6 : break;
515 :
516 : case( BMP_FORMAT_4BIT_MSN_PAL ):
517 : case( BMP_FORMAT_4BIT_LSN_PAL ):
518 : {
519 0 : cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
520 0 : cIndex = cIndex | ( cIndex << 4 );
521 0 : bFast = sal_True;
522 : }
523 0 : break;
524 :
525 : case( BMP_FORMAT_8BIT_PAL ):
526 : {
527 73 : cIndex = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( rFillColor );
528 73 : bFast = sal_True;
529 : }
530 73 : break;
531 :
532 : case( BMP_FORMAT_24BIT_TC_BGR ):
533 : case( BMP_FORMAT_24BIT_TC_RGB ):
534 : {
535 0 : if( ( rFillColor.GetRed() == rFillColor.GetGreen() ) &&
536 0 : ( rFillColor.GetRed() == rFillColor.GetBlue() ) )
537 : {
538 0 : cIndex = rFillColor.GetRed();
539 0 : bFast = sal_True;
540 : }
541 : else
542 0 : bFast = sal_False;
543 : }
544 0 : break;
545 :
546 : default:
547 0 : bFast = sal_False;
548 0 : break;
549 : }
550 :
551 79 : if( bFast )
552 : {
553 79 : const sal_uLong nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
554 79 : memset( pWriteAcc->GetBuffer(), cIndex, nBufSize );
555 : }
556 : else
557 : {
558 0 : Point aTmpPoint;
559 0 : const Rectangle aRect( aTmpPoint, Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
560 0 : pWriteAcc->SetFillColor( rFillColor );
561 0 : pWriteAcc->FillRect( aRect );
562 : }
563 :
564 79 : ReleaseAccess( pWriteAcc );
565 79 : bRet = sal_True;
566 : }
567 :
568 80 : return bRet;
569 : }
570 :
571 : // ------------------------------------------------------------------
572 :
573 0 : sal_Bool Bitmap::Invert()
574 : {
575 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
576 0 : sal_Bool bRet = sal_False;
577 :
578 0 : if( pAcc )
579 : {
580 0 : if( pAcc->HasPalette() )
581 : {
582 0 : BitmapPalette aBmpPal( pAcc->GetPalette() );
583 0 : const sal_uInt16 nCount = aBmpPal.GetEntryCount();
584 :
585 0 : for( sal_uInt16 i = 0; i < nCount; i++ )
586 0 : aBmpPal[ i ].Invert();
587 :
588 0 : pAcc->SetPalette( aBmpPal );
589 : }
590 : else
591 : {
592 0 : const long nWidth = pAcc->Width();
593 0 : const long nHeight = pAcc->Height();
594 :
595 0 : for( long nX = 0L; nX < nWidth; nX++ )
596 0 : for( long nY = 0L; nY < nHeight; nY++ )
597 0 : pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nX ).Invert() );
598 : }
599 :
600 0 : ReleaseAccess( pAcc );
601 0 : bRet = sal_True;
602 : }
603 :
604 0 : return bRet;
605 : }
606 :
607 : // ------------------------------------------------------------------
608 :
609 1 : sal_Bool Bitmap::Mirror( sal_uLong nMirrorFlags )
610 : {
611 1 : sal_Bool bHorz = ( ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ );
612 1 : sal_Bool bVert = ( ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
613 1 : sal_Bool bRet = sal_False;
614 :
615 1 : if( bHorz && !bVert )
616 : {
617 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
618 :
619 0 : if( pAcc )
620 : {
621 0 : const long nWidth = pAcc->Width();
622 0 : const long nHeight = pAcc->Height();
623 0 : const long nWidth1 = nWidth - 1L;
624 0 : const long nWidth_2 = nWidth >> 1L;
625 :
626 0 : for( long nY = 0L; nY < nHeight; nY++ )
627 : {
628 0 : for( long nX = 0L, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
629 : {
630 0 : const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
631 :
632 0 : pAcc->SetPixel( nY, nX, pAcc->GetPixel( nY, nOther ) );
633 0 : pAcc->SetPixel( nY, nOther, aTemp );
634 0 : }
635 : }
636 :
637 0 : ReleaseAccess( pAcc );
638 0 : bRet = sal_True;
639 0 : }
640 : }
641 1 : else if( bVert && !bHorz )
642 : {
643 1 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
644 :
645 1 : if( pAcc )
646 : {
647 1 : const long nScanSize = pAcc->GetScanlineSize();
648 1 : sal_uInt8* pBuffer = new sal_uInt8[ nScanSize ];
649 1 : const long nHeight = pAcc->Height();
650 1 : const long nHeight1 = nHeight - 1L;
651 1 : const long nHeight_2 = nHeight >> 1L;
652 :
653 63 : for( long nY = 0L, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
654 : {
655 62 : memcpy( pBuffer, pAcc->GetScanline( nY ), nScanSize );
656 62 : memcpy( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
657 62 : memcpy( pAcc->GetScanline( nOther ), pBuffer, nScanSize );
658 : }
659 :
660 1 : delete[] pBuffer;
661 1 : ReleaseAccess( pAcc );
662 1 : bRet = sal_True;
663 1 : }
664 : }
665 0 : else if( bHorz && bVert )
666 : {
667 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
668 :
669 0 : if( pAcc )
670 : {
671 0 : const long nWidth = pAcc->Width();
672 0 : const long nWidth1 = nWidth - 1L;
673 0 : const long nHeight = pAcc->Height();
674 0 : long nHeight_2 = nHeight >> 1;
675 :
676 0 : for( long nY = 0L, nOtherY = nHeight - 1L; nY < nHeight_2; nY++, nOtherY-- )
677 : {
678 0 : for( long nX = 0L, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
679 : {
680 0 : const BitmapColor aTemp( pAcc->GetPixel( nY, nX ) );
681 :
682 0 : pAcc->SetPixel( nY, nX, pAcc->GetPixel( nOtherY, nOtherX ) );
683 0 : pAcc->SetPixel( nOtherY, nOtherX, aTemp );
684 0 : }
685 : }
686 :
687 : // ggf. noch mittlere Zeile horizontal spiegeln
688 0 : if( nHeight & 1 )
689 : {
690 0 : for( long nX = 0L, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
691 : {
692 0 : const BitmapColor aTemp( pAcc->GetPixel( nHeight_2, nX ) );
693 0 : pAcc->SetPixel( nHeight_2, nX, pAcc->GetPixel( nHeight_2, nOtherX ) );
694 0 : pAcc->SetPixel( nHeight_2, nOtherX, aTemp );
695 0 : }
696 : }
697 :
698 0 : ReleaseAccess( pAcc );
699 0 : bRet = sal_True;
700 0 : }
701 : }
702 : else
703 0 : bRet = sal_True;
704 :
705 1 : return bRet;
706 : }
707 :
708 : // ------------------------------------------------------------------
709 :
710 0 : sal_Bool Bitmap::Rotate( long nAngle10, const Color& rFillColor )
711 : {
712 0 : sal_Bool bRet = sal_False;
713 :
714 0 : nAngle10 %= 3600L;
715 0 : nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
716 :
717 0 : if( !nAngle10 )
718 0 : bRet = sal_True;
719 0 : else if( 1800L == nAngle10 )
720 0 : bRet = Mirror( BMP_MIRROR_HORZ | BMP_MIRROR_VERT );
721 : else
722 : {
723 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
724 0 : Bitmap aRotatedBmp;
725 :
726 0 : if( pReadAcc )
727 : {
728 0 : const Size aSizePix( GetSizePixel() );
729 :
730 0 : if( ( 900L == nAngle10 ) || ( 2700L == nAngle10 ) )
731 : {
732 0 : const Size aNewSizePix( aSizePix.Height(), aSizePix.Width() );
733 0 : Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
734 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
735 :
736 0 : if( pWriteAcc )
737 : {
738 0 : const long nWidth = aSizePix.Width();
739 0 : const long nWidth1 = nWidth - 1L;
740 0 : const long nHeight = aSizePix.Height();
741 0 : const long nHeight1 = nHeight - 1L;
742 0 : const long nNewWidth = aNewSizePix.Width();
743 0 : const long nNewHeight = aNewSizePix.Height();
744 :
745 0 : if( 900L == nAngle10 )
746 : {
747 0 : for( long nY = 0L, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
748 0 : for( long nX = 0L, nOtherY = 0L; nX < nNewWidth; nX++ )
749 0 : pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
750 : }
751 0 : else if( 2700L == nAngle10 )
752 : {
753 0 : for( long nY = 0L, nOtherX = 0L; nY < nNewHeight; nY++, nOtherX++ )
754 0 : for( long nX = 0L, nOtherY = nHeight1; nX < nNewWidth; nX++ )
755 0 : pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
756 : }
757 :
758 0 : aNewBmp.ReleaseAccess( pWriteAcc );
759 : }
760 :
761 0 : aRotatedBmp = aNewBmp;
762 : }
763 : else
764 : {
765 0 : Point aTmpPoint;
766 0 : Rectangle aTmpRectangle( aTmpPoint, aSizePix );
767 0 : Polygon aPoly( aTmpRectangle );
768 0 : aPoly.Rotate( aTmpPoint, (sal_uInt16) nAngle10 );
769 :
770 0 : Rectangle aNewBound( aPoly.GetBoundRect() );
771 0 : const Size aNewSizePix( aNewBound.GetSize() );
772 0 : Bitmap aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
773 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
774 :
775 0 : if( pWriteAcc )
776 : {
777 0 : const BitmapColor aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
778 0 : const double fCosAngle = cos( nAngle10 * F_PI1800 );
779 0 : const double fSinAngle = sin( nAngle10 * F_PI1800 );
780 0 : const double fXMin = aNewBound.Left();
781 0 : const double fYMin = aNewBound.Top();
782 0 : const long nWidth = aSizePix.Width();
783 0 : const long nHeight = aSizePix.Height();
784 0 : const long nNewWidth = aNewSizePix.Width();
785 0 : const long nNewHeight = aNewSizePix.Height();
786 : long nX;
787 : long nY;
788 : long nRotX;
789 : long nRotY;
790 : long nSinY;
791 : long nCosY;
792 0 : long* pCosX = new long[ nNewWidth ];
793 0 : long* pSinX = new long[ nNewWidth ];
794 0 : long* pCosY = new long[ nNewHeight ];
795 0 : long* pSinY = new long[ nNewHeight ];
796 :
797 0 : for ( nX = 0; nX < nNewWidth; nX++ )
798 : {
799 0 : const double fTmp = ( fXMin + nX ) * 64.;
800 :
801 0 : pCosX[ nX ] = FRound( fCosAngle * fTmp );
802 0 : pSinX[ nX ] = FRound( fSinAngle * fTmp );
803 : }
804 :
805 0 : for ( nY = 0; nY < nNewHeight; nY++ )
806 : {
807 0 : const double fTmp = ( fYMin + nY ) * 64.;
808 :
809 0 : pCosY[ nY ] = FRound( fCosAngle * fTmp );
810 0 : pSinY[ nY ] = FRound( fSinAngle * fTmp );
811 : }
812 :
813 0 : for( nY = 0L; nY < nNewHeight; nY++ )
814 : {
815 0 : nSinY = pSinY[ nY ];
816 0 : nCosY = pCosY[ nY ];
817 :
818 0 : for( nX = 0L; nX < nNewWidth; nX++ )
819 : {
820 0 : nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
821 0 : nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
822 :
823 0 : if ( ( nRotX > -1L ) && ( nRotX < nWidth ) && ( nRotY > -1L ) && ( nRotY < nHeight ) )
824 0 : pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
825 : else
826 0 : pWriteAcc->SetPixel( nY, nX, aFillColor );
827 : }
828 : }
829 :
830 0 : delete[] pSinX;
831 0 : delete[] pCosX;
832 0 : delete[] pSinY;
833 0 : delete[] pCosY;
834 :
835 0 : aNewBmp.ReleaseAccess( pWriteAcc );
836 : }
837 :
838 0 : aRotatedBmp = aNewBmp;
839 : }
840 :
841 0 : ReleaseAccess( pReadAcc );
842 : }
843 :
844 0 : if( ( bRet = !!aRotatedBmp ) == sal_True )
845 0 : ImplAssignWithSize( aRotatedBmp );
846 : }
847 :
848 0 : return bRet;
849 : };
850 :
851 : // ------------------------------------------------------------------
852 :
853 1 : sal_Bool Bitmap::Crop( const Rectangle& rRectPixel )
854 : {
855 1 : const Size aSizePix( GetSizePixel() );
856 1 : Rectangle aRect( rRectPixel );
857 1 : sal_Bool bRet = sal_False;
858 :
859 1 : aRect.Intersection( Rectangle( Point(), aSizePix ) );
860 :
861 1 : if( !aRect.IsEmpty() )
862 : {
863 1 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
864 :
865 1 : if( pReadAcc )
866 : {
867 1 : Point aTmpPoint;
868 1 : const Rectangle aNewRect( aTmpPoint, aRect.GetSize() );
869 1 : Bitmap aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
870 1 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
871 :
872 1 : if( pWriteAcc )
873 : {
874 1 : const long nOldX = aRect.Left();
875 1 : const long nOldY = aRect.Top();
876 1 : const long nNewWidth = aNewRect.GetWidth();
877 1 : const long nNewHeight = aNewRect.GetHeight();
878 :
879 126 : for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
880 35375 : for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
881 35250 : pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY2, nX2 ) );
882 :
883 1 : aNewBmp.ReleaseAccess( pWriteAcc );
884 1 : bRet = sal_True;
885 : }
886 :
887 1 : ReleaseAccess( pReadAcc );
888 :
889 1 : if( bRet )
890 1 : ImplAssignWithSize( aNewBmp );
891 : }
892 : }
893 :
894 1 : return bRet;
895 : };
896 :
897 : // ------------------------------------------------------------------
898 :
899 0 : sal_Bool Bitmap::CopyPixel( const Rectangle& rRectDst,
900 : const Rectangle& rRectSrc, const Bitmap* pBmpSrc )
901 : {
902 0 : const Size aSizePix( GetSizePixel() );
903 0 : Rectangle aRectDst( rRectDst );
904 0 : sal_Bool bRet = sal_False;
905 :
906 0 : aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
907 :
908 0 : if( !aRectDst.IsEmpty() )
909 : {
910 0 : if( pBmpSrc && ( *pBmpSrc != *this ) )
911 : {
912 0 : Bitmap* pSrc = (Bitmap*) pBmpSrc;
913 0 : const Size aCopySizePix( pSrc->GetSizePixel() );
914 0 : Rectangle aRectSrc( rRectSrc );
915 0 : const sal_uInt16 nSrcBitCount = pBmpSrc->GetBitCount();
916 0 : const sal_uInt16 nDstBitCount = GetBitCount();
917 :
918 0 : if( nSrcBitCount > nDstBitCount )
919 : {
920 0 : long nNextIndex = 0L;
921 :
922 0 : if( ( nSrcBitCount == 24 ) && ( nDstBitCount < 24 ) )
923 0 : Convert( BMP_CONVERSION_24BIT );
924 0 : else if( ( nSrcBitCount == 8 ) && ( nDstBitCount < 8 ) )
925 : {
926 0 : Convert( BMP_CONVERSION_8BIT_COLORS );
927 0 : nNextIndex = 16;
928 : }
929 0 : else if( ( nSrcBitCount == 4 ) && ( nDstBitCount < 4 ) )
930 : {
931 0 : Convert( BMP_CONVERSION_4BIT_COLORS );
932 0 : nNextIndex = 2;
933 : }
934 :
935 0 : if( nNextIndex )
936 : {
937 0 : BitmapReadAccess* pSrcAcc = pSrc->AcquireReadAccess();
938 0 : BitmapWriteAccess* pDstAcc = AcquireWriteAccess();
939 :
940 0 : if( pSrcAcc && pDstAcc )
941 : {
942 0 : const long nSrcCount = pDstAcc->GetPaletteEntryCount();
943 0 : const long nDstCount = 1 << nDstBitCount;
944 : sal_Bool bFound;
945 :
946 0 : for( long i = 0L; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); i++ )
947 : {
948 0 : const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( (sal_uInt16) i );
949 :
950 0 : bFound = sal_False;
951 :
952 0 : for( long j = 0L; j < nDstCount; j++ )
953 : {
954 0 : if( rSrcCol == pDstAcc->GetPaletteColor( (sal_uInt16) j ) )
955 : {
956 0 : bFound = sal_True;
957 0 : break;
958 : }
959 : }
960 :
961 0 : if( !bFound )
962 0 : pDstAcc->SetPaletteColor( (sal_uInt16) nNextIndex++, rSrcCol );
963 : }
964 : }
965 :
966 0 : if( pSrcAcc )
967 0 : pSrc->ReleaseAccess( pSrcAcc );
968 :
969 0 : if( pDstAcc )
970 0 : ReleaseAccess( pDstAcc );
971 : }
972 : }
973 :
974 0 : aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
975 :
976 0 : if( !aRectSrc.IsEmpty() )
977 : {
978 0 : BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
979 :
980 0 : if( pReadAcc )
981 : {
982 0 : BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
983 :
984 0 : if( pWriteAcc )
985 : {
986 0 : const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
987 0 : const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
988 0 : const long nSrcEndX = aRectSrc.Left() + nWidth;
989 0 : const long nSrcEndY = aRectSrc.Top() + nHeight;
990 0 : long nDstY = aRectDst.Top();
991 :
992 0 : if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
993 : {
994 0 : const sal_uInt16 nCount = pReadAcc->GetPaletteEntryCount();
995 0 : sal_uInt8* pMap = new sal_uInt8[ nCount ];
996 :
997 : // Index-Map fuer Farbtabelle
998 : // aufbauen, da das Bild ja (relativ) farbgenau
999 : // kopiert werden soll
1000 0 : for( sal_uInt16 i = 0; i < nCount; i++ )
1001 0 : pMap[ i ] = (sal_uInt8) pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) );
1002 :
1003 0 : for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1004 0 : for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1005 0 : pWriteAcc->SetPixel( nDstY, nDstX, pMap[ pReadAcc->GetPixel( nSrcY, nSrcX ).GetIndex() ] );
1006 :
1007 0 : delete[] pMap;
1008 : }
1009 0 : else if( pReadAcc->HasPalette() )
1010 : {
1011 0 : for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1012 0 : for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1013 0 : pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nSrcY, nSrcX ) ) );
1014 : }
1015 : else
1016 0 : for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
1017 0 : for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
1018 0 : pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
1019 :
1020 0 : ReleaseAccess( pWriteAcc );
1021 0 : bRet = ( nWidth > 0L ) && ( nHeight > 0L );
1022 : }
1023 :
1024 0 : pSrc->ReleaseAccess( pReadAcc );
1025 : }
1026 : }
1027 : }
1028 : else
1029 : {
1030 0 : Rectangle aRectSrc( rRectSrc );
1031 :
1032 0 : aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
1033 :
1034 0 : if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
1035 : {
1036 0 : BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
1037 :
1038 0 : if( pWriteAcc )
1039 : {
1040 0 : const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
1041 0 : const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
1042 0 : const long nSrcX = aRectSrc.Left();
1043 0 : const long nSrcY = aRectSrc.Top();
1044 0 : const long nSrcEndX1 = nSrcX + nWidth - 1L;
1045 0 : const long nSrcEndY1 = nSrcY + nHeight - 1L;
1046 0 : const long nDstX = aRectDst.Left();
1047 0 : const long nDstY = aRectDst.Top();
1048 0 : const long nDstEndX1 = nDstX + nWidth - 1L;
1049 0 : const long nDstEndY1 = nDstY + nHeight - 1L;
1050 :
1051 0 : if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
1052 : {
1053 0 : for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
1054 0 : for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
1055 0 : pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1056 : }
1057 0 : else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
1058 : {
1059 0 : for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
1060 0 : for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
1061 0 : pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1062 : }
1063 0 : else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
1064 : {
1065 0 : for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
1066 0 : for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
1067 0 : pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1068 : }
1069 : else
1070 : {
1071 0 : for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
1072 0 : for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
1073 0 : pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
1074 : }
1075 :
1076 0 : ReleaseAccess( pWriteAcc );
1077 0 : bRet = sal_True;
1078 : }
1079 : }
1080 : }
1081 : }
1082 :
1083 0 : return bRet;
1084 : }
1085 :
1086 : // ------------------------------------------------------------------
1087 :
1088 0 : sal_Bool Bitmap::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor )
1089 : {
1090 0 : sal_Bool bRet = sal_False;
1091 :
1092 0 : if( nDX || nDY )
1093 : {
1094 0 : const Size aSizePixel( GetSizePixel() );
1095 0 : const long nWidth = aSizePixel.Width();
1096 0 : const long nHeight = aSizePixel.Height();
1097 0 : const Size aNewSize( nWidth + nDX, nHeight + nDY );
1098 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
1099 :
1100 0 : if( pReadAcc )
1101 : {
1102 0 : BitmapPalette aBmpPal( pReadAcc->GetPalette() );
1103 0 : Bitmap aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
1104 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
1105 :
1106 0 : if( pWriteAcc )
1107 : {
1108 0 : BitmapColor aColor;
1109 0 : const long nNewX = nWidth;
1110 0 : const long nNewY = nHeight;
1111 0 : const long nNewWidth = pWriteAcc->Width();
1112 0 : const long nNewHeight = pWriteAcc->Height();
1113 : long nX;
1114 : long nY;
1115 :
1116 0 : if( pInitColor )
1117 0 : aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
1118 :
1119 0 : for( nY = 0L; nY < nHeight; nY++ )
1120 : {
1121 0 : pWriteAcc->CopyScanline( nY, *pReadAcc );
1122 :
1123 0 : if( pInitColor && nDX )
1124 0 : for( nX = nNewX; nX < nNewWidth; nX++ )
1125 0 : pWriteAcc->SetPixel( nY, nX, aColor );
1126 : }
1127 :
1128 0 : if( pInitColor && nDY )
1129 0 : for( nY = nNewY; nY < nNewHeight; nY++ )
1130 0 : for( nX = 0; nX < nNewWidth; nX++ )
1131 0 : pWriteAcc->SetPixel( nY, nX, aColor );
1132 :
1133 0 : aNewBmp.ReleaseAccess( pWriteAcc );
1134 0 : bRet = sal_True;
1135 : }
1136 :
1137 0 : ReleaseAccess( pReadAcc );
1138 :
1139 0 : if( bRet )
1140 0 : ImplAssignWithSize( aNewBmp );
1141 : }
1142 : }
1143 :
1144 0 : return bRet;
1145 : }
1146 :
1147 : // ------------------------------------------------------------------
1148 :
1149 0 : Bitmap Bitmap::CreateMask( const Color& rTransColor, sal_uLong nTol ) const
1150 : {
1151 0 : Bitmap aNewBmp( GetSizePixel(), 1 );
1152 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
1153 0 : sal_Bool bRet = sal_False;
1154 :
1155 0 : if( pWriteAcc )
1156 : {
1157 0 : BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
1158 :
1159 0 : if( pReadAcc )
1160 : {
1161 0 : const long nWidth = pReadAcc->Width();
1162 0 : const long nHeight = pReadAcc->Height();
1163 0 : const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
1164 0 : const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1165 :
1166 0 : if( !nTol )
1167 : {
1168 0 : const BitmapColor aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
1169 : long nX, nY;
1170 :
1171 0 : if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ||
1172 0 : pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_LSN_PAL )
1173 : {
1174 : // optimized for 4Bit-MSN/LSN source palette
1175 0 : const sal_uInt8 cTest = aTest.GetIndex();
1176 0 : const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == BMP_FORMAT_4BIT_MSN_PAL ) ? 4 : 0 );
1177 :
1178 0 : if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
1179 0 : aWhite.GetIndex() == 1 )
1180 : {
1181 : // optimized for 1Bit-MSB destination palette
1182 0 : for( nY = 0L; nY < nHeight; nY++ )
1183 : {
1184 0 : Scanline pSrc = pReadAcc->GetScanline( nY );
1185 0 : Scanline pDst = pWriteAcc->GetScanline( nY );
1186 0 : long nShift = 0;
1187 0 : for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
1188 : {
1189 0 : if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
1190 0 : pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
1191 : else
1192 0 : pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
1193 : }
1194 : }
1195 : }
1196 : else
1197 : {
1198 0 : for( nY = 0L; nY < nHeight; nY++ )
1199 : {
1200 0 : Scanline pSrc = pReadAcc->GetScanline( nY );
1201 0 : long nShift = 0;
1202 0 : for( nX = 0L, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4 )
1203 : {
1204 0 : if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
1205 0 : pWriteAcc->SetPixel( nY, nX, aWhite );
1206 : else
1207 0 : pWriteAcc->SetPixel( nY, nX, aBlack );
1208 : }
1209 : }
1210 : }
1211 : }
1212 0 : else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1213 : {
1214 : // optimized for 8Bit source palette
1215 0 : const sal_uInt8 cTest = aTest.GetIndex();
1216 :
1217 0 : if( pWriteAcc->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
1218 0 : aWhite.GetIndex() == 1 )
1219 : {
1220 : // optimized for 1Bit-MSB destination palette
1221 0 : for( nY = 0L; nY < nHeight; nY++ )
1222 : {
1223 0 : Scanline pSrc = pReadAcc->GetScanline( nY );
1224 0 : Scanline pDst = pWriteAcc->GetScanline( nY );
1225 0 : for( nX = 0L; nX < nWidth; nX++ )
1226 : {
1227 0 : if( cTest == pSrc[ nX ] )
1228 0 : pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
1229 : else
1230 0 : pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
1231 : }
1232 : }
1233 : }
1234 : else
1235 : {
1236 0 : for( nY = 0L; nY < nHeight; nY++ )
1237 : {
1238 0 : Scanline pSrc = pReadAcc->GetScanline( nY );
1239 0 : for( nX = 0L; nX < nWidth; nX++ )
1240 : {
1241 0 : if( cTest == pSrc[ nX ] )
1242 0 : pWriteAcc->SetPixel( nY, nX, aWhite );
1243 : else
1244 0 : pWriteAcc->SetPixel( nY, nX, aBlack );
1245 : }
1246 : }
1247 : }
1248 : }
1249 : else
1250 : {
1251 : // not optimized
1252 0 : for( nY = 0L; nY < nHeight; nY++ )
1253 : {
1254 0 : for( nX = 0L; nX < nWidth; nX++ )
1255 : {
1256 0 : if( aTest == pReadAcc->GetPixel( nY, nX ) )
1257 0 : pWriteAcc->SetPixel( nY, nX, aWhite );
1258 : else
1259 0 : pWriteAcc->SetPixel( nY, nX, aBlack );
1260 : }
1261 : }
1262 0 : }
1263 : }
1264 : else
1265 : {
1266 0 : BitmapColor aCol;
1267 : long nR, nG, nB;
1268 0 : const long nMinR = MinMax( (long) rTransColor.GetRed() - nTol, 0, 255 );
1269 0 : const long nMaxR = MinMax( (long) rTransColor.GetRed() + nTol, 0, 255 );
1270 0 : const long nMinG = MinMax( (long) rTransColor.GetGreen() - nTol, 0, 255 );
1271 0 : const long nMaxG = MinMax( (long) rTransColor.GetGreen() + nTol, 0, 255 );
1272 0 : const long nMinB = MinMax( (long) rTransColor.GetBlue() - nTol, 0, 255 );
1273 0 : const long nMaxB = MinMax( (long) rTransColor.GetBlue() + nTol, 0, 255 );
1274 :
1275 0 : if( pReadAcc->HasPalette() )
1276 : {
1277 0 : for( long nY = 0L; nY < nHeight; nY++ )
1278 : {
1279 0 : for( long nX = 0L; nX < nWidth; nX++ )
1280 : {
1281 0 : aCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) );
1282 0 : nR = aCol.GetRed();
1283 0 : nG = aCol.GetGreen();
1284 0 : nB = aCol.GetBlue();
1285 :
1286 0 : if( nMinR <= nR && nMaxR >= nR &&
1287 : nMinG <= nG && nMaxG >= nG &&
1288 : nMinB <= nB && nMaxB >= nB )
1289 : {
1290 0 : pWriteAcc->SetPixel( nY, nX, aWhite );
1291 : }
1292 : else
1293 0 : pWriteAcc->SetPixel( nY, nX, aBlack );
1294 : }
1295 : }
1296 : }
1297 : else
1298 : {
1299 0 : for( long nY = 0L; nY < nHeight; nY++ )
1300 : {
1301 0 : for( long nX = 0L; nX < nWidth; nX++ )
1302 : {
1303 0 : aCol = pReadAcc->GetPixel( nY, nX );
1304 0 : nR = aCol.GetRed();
1305 0 : nG = aCol.GetGreen();
1306 0 : nB = aCol.GetBlue();
1307 :
1308 0 : if( nMinR <= nR && nMaxR >= nR &&
1309 : nMinG <= nG && nMaxG >= nG &&
1310 : nMinB <= nB && nMaxB >= nB )
1311 : {
1312 0 : pWriteAcc->SetPixel( nY, nX, aWhite );
1313 : }
1314 : else
1315 0 : pWriteAcc->SetPixel( nY, nX, aBlack );
1316 : }
1317 : }
1318 0 : }
1319 : }
1320 :
1321 0 : ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
1322 0 : bRet = sal_True;
1323 : }
1324 :
1325 0 : aNewBmp.ReleaseAccess( pWriteAcc );
1326 : }
1327 :
1328 0 : if( bRet )
1329 : {
1330 0 : aNewBmp.maPrefSize = maPrefSize;
1331 0 : aNewBmp.maPrefMapMode = maPrefMapMode;
1332 : }
1333 : else
1334 0 : aNewBmp = Bitmap();
1335 :
1336 0 : return aNewBmp;
1337 : }
1338 :
1339 : // ------------------------------------------------------------------
1340 :
1341 0 : Region Bitmap::CreateRegion( const Color& rColor, const Rectangle& rRect ) const
1342 : {
1343 0 : Region aRegion;
1344 0 : Rectangle aRect( rRect );
1345 0 : BitmapReadAccess* pReadAcc = ( (Bitmap*) this )->AcquireReadAccess();
1346 :
1347 0 : aRect.Intersection( Rectangle( Point(), GetSizePixel() ) );
1348 0 : aRect.Justify();
1349 :
1350 0 : if( pReadAcc )
1351 : {
1352 0 : Rectangle aSubRect;
1353 0 : const long nLeft = aRect.Left();
1354 0 : const long nTop = aRect.Top();
1355 0 : const long nRight = aRect.Right();
1356 0 : const long nBottom = aRect.Bottom();
1357 0 : const BitmapColor aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
1358 :
1359 0 : aRegion.ImplBeginAddRect();
1360 :
1361 0 : for( long nY = nTop; nY <= nBottom; nY++ )
1362 : {
1363 0 : aSubRect.Top() = aSubRect.Bottom() = nY;
1364 :
1365 0 : for( long nX = nLeft; nX <= nRight; )
1366 : {
1367 0 : while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixel( nY, nX ) ) )
1368 0 : nX++;
1369 :
1370 0 : if( nX <= nRight )
1371 : {
1372 0 : aSubRect.Left() = nX;
1373 :
1374 0 : while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixel( nY, nX ) ) )
1375 0 : nX++;
1376 :
1377 0 : aSubRect.Right() = nX - 1L;
1378 0 : aRegion.ImplAddRect( aSubRect );
1379 : }
1380 : }
1381 : }
1382 :
1383 0 : aRegion.ImplEndAddRect();
1384 0 : ( (Bitmap*) this )->ReleaseAccess( pReadAcc );
1385 : }
1386 : else
1387 0 : aRegion = aRect;
1388 :
1389 0 : return aRegion;
1390 : }
1391 :
1392 : // ------------------------------------------------------------------
1393 :
1394 0 : sal_Bool Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
1395 : {
1396 0 : BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
1397 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
1398 0 : sal_Bool bRet = sal_False;
1399 :
1400 0 : if( pMaskAcc && pAcc )
1401 : {
1402 0 : const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
1403 0 : const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
1404 0 : const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1405 0 : BitmapColor aReplace;
1406 :
1407 0 : if( pAcc->HasPalette() )
1408 : {
1409 0 : const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount();
1410 0 : const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount();
1411 :
1412 : // erst einmal naechste Farbe nehmen
1413 0 : aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
1414 :
1415 : // falls Palettenbild, und die zu setzende Farbe ist nicht
1416 : // in der Palette, suchen wir nach freien Eintraegen (teuer)
1417 0 : if( pAcc->GetPaletteColor( (sal_uInt8) aReplace ) != BitmapColor( rReplaceColor ) )
1418 : {
1419 : // erst einmal nachsehen, ob wir unsere ReplaceColor
1420 : // nicht auf einen freien Platz am Ende der Palette
1421 : // setzen koennen
1422 0 : if( nActColors < nMaxColors )
1423 : {
1424 0 : pAcc->SetPaletteEntryCount( nActColors + 1 );
1425 0 : pAcc->SetPaletteColor( nActColors, rReplaceColor );
1426 0 : aReplace = BitmapColor( (sal_uInt8) nActColors );
1427 : }
1428 : else
1429 : {
1430 0 : sal_Bool* pFlags = new sal_Bool[ nMaxColors ];
1431 :
1432 : // alle Eintraege auf 0 setzen
1433 0 : memset( pFlags, 0, nMaxColors );
1434 :
1435 0 : for( long nY = 0L; nY < nHeight; nY++ )
1436 0 : for( long nX = 0L; nX < nWidth; nX++ )
1437 0 : pFlags[ (sal_uInt8) pAcc->GetPixel( nY, nX ) ] = sal_True;
1438 :
1439 0 : for( sal_uInt16 i = 0UL; i < nMaxColors; i++ )
1440 : {
1441 : // Hurra, wir haben einen unbenutzten Eintrag
1442 0 : if( !pFlags[ i ] )
1443 : {
1444 0 : pAcc->SetPaletteColor( (sal_uInt16) i, rReplaceColor );
1445 0 : aReplace = BitmapColor( (sal_uInt8) i );
1446 : }
1447 : }
1448 :
1449 0 : delete[] pFlags;
1450 : }
1451 : }
1452 : }
1453 : else
1454 0 : aReplace = rReplaceColor;
1455 :
1456 0 : for( long nY = 0L; nY < nHeight; nY++ )
1457 0 : for( long nX = 0L; nX < nWidth; nX++ )
1458 0 : if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
1459 0 : pAcc->SetPixel( nY, nX, aReplace );
1460 :
1461 0 : bRet = sal_True;
1462 : }
1463 :
1464 0 : ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
1465 0 : ReleaseAccess( pAcc );
1466 :
1467 0 : return bRet;
1468 : }
1469 :
1470 : // ------------------------------------------------------------------
1471 :
1472 0 : sal_Bool Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
1473 : {
1474 0 : Bitmap aNewBmp( GetSizePixel(), 24 );
1475 0 : BitmapReadAccess* pAcc = AcquireReadAccess();
1476 0 : BitmapReadAccess* pAlphaAcc = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
1477 0 : BitmapWriteAccess* pNewAcc = aNewBmp.AcquireWriteAccess();
1478 0 : sal_Bool bRet = sal_False;
1479 :
1480 0 : if( pAcc && pAlphaAcc && pNewAcc )
1481 : {
1482 0 : BitmapColor aCol;
1483 0 : const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
1484 0 : const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
1485 :
1486 0 : for( long nY = 0L; nY < nHeight; nY++ )
1487 : {
1488 0 : for( long nX = 0L; nX < nWidth; nX++ )
1489 : {
1490 0 : aCol = pAcc->GetColor( nY, nX );
1491 0 : pNewAcc->SetPixel( nY, nX, aCol.Merge( rMergeColor, 255 - (sal_uInt8) pAlphaAcc->GetPixel( nY, nX ) ) );
1492 : }
1493 : }
1494 :
1495 0 : bRet = sal_True;
1496 : }
1497 :
1498 0 : ReleaseAccess( pAcc );
1499 0 : ( (AlphaMask&) rAlpha ).ReleaseAccess( pAlphaAcc );
1500 0 : aNewBmp.ReleaseAccess( pNewAcc );
1501 :
1502 0 : if( bRet )
1503 : {
1504 0 : const MapMode aMap( maPrefMapMode );
1505 0 : const Size aSize( maPrefSize );
1506 :
1507 0 : *this = aNewBmp;
1508 :
1509 0 : maPrefMapMode = aMap;
1510 0 : maPrefSize = aSize;
1511 : }
1512 :
1513 0 : return bRet;
1514 : }
1515 :
1516 : // ------------------------------------------------------------------
1517 :
1518 0 : sal_Bool Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
1519 : {
1520 : // Bitmaps with 1 bit color depth can cause problems
1521 : // if they have other entries than black/white in their palette
1522 0 : if( 1 == GetBitCount() )
1523 0 : Convert( BMP_CONVERSION_4BIT_COLORS );
1524 :
1525 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
1526 0 : sal_Bool bRet = sal_False;
1527 :
1528 0 : if( pAcc )
1529 : {
1530 0 : const long nMinR = MinMax( (long) rSearchColor.GetRed() - nTol, 0, 255 );
1531 0 : const long nMaxR = MinMax( (long) rSearchColor.GetRed() + nTol, 0, 255 );
1532 0 : const long nMinG = MinMax( (long) rSearchColor.GetGreen() - nTol, 0, 255 );
1533 0 : const long nMaxG = MinMax( (long) rSearchColor.GetGreen() + nTol, 0, 255 );
1534 0 : const long nMinB = MinMax( (long) rSearchColor.GetBlue() - nTol, 0, 255 );
1535 0 : const long nMaxB = MinMax( (long) rSearchColor.GetBlue() + nTol, 0, 255 );
1536 :
1537 0 : if( pAcc->HasPalette() )
1538 : {
1539 0 : for( sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
1540 : {
1541 0 : const BitmapColor& rCol = pAcc->GetPaletteColor( i );
1542 :
1543 0 : if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
1544 0 : nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
1545 0 : nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
1546 : {
1547 0 : pAcc->SetPaletteColor( i, rReplaceColor );
1548 : }
1549 : }
1550 : }
1551 : else
1552 : {
1553 0 : BitmapColor aCol;
1554 0 : const BitmapColor aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
1555 :
1556 0 : for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
1557 : {
1558 0 : for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
1559 : {
1560 0 : aCol = pAcc->GetPixel( nY, nX );
1561 :
1562 0 : if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
1563 0 : nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
1564 0 : nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
1565 : {
1566 0 : pAcc->SetPixel( nY, nX, aReplace );
1567 : }
1568 : }
1569 0 : }
1570 : }
1571 :
1572 0 : ReleaseAccess( pAcc );
1573 0 : bRet = sal_True;
1574 : }
1575 :
1576 0 : return bRet;
1577 : }
1578 :
1579 : // ------------------------------------------------------------------
1580 :
1581 0 : sal_Bool Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
1582 : sal_uLong nColorCount, sal_uLong* _pTols )
1583 : {
1584 : // Bitmaps with 1 bit color depth can cause problems
1585 : // if they have other entries than black/white in their palette
1586 0 : if( 1 == GetBitCount() )
1587 0 : Convert( BMP_CONVERSION_4BIT_COLORS );
1588 :
1589 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
1590 0 : sal_Bool bRet = sal_False;
1591 :
1592 0 : if( pAcc )
1593 : {
1594 0 : long* pMinR = new long[ nColorCount ];
1595 0 : long* pMaxR = new long[ nColorCount ];
1596 0 : long* pMinG = new long[ nColorCount ];
1597 0 : long* pMaxG = new long[ nColorCount ];
1598 0 : long* pMinB = new long[ nColorCount ];
1599 0 : long* pMaxB = new long[ nColorCount ];
1600 : long* pTols;
1601 : sal_uLong i;
1602 :
1603 0 : if( !_pTols )
1604 : {
1605 0 : pTols = new long[ nColorCount ];
1606 0 : memset( pTols, 0, nColorCount * sizeof( long ) );
1607 : }
1608 : else
1609 0 : pTols = (long*) _pTols;
1610 :
1611 0 : for( i = 0UL; i < nColorCount; i++ )
1612 : {
1613 0 : const Color& rCol = pSearchColors[ i ];
1614 0 : const long nTol = pTols[ i ];
1615 :
1616 0 : pMinR[ i ] = MinMax( (long) rCol.GetRed() - nTol, 0, 255 );
1617 0 : pMaxR[ i ] = MinMax( (long) rCol.GetRed() + nTol, 0, 255 );
1618 0 : pMinG[ i ] = MinMax( (long) rCol.GetGreen() - nTol, 0, 255 );
1619 0 : pMaxG[ i ] = MinMax( (long) rCol.GetGreen() + nTol, 0, 255 );
1620 0 : pMinB[ i ] = MinMax( (long) rCol.GetBlue() - nTol, 0, 255 );
1621 0 : pMaxB[ i ] = MinMax( (long) rCol.GetBlue() + nTol, 0, 255 );
1622 : }
1623 :
1624 0 : if( pAcc->HasPalette() )
1625 : {
1626 0 : for( sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
1627 : {
1628 0 : const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
1629 :
1630 0 : for( i = 0UL; i < nColorCount; i++ )
1631 : {
1632 0 : if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
1633 0 : pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
1634 0 : pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
1635 : {
1636 0 : pAcc->SetPaletteColor( (sal_uInt16)nEntry, pReplaceColors[ i ] );
1637 0 : break;
1638 : }
1639 : }
1640 : }
1641 : }
1642 : else
1643 : {
1644 0 : BitmapColor aCol;
1645 0 : BitmapColor* pReplaces = new BitmapColor[ nColorCount ];
1646 :
1647 0 : for( i = 0UL; i < nColorCount; i++ )
1648 0 : pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
1649 :
1650 0 : for( long nY = 0L, nHeight = pAcc->Height(); nY < nHeight; nY++ )
1651 : {
1652 0 : for( long nX = 0L, nWidth = pAcc->Width(); nX < nWidth; nX++ )
1653 : {
1654 0 : aCol = pAcc->GetPixel( nY, nX );
1655 :
1656 0 : for( i = 0UL; i < nColorCount; i++ )
1657 : {
1658 0 : if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
1659 0 : pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
1660 0 : pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
1661 : {
1662 0 : pAcc->SetPixel( nY, nX, pReplaces[ i ] );
1663 0 : break;
1664 : }
1665 : }
1666 : }
1667 : }
1668 :
1669 0 : delete[] pReplaces;
1670 : }
1671 :
1672 0 : if( !_pTols )
1673 0 : delete[] pTols;
1674 :
1675 0 : delete[] pMinR;
1676 0 : delete[] pMaxR;
1677 0 : delete[] pMinG;
1678 0 : delete[] pMaxG;
1679 0 : delete[] pMinB;
1680 0 : delete[] pMaxB;
1681 0 : ReleaseAccess( pAcc );
1682 0 : bRet = sal_True;
1683 : }
1684 :
1685 0 : return bRet;
1686 : }
1687 :
1688 : // ------------------------------------------------------------------
1689 :
1690 6 : Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
1691 : {
1692 6 : Bitmap aDispBmp( *this );
1693 :
1694 6 : if( mpImpBmp && ( pDisplay->mpGraphics || pDisplay->ImplGetGraphics() ) )
1695 : {
1696 6 : ImpBitmap* pImpDispBmp = new ImpBitmap;
1697 :
1698 6 : if( pImpDispBmp->ImplCreate( *mpImpBmp, pDisplay->mpGraphics ) )
1699 0 : aDispBmp.ImplSetImpBitmap( pImpDispBmp );
1700 : else
1701 6 : delete pImpDispBmp;
1702 : }
1703 :
1704 6 : return aDispBmp;
1705 : }
1706 :
1707 : // ------------------------------------------------------------------
1708 :
1709 0 : sal_Bool Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
1710 : {
1711 0 : BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
1712 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
1713 0 : sal_Bool bRet = sal_False;
1714 :
1715 0 : if( pMaskAcc && pAcc )
1716 : {
1717 0 : const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
1718 0 : const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
1719 0 : const Color aColBlack( COL_BLACK );
1720 0 : BitmapColor aPixel;
1721 0 : BitmapColor aMaskPixel;
1722 0 : const BitmapColor aWhite( pAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
1723 0 : const BitmapColor aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
1724 0 : const BitmapColor aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
1725 :
1726 0 : switch( eCombine )
1727 : {
1728 : case( BMP_COMBINE_COPY ):
1729 : {
1730 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1731 : {
1732 0 : if( pMaskAcc->GetPixel( nY, nX ) == aMaskBlack )
1733 0 : pAcc->SetPixel( nY, nX, aBlack );
1734 : else
1735 0 : pAcc->SetPixel( nY, nX, aWhite );
1736 : }
1737 : }
1738 0 : break;
1739 :
1740 : case( BMP_COMBINE_INVERT ):
1741 : {
1742 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1743 : {
1744 0 : if( pAcc->GetPixel( nY, nX ) == aBlack )
1745 0 : pAcc->SetPixel( nY, nX, aWhite );
1746 : else
1747 0 : pAcc->SetPixel( nY, nX, aBlack );
1748 : }
1749 : }
1750 0 : break;
1751 :
1752 : case( BMP_COMBINE_AND ):
1753 : {
1754 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1755 : {
1756 0 : if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
1757 0 : pAcc->SetPixel( nY, nX, aWhite );
1758 : else
1759 0 : pAcc->SetPixel( nY, nX, aBlack );
1760 : }
1761 : }
1762 0 : break;
1763 :
1764 : case( BMP_COMBINE_NAND ):
1765 : {
1766 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1767 : {
1768 0 : if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack && pAcc->GetPixel( nY, nX ) != aBlack )
1769 0 : pAcc->SetPixel( nY, nX, aBlack );
1770 : else
1771 0 : pAcc->SetPixel( nY, nX, aWhite );
1772 : }
1773 : }
1774 0 : break;
1775 :
1776 : case( BMP_COMBINE_OR ):
1777 : {
1778 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1779 : {
1780 0 : if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
1781 0 : pAcc->SetPixel( nY, nX, aWhite );
1782 : else
1783 0 : pAcc->SetPixel( nY, nX, aBlack );
1784 : }
1785 : }
1786 0 : break;
1787 :
1788 : case( BMP_COMBINE_NOR ):
1789 : {
1790 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1791 : {
1792 0 : if( pMaskAcc->GetPixel( nY, nX ) != aMaskBlack || pAcc->GetPixel( nY, nX ) != aBlack )
1793 0 : pAcc->SetPixel( nY, nX, aBlack );
1794 : else
1795 0 : pAcc->SetPixel( nY, nX, aWhite );
1796 : }
1797 : }
1798 0 : break;
1799 :
1800 : case( BMP_COMBINE_XOR ):
1801 : {
1802 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1803 : {
1804 0 : aPixel = pAcc->GetPixel( nY, nX );
1805 0 : aMaskPixel = pMaskAcc->GetPixel( nY, nX );
1806 :
1807 0 : if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
1808 0 : ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
1809 : {
1810 0 : pAcc->SetPixel( nY, nX, aWhite );
1811 : }
1812 : else
1813 0 : pAcc->SetPixel( nY, nX, aBlack );
1814 : }
1815 : }
1816 0 : break;
1817 :
1818 : case( BMP_COMBINE_NXOR ):
1819 : {
1820 0 : for( long nY = 0L; nY < nHeight; nY++ ) for( long nX = 0L; nX < nWidth; nX++ )
1821 : {
1822 0 : aPixel = pAcc->GetPixel( nY, nX );
1823 0 : aMaskPixel = pMaskAcc->GetPixel( nY, nX );
1824 :
1825 0 : if( ( aMaskPixel != aMaskBlack && aPixel == aBlack ) ||
1826 0 : ( aMaskPixel == aMaskBlack && aPixel != aBlack ) )
1827 : {
1828 0 : pAcc->SetPixel( nY, nX, aBlack );
1829 : }
1830 : else
1831 0 : pAcc->SetPixel( nY, nX, aWhite );
1832 : }
1833 : }
1834 0 : break;
1835 : }
1836 :
1837 0 : bRet = sal_True;
1838 : }
1839 :
1840 0 : ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
1841 0 : ReleaseAccess( pAcc );
1842 :
1843 0 : return bRet;
1844 : }
1845 :
1846 : // ------------------------------------------------------------------
1847 :
1848 0 : sal_Bool Bitmap::Blend( const AlphaMask& rAlpha, const Color& rBackgroundColor )
1849 : {
1850 : // TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
1851 : // optimizations. Might even consolidate the code here and there.
1852 :
1853 : // convert to a truecolor bitmap, if we're a paletted one. There's
1854 : // room for tradeoff decision here, maybe later for an overload (or a flag)
1855 0 : if( GetBitCount() <= 8 )
1856 0 : Convert( BMP_CONVERSION_24BIT );
1857 :
1858 0 : BitmapReadAccess* pAlphaAcc = const_cast<AlphaMask&>(rAlpha).AcquireReadAccess();
1859 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
1860 0 : sal_Bool bRet = sal_False;
1861 :
1862 0 : if( pAlphaAcc && pAcc )
1863 : {
1864 0 : const long nWidth = Min( pAlphaAcc->Width(), pAcc->Width() );
1865 0 : const long nHeight = Min( pAlphaAcc->Height(), pAcc->Height() );
1866 :
1867 0 : for( long nY = 0L; nY < nHeight; ++nY )
1868 0 : for( long nX = 0L; nX < nWidth; ++nX )
1869 : pAcc->SetPixel( nY, nX,
1870 : pAcc->GetPixel( nY, nX ).Merge( rBackgroundColor,
1871 0 : 255 - pAlphaAcc->GetPixel( nY, nX ) ) );
1872 :
1873 0 : bRet = sal_True;
1874 : }
1875 :
1876 0 : const_cast<AlphaMask&>(rAlpha).ReleaseAccess( pAlphaAcc );
1877 0 : ReleaseAccess( pAcc );
1878 :
1879 0 : return bRet;
1880 : }
1881 :
1882 : // ------------------------------------------------------------------
1883 :
1884 0 : sal_Bool Bitmap::MakeMono( sal_uInt8 cThreshold )
1885 : {
1886 0 : return ImplMakeMono( cThreshold );
1887 : }
1888 :
1889 : // ------------------------------------------------------------------
1890 :
1891 0 : bool Bitmap::GetSystemData( BitmapSystemData& rData ) const
1892 : {
1893 0 : bool bRet = false;
1894 0 : if( mpImpBmp )
1895 : {
1896 0 : SalBitmap* pSalBitmap = mpImpBmp->ImplGetSalBitmap();
1897 0 : if( pSalBitmap )
1898 0 : bRet = pSalBitmap->GetSystemData( rData );
1899 : }
1900 :
1901 0 : return bRet;
1902 : }
1903 :
1904 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|