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