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