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