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