1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: imgcons.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <tools/stream.hxx>
35 #include <vcl/bmpacc.hxx>
36 #include <vcl/bitmapex.hxx>
37 #include <vcl/image.hxx>
38 #include <vcl/imgcons.hxx>
40 // -------------------
41 // - ImplColorMapper -
42 // -------------------
56 ULONG
ImplCalcMaskShift( ULONG nVal
);
60 ImplColorMapper( ULONG nRMask
, ULONG nGMask
, ULONG nBMask
, ULONG nTMask
);
63 const Color
& ImplGetColor( ULONG nColor
)
65 maCol
.SetRed( (UINT8
) ( ( nColor
& mnR
) >> mnRShift
) );
66 maCol
.SetGreen( (UINT8
) ( ( nColor
& mnG
) >> mnGShift
) );
67 maCol
.SetBlue( (UINT8
) ( ( nColor
& mnB
) >> mnBShift
) );
68 maCol
.SetTransparency( (UINT8
) ( ( nColor
& mnT
) >> mnTShift
) );
73 // -----------------------------------------------------------------------------
75 ImplColorMapper::ImplColorMapper( ULONG nRMask
, ULONG nGMask
, ULONG nBMask
, ULONG nTMask
) :
81 mnRShift
= ImplCalcMaskShift( mnR
);
82 mnGShift
= ImplCalcMaskShift( mnG
);
83 mnBShift
= ImplCalcMaskShift( mnB
);
84 mnTShift
= ImplCalcMaskShift( mnT
);
87 // -----------------------------------------------------------------------------
89 ImplColorMapper::~ImplColorMapper()
93 // -----------------------------------------------------------------------------
95 ULONG
ImplColorMapper::ImplCalcMaskShift( ULONG nVal
)
97 DBG_ASSERT( nVal
> 0, "Mask has no value!" );
101 for( ULONG i
= 0UL; i
< 32; i
++ )
103 if( nVal
& ( 1UL << i
) )
117 ImageConsumer::ImageConsumer() :
125 // -----------------------------------------------------------------------------
127 ImageConsumer::~ImageConsumer()
133 // -----------------------------------------------------------------------------
135 void ImageConsumer::Init( sal_uInt32 nWidth
, sal_uInt32 nHeight
)
137 maSize
= Size( nWidth
, nHeight
);
138 maBitmap
= maMask
= Bitmap();
143 // -----------------------------------------------------------------------------
145 void ImageConsumer::SetColorModel( USHORT nBitCount
,
146 sal_uInt32 nPalEntries
, const sal_uInt32
* pRGBAPal
,
147 sal_uInt32 nRMask
, sal_uInt32 nGMask
, sal_uInt32 nBMask
, sal_uInt32 nAMask
)
149 DBG_ASSERT( maSize
.Width() && maSize
.Height(), "Missing call to ImageConsumer::Init(...)!" );
151 BitmapPalette
aPal( Min( (USHORT
) nPalEntries
, (USHORT
) 256 ) );
156 const sal_Int32
* pTmp
= (sal_Int32
*) pRGBAPal
;
162 mpPal
= new Color
[ nPalEntries
];
164 for( ULONG i
= 0; i
< nPalEntries
; i
++, pTmp
++ )
166 Color
& rCol
= mpPal
[ i
];
169 cVal
= (BYTE
) ( ( *pTmp
& 0xff000000UL
) >> 24L );
172 if( i
< (ULONG
) aPal
.GetEntryCount() )
173 aPal
[ (USHORT
) i
].SetRed( cVal
);
175 cVal
= (BYTE
) ( ( *pTmp
& 0x00ff0000UL
) >> 16L );
176 rCol
.SetGreen( cVal
);
178 if( i
< (ULONG
) aPal
.GetEntryCount() )
179 aPal
[ (USHORT
) i
].SetGreen( cVal
);
181 cVal
= (BYTE
) ( ( *pTmp
& 0x0000ff00UL
) >> 8L );
182 rCol
.SetBlue( cVal
);
184 if( i
< (ULONG
) aPal
.GetEntryCount() )
185 aPal
[ (USHORT
) i
].SetBlue( cVal
);
187 rCol
.SetTransparency( (BYTE
) ( ( *pTmp
& 0x000000ffL
) ) );
192 else if( nBitCount
<= 4 )
194 else if( nBitCount
<= 8 )
202 mpMapper
= new ImplColorMapper( nRMask
, nGMask
, nBMask
, nAMask
);
213 maBitmap
= Bitmap( maSize
, nBitCount
, &aPal
);
214 maMask
= Bitmap( maSize
, 1 );
215 maMask
.Erase( COL_BLACK
);
220 // -----------------------------------------------------------------------------
222 void ImageConsumer::SetPixelsByBytes( sal_uInt32 nConsX
, sal_uInt32 nConsY
,
223 sal_uInt32 nConsWidth
, sal_uInt32 nConsHeight
,
224 const BYTE
* pData
, sal_uInt32 nOffset
, sal_uInt32 nScanSize
)
226 DBG_ASSERT( !!maBitmap
&& !!maMask
, "Missing call to ImageConsumer::SetColorModel(...)!" );
228 BitmapWriteAccess
* pBmpAcc
= maBitmap
.AcquireWriteAccess();
229 BitmapWriteAccess
* pMskAcc
= maMask
.AcquireWriteAccess();
230 sal_Bool bDataChanged
= sal_False
;
232 if( pBmpAcc
&& pMskAcc
)
234 const long nWidth
= pBmpAcc
->Width();
235 const long nHeight
= pBmpAcc
->Height();
237 maChangedRect
= Rectangle( Point(), Size( nWidth
, nHeight
) );
238 maChangedRect
.Intersection( Rectangle( Point( nConsX
, nConsY
), Size( nConsWidth
, nConsHeight
) ) );
240 if( !maChangedRect
.IsEmpty() )
242 const long nStartX
= maChangedRect
.Left();
243 const long nEndX
= maChangedRect
.Right();
244 const long nStartY
= maChangedRect
.Top();
245 const long nEndY
= maChangedRect
.Bottom();
247 if( mpMapper
&& ( pBmpAcc
->GetBitCount() > 8 ) )
250 BitmapColor
aMskWhite( pMskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
252 for( long nY
= nStartY
; nY
<= nEndY
; nY
++ )
254 const BYTE
* pTmp
= pData
+ ( nY
- nStartY
) * nScanSize
+ nOffset
;
256 for( long nX
= nStartX
; nX
<= nEndX
; nX
++ )
258 const Color
& rCol
= mpMapper
->ImplGetColor( *pTmp
++ );
260 // 0: Transparent; >0: Non-Transparent
261 if( !rCol
.GetTransparency() )
263 pMskAcc
->SetPixel( nY
, nX
, aMskWhite
);
268 aCol
.SetRed( rCol
.GetRed() );
269 aCol
.SetGreen( rCol
.GetGreen() );
270 aCol
.SetBlue( rCol
.GetBlue() );
271 pBmpAcc
->SetPixel( nY
, nX
, aCol
);
276 bDataChanged
= sal_True
;
278 else if( mpPal
&& ( pBmpAcc
->GetBitCount() <= 8 ) )
280 BitmapColor
aIndex( (BYTE
) 0 );
281 BitmapColor
aMskWhite( pMskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
283 for( long nY
= nStartY
; nY
<= nEndY
; nY
++ )
285 const BYTE
* pTmp
= pData
+ ( nY
- nStartY
) * nScanSize
+ nOffset
;
287 for( long nX
= nStartX
; nX
<= nEndX
; nX
++ )
289 const BYTE cIndex
= *pTmp
++;
290 const Color
& rCol
= mpPal
[ cIndex
];
292 // 0: Transparent; >0: Non-Transparent
293 if( !rCol
.GetTransparency() )
295 pMskAcc
->SetPixel( nY
, nX
, aMskWhite
);
300 aIndex
.SetIndex( cIndex
);
301 pBmpAcc
->SetPixel( nY
, nX
, aIndex
);
306 bDataChanged
= sal_True
;
308 else if( mpPal
&& ( pBmpAcc
->GetBitCount() > 8 ) )
311 BitmapColor
aMskWhite( pMskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
313 for( long nY
= nStartY
; nY
<= nEndY
; nY
++ )
315 const BYTE
* pTmp
= pData
+ ( nY
- nStartY
) * nScanSize
+ nOffset
;
317 for( long nX
= nStartX
; nX
<= nEndX
; nX
++ )
319 const BYTE cIndex
= *pTmp
++;
320 const Color
& rCol
= mpPal
[ cIndex
];
322 // 0: Transparent; >0: Non-Transparent
323 if( !rCol
.GetTransparency() )
325 pMskAcc
->SetPixel( nY
, nX
, aMskWhite
);
330 aCol
.SetRed( rCol
.GetRed() );
331 aCol
.SetGreen( rCol
.GetGreen() );
332 aCol
.SetBlue( rCol
.GetBlue() );
333 pBmpAcc
->SetPixel( nY
, nX
, aCol
);
338 bDataChanged
= sal_True
;
342 DBG_ERROR( "Producer format error!" );
343 maChangedRect
.SetEmpty();
348 maChangedRect
.SetEmpty();
350 maBitmap
.ReleaseAccess( pBmpAcc
);
351 maMask
.ReleaseAccess( pMskAcc
);
357 // -----------------------------------------------------------------------------
359 void ImageConsumer::SetPixelsByLongs( sal_uInt32 nConsX
, sal_uInt32 nConsY
,
360 sal_uInt32 nConsWidth
, sal_uInt32 nConsHeight
,
361 const sal_uInt32
* pData
, sal_uInt32 nOffset
, sal_uInt32 nScanSize
)
363 DBG_ASSERT( !!maBitmap
&& !!maMask
, "Missing call to ImageConsumer::SetColorModel(...)!" );
365 BitmapWriteAccess
* pBmpAcc
= maBitmap
.AcquireWriteAccess();
366 BitmapWriteAccess
* pMskAcc
= maMask
.AcquireWriteAccess();
367 sal_Bool bDataChanged
= sal_False
;
369 if( pBmpAcc
&& pMskAcc
)
371 const long nWidth
= pBmpAcc
->Width();
372 const long nHeight
= pBmpAcc
->Height();
374 maChangedRect
= Rectangle( Point(), Size( nWidth
, nHeight
) );
375 maChangedRect
.Intersection( Rectangle( Point( nConsX
, nConsY
), Size( nConsWidth
, nConsHeight
) ) );
377 if( !maChangedRect
.IsEmpty() )
379 const long nStartX
= maChangedRect
.Left();
380 const long nEndX
= maChangedRect
.Right();
381 const long nStartY
= maChangedRect
.Top();
382 const long nEndY
= maChangedRect
.Bottom();
384 if( mpMapper
&& ( pBmpAcc
->GetBitCount() > 8 ) )
387 BitmapColor
aMskWhite( pMskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
389 for( long nY
= nStartY
; nY
<= nEndY
; nY
++ )
391 const sal_Int32
* pTmp
= (sal_Int32
*) pData
+ ( nY
- nStartY
) * nScanSize
+ nOffset
;
393 for( long nX
= nStartX
; nX
<= nEndX
; nX
++ )
395 const Color
& rCol
= mpMapper
->ImplGetColor( *pTmp
++ );
397 // 0: Transparent; >0: Non-Transparent
398 if( !rCol
.GetTransparency() )
400 pMskAcc
->SetPixel( nY
, nX
, aMskWhite
);
405 aCol
.SetRed( rCol
.GetRed() );
406 aCol
.SetGreen( rCol
.GetGreen() );
407 aCol
.SetBlue( rCol
.GetBlue() );
408 pBmpAcc
->SetPixel( nY
, nX
, aCol
);
413 bDataChanged
= sal_True
;
415 else if( mpPal
&& ( pBmpAcc
->GetBitCount() <= 8 ) )
417 BitmapColor
aIndex( (BYTE
) 0 );
418 BitmapColor
aMskWhite( pMskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
420 for( long nY
= nStartY
; nY
<= nEndY
; nY
++ )
422 const sal_Int32
* pTmp
= (sal_Int32
*) pData
+ ( nY
- nStartY
) * nScanSize
+ nOffset
;
424 for( long nX
= nStartX
; nX
<= nEndX
; nX
++ )
426 const sal_Int32 nIndex
= *pTmp
++;
427 const Color
& rCol
= mpPal
[ nIndex
];
429 // 0: Transparent; >0: Non-Transparent
430 if( !rCol
.GetTransparency() )
432 pMskAcc
->SetPixel( nY
, nX
, aMskWhite
);
437 aIndex
.SetIndex( (BYTE
) nIndex
);
438 pBmpAcc
->SetPixel( nY
, nX
, aIndex
);
443 bDataChanged
= sal_True
;
445 else if( mpPal
&& ( pBmpAcc
->GetBitCount() > 8 ) )
448 BitmapColor
aMskWhite( pMskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
450 for( long nY
= nStartY
; nY
<= nEndY
; nY
++ )
452 const sal_Int32
* pTmp
= (sal_Int32
*) pData
+ ( nY
- nStartY
) * nScanSize
+ nOffset
;
454 for( long nX
= nStartX
; nX
<= nEndX
; nX
++ )
456 const sal_Int32 nIndex
= *pTmp
++;
457 const Color
& rCol
= mpPal
[ nIndex
];
459 // 0: Transparent; >0: Non-Transparent
460 if( !rCol
.GetTransparency() )
462 pMskAcc
->SetPixel( nY
, nX
, aMskWhite
);
467 aCol
.SetRed( rCol
.GetRed() );
468 aCol
.SetGreen( rCol
.GetGreen() );
469 aCol
.SetBlue( rCol
.GetBlue() );
470 pBmpAcc
->SetPixel( nY
, nX
, aCol
);
475 bDataChanged
= sal_True
;
479 DBG_ERROR( "Producer format error!" );
480 maChangedRect
.SetEmpty();
485 maChangedRect
.SetEmpty();
487 maBitmap
.ReleaseAccess( pBmpAcc
);
488 maMask
.ReleaseAccess( pMskAcc
);
494 // -----------------------------------------------------------------------------
496 void ImageConsumer::Completed( sal_uInt32 nStatus
/*, ImageProducer& rProducer */ )
507 case( SINGLEFRAMEDONE
):
508 case( STATICIMAGEDONE
):
516 case( IMAGEABORTED
):
517 maBitmap
= maMask
= Bitmap();
524 // rProducer.RemoveConsumer( *this );
526 if( maDoneLink
.IsSet() )
527 maDoneLink
.Call( this );
530 // -----------------------------------------------------------------------------
532 void ImageConsumer::DataChanged()
534 if( maChgLink
.IsSet() )
535 maChgLink
.Call( this );
538 // -----------------------------------------------------------------------------
540 sal_uInt32
ImageConsumer::GetStatus() const
545 // -----------------------------------------------------------------------------
547 BOOL
ImageConsumer::GetData( BitmapEx
& rBmpEx
) const
549 const BOOL bRet
= ( SINGLEFRAMEDONE
== mnStatus
|| STATICIMAGEDONE
== mnStatus
);
554 rBmpEx
= BitmapEx( maBitmap
, maMask
);
556 rBmpEx
= BitmapEx( maBitmap
);
562 // -----------------------------------------------------------------------------
564 BOOL
ImageConsumer::GetData( Image
& rImage
) const
566 const BOOL bRet
= ( SINGLEFRAMEDONE
== mnStatus
|| STATICIMAGEDONE
== mnStatus
);
571 rImage
= Image( maBitmap
, maMask
);
573 rImage
= Image( maBitmap
);