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: impimage.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"
33 #include <vcl/outdev.hxx>
34 #include <vcl/bitmapex.hxx>
35 #include <vcl/alpha.hxx>
36 #include <vcl/window.hxx>
37 #include <vcl/bmpacc.hxx>
38 #include <vcl/virdev.hxx>
39 #include <vcl/image.h>
40 #include <vcl/image.hxx>
46 #define IMPSYSIMAGEITEM_MASK ( 0x01 )
47 #define IMPSYSIMAGEITEM_ALPHA ( 0x02 )
48 #define DISA_ALL ( 0xffff )
54 ImageAryData::ImageAryData() :
61 // -----------------------------------------------------------------------
63 ImageAryData::ImageAryData( const ImageAryData
& rData
) :
64 maName( rData
.maName
),
66 maBitmapEx( rData
.maBitmapEx
)
70 ImageAryData::ImageAryData( const rtl::OUString
&aName
,
71 USHORT nId
, const BitmapEx
&aBitmap
)
72 : maName( aName
), mnId( nId
), maBitmapEx( aBitmap
)
76 // -----------------------------------------------------------------------
78 ImageAryData::~ImageAryData()
82 // -----------------------------------------------------------------------
84 ImageAryData
& ImageAryData::operator=( const ImageAryData
& rData
)
86 maName
= rData
.maName
;
88 maBitmapEx
= rData
.maBitmapEx
;
97 ImplImageList::ImplImageList()
101 ImplImageList::ImplImageList( const ImplImageList
&aSrc
) :
102 maPrefix( aSrc
.maPrefix
),
103 maImageSize( aSrc
.maImageSize
),
106 maImages
.reserve( aSrc
.maImages
.size() );
107 for ( ImageAryDataVec::const_iterator aIt
= aSrc
.maImages
.begin(), aEnd
= aSrc
.maImages
.end(); aIt
!= aEnd
; ++aIt
)
109 ImageAryData
* pAryData
= new ImageAryData( **aIt
);
110 maImages
.push_back( pAryData
);
111 if( pAryData
->maName
.getLength() )
112 maNameHash
[ pAryData
->maName
] = pAryData
;
116 ImplImageList::~ImplImageList()
118 for ( ImageAryDataVec::iterator aIt
= maImages
.begin(), aEnd
= maImages
.end(); aIt
!= aEnd
; ++aIt
)
122 void ImplImageList::AddImage( const ::rtl::OUString
&aName
,
123 USHORT nId
, const BitmapEx
&aBitmapEx
)
125 ImageAryData
*pImg
= new ImageAryData( aName
, nId
, aBitmapEx
);
126 maImages
.push_back( pImg
);
127 if( aName
.getLength() )
128 maNameHash
[ aName
] = pImg
;
131 void ImplImageList::RemoveImage( USHORT nPos
)
133 ImageAryData
*pImg
= maImages
[ nPos
];
134 if( pImg
->maName
.getLength() )
135 maNameHash
.erase( pImg
->maName
);
136 maImages
.erase( maImages
.begin() + nPos
);
139 USHORT
ImplImageList::GetImageCount() const
141 return sal::static_int_cast
< USHORT
>( maImages
.size() );
148 ImplImageData::ImplImageData( const BitmapEx
& rBmpEx
) :
149 mpImageBitmap( NULL
),
154 // -----------------------------------------------------------------------
156 ImplImageData::~ImplImageData()
158 delete mpImageBitmap
;
165 BOOL
ImplImageData::IsEqual( const ImplImageData
& rData
)
167 return( maBmpEx
== rData
.maBmpEx
);
174 ImplImage::ImplImage()
178 // ------------------------------------------------------------------------------
180 ImplImage::~ImplImage()
184 case IMAGETYPE_BITMAP
:
185 delete static_cast< Bitmap
* >( mpData
);
188 case IMAGETYPE_IMAGE
:
189 delete static_cast< ImplImageData
* >( mpData
);
198 ImplImageBmp::ImplImageBmp() :
199 mpDisplayBmp( NULL
),
209 ImplImageBmp::~ImplImageBmp()
215 // -----------------------------------------------------------------------
217 void ImplImageBmp::Create( long nItemWidth
, long nItemHeight
, USHORT nInitSize
)
219 const Size
aTotalSize( nInitSize
* nItemWidth
, nItemHeight
);
221 maBmpEx
= Bitmap( aTotalSize
, 24 );
222 maDisabledBmpEx
.SetEmpty();
227 maSize
= Size( nItemWidth
, nItemHeight
);
231 mpInfoAry
= new BYTE
[ mnSize
];
232 memset( mpInfoAry
, 0, mnSize
);
235 // -----------------------------------------------------------------------
237 void ImplImageBmp::Create( const BitmapEx
& rBmpEx
, long nItemWidth
, long nItemHeight
, USHORT nInitSize
)
240 maDisabledBmpEx
.SetEmpty();
245 maSize
= Size( nItemWidth
, nItemHeight
);
249 mpInfoAry
= new BYTE
[ mnSize
];
251 rBmpEx
.IsAlpha() ? IMPSYSIMAGEITEM_ALPHA
: ( rBmpEx
.IsTransparent() ? IMPSYSIMAGEITEM_MASK
: 0 ),
255 // -----------------------------------------------------------------------
257 void ImplImageBmp::Expand( USHORT nGrowSize
)
259 const ULONG nDX
= nGrowSize
* maSize
.Width();
260 const USHORT nOldSize
= mnSize
;
261 BYTE
* pNewAry
= new BYTE
[ mnSize
= sal::static_int_cast
<USHORT
>(mnSize
+nGrowSize
) ];
263 maBmpEx
.Expand( nDX
, 0UL );
265 if( !maDisabledBmpEx
.IsEmpty() )
266 maDisabledBmpEx
.Expand( nDX
, 0UL );
271 memset( pNewAry
, 0, mnSize
);
272 memcpy( pNewAry
, mpInfoAry
, nOldSize
);
277 // -----------------------------------------------------------------------
279 void ImplImageBmp::Invert()
287 // -----------------------------------------------------------------------
289 void ImplImageBmp::Replace( USHORT nPos
, USHORT nSrcPos
)
291 const Point
aSrcPos( nSrcPos
* maSize
.Width(), 0L ), aPos( nPos
* maSize
.Width(), 0L );
292 const Rectangle
aSrcRect( aSrcPos
, maSize
);
293 const Rectangle
aDstRect( aPos
, maSize
);
295 maBmpEx
.CopyPixel( aDstRect
, aSrcRect
);
297 if( !maDisabledBmpEx
.IsEmpty() )
298 maDisabledBmpEx
.CopyPixel( aDstRect
, aSrcRect
);
303 mpInfoAry
[ nPos
] = mpInfoAry
[ nSrcPos
];
306 // -----------------------------------------------------------------------
308 void ImplImageBmp::Replace( USHORT nPos
, const ImplImageBmp
& rImageBmp
, USHORT nSrcPos
)
310 const Point
aSrcPos( nSrcPos
* maSize
.Width(), 0L ), aPos( nPos
* maSize
.Width(), 0L );
311 const Rectangle
aSrcRect( aSrcPos
, maSize
);
312 const Rectangle
aDstRect( aPos
, maSize
);
314 maBmpEx
.CopyPixel( aDstRect
, aSrcRect
, &rImageBmp
.maBmpEx
);
316 ImplUpdateDisabledBmpEx( nPos
);
320 mpInfoAry
[ nPos
] = rImageBmp
.mpInfoAry
[ nSrcPos
];
323 // -----------------------------------------------------------------------
325 void ImplImageBmp::Replace( USHORT nPos
, const BitmapEx
& rBmpEx
)
327 const Point aNullPos
, aPos( nPos
* maSize
.Width(), 0L );
328 const Rectangle
aSrcRect( aNullPos
, maSize
);
329 const Rectangle
aDstRect( aPos
, maSize
);
331 maBmpEx
.CopyPixel( aDstRect
, aSrcRect
, &rBmpEx
);
333 ImplUpdateDisabledBmpEx( nPos
);
337 mpInfoAry
[ nPos
] &= ~( IMPSYSIMAGEITEM_MASK
| IMPSYSIMAGEITEM_ALPHA
);
338 mpInfoAry
[ nPos
] |= ( rBmpEx
.IsAlpha() ? IMPSYSIMAGEITEM_ALPHA
: ( rBmpEx
.IsTransparent() ? IMPSYSIMAGEITEM_MASK
: 0 ) );
341 // -----------------------------------------------------------------------
343 void ImplImageBmp::ReplaceColors( const Color
* pSrcColors
, const Color
* pDstColors
, ULONG nColorCount
)
345 maBmpEx
.Replace( pSrcColors
, pDstColors
, nColorCount
);
350 // -----------------------------------------------------------------------
352 void ImplImageBmp::ColorTransform( BmpColorMode eColorMode
)
354 maBmpEx
= maBmpEx
.GetColorTransformedBitmapEx( eColorMode
);
359 // -----------------------------------------------------------------------
361 BitmapEx
ImplImageBmp::GetBitmapEx( USHORT nPosCount
, USHORT
* pPosAry
) const
363 const Bitmap
aNewBmp( Size( nPosCount
* maSize
.Width(), maSize
.Height() ), maBmpEx
.GetBitmap().GetBitCount() );
365 if( maBmpEx
.IsAlpha() )
367 // initialize target bitmap with an empty alpha mask
368 // which allows for using an optimized copypixel later on (see AlphaMask::CopyPixel)
369 // that avoids palette lookups
370 AlphaMask
aAlpha( Size( nPosCount
* maSize
.Width(), maSize
.Height() ) );
371 aRet
= BitmapEx( aNewBmp
, aAlpha
);
374 aRet
= BitmapEx( aNewBmp
);
376 for( USHORT i
= 0; i
< nPosCount
; i
++ )
378 const Point
aSrcPos( pPosAry
[ i
] * maSize
.Width(), 0L );
379 const Point
aPos( i
* maSize
.Width(), 0L );
380 const Rectangle
aSrcRect( aSrcPos
, maSize
);
381 const Rectangle
aDstRect( aPos
, maSize
);
383 aRet
.CopyPixel( aDstRect
, aSrcRect
, &maBmpEx
);
389 // -----------------------------------------------------------------------
391 void ImplImageBmp::Draw( USHORT nPos
, OutputDevice
* pOutDev
,
392 const Point
& rPos
, USHORT nStyle
,
395 if( pOutDev
->IsDeviceOutputNecessary() )
397 const Point
aSrcPos( nPos
* maSize
.Width(), 0 );
400 aOutSize
= ( pSize
? *pSize
: pOutDev
->PixelToLogic( maSize
) );
402 if( nStyle
& IMAGE_DRAW_DISABLE
)
404 ImplUpdateDisabledBmpEx( nPos
);
405 pOutDev
->DrawBitmapEx( rPos
, aOutSize
, aSrcPos
, maSize
, maDisabledBmpEx
);
409 if( nStyle
& ( IMAGE_DRAW_COLORTRANSFORM
|
410 IMAGE_DRAW_MONOCHROME_BLACK
| IMAGE_DRAW_MONOCHROME_WHITE
|
411 IMAGE_DRAW_HIGHLIGHT
| IMAGE_DRAW_DEACTIVE
| IMAGE_DRAW_SEMITRANSPARENT
) )
414 const Rectangle
aCropRect( aSrcPos
, maSize
);
416 if( mpInfoAry
[ nPos
] & ( IMPSYSIMAGEITEM_MASK
| IMPSYSIMAGEITEM_ALPHA
) )
419 aTmpBmpEx
= maBmpEx
.GetBitmap();
421 aTmpBmpEx
.Crop( aCropRect
);
423 if( nStyle
& ( IMAGE_DRAW_COLORTRANSFORM
| IMAGE_DRAW_MONOCHROME_BLACK
| IMAGE_DRAW_MONOCHROME_WHITE
) )
425 const BmpColorMode eMode
= ( nStyle
& IMAGE_DRAW_COLORTRANSFORM
) ? BMP_COLOR_HIGHCONTRAST
:
426 ( ( nStyle
& IMAGE_DRAW_MONOCHROME_BLACK
) ? BMP_COLOR_MONOCHROME_BLACK
: BMP_COLOR_MONOCHROME_WHITE
);
428 aTmpBmpEx
= aTmpBmpEx
.GetColorTransformedBitmapEx( eMode
);
431 Bitmap
aTmpBmp( aTmpBmpEx
.GetBitmap() );
433 if( nStyle
& ( IMAGE_DRAW_HIGHLIGHT
| IMAGE_DRAW_DEACTIVE
) )
435 BitmapWriteAccess
* pAcc
= aTmpBmp
.AcquireWriteAccess();
439 const StyleSettings
& rSettings
= pOutDev
->GetSettings().GetStyleSettings();
442 const long nW
= pAcc
->Width();
443 const long nH
= pAcc
->Height();
444 BYTE
* pMapR
= new BYTE
[ 256 ];
445 BYTE
* pMapG
= new BYTE
[ 256 ];
446 BYTE
* pMapB
= new BYTE
[ 256 ];
449 if( nStyle
& IMAGE_DRAW_HIGHLIGHT
)
450 aColor
= rSettings
.GetHighlightColor();
452 aColor
= rSettings
.GetDeactiveColor();
454 const BYTE cR
= aColor
.GetRed();
455 const BYTE cG
= aColor
.GetGreen();
456 const BYTE cB
= aColor
.GetBlue();
458 for( nX
= 0L; nX
< 256L; nX
++ )
460 pMapR
[ nX
] = (BYTE
) ( ( ( nY
= ( nX
+ cR
) >> 1 ) > 255 ) ? 255 : nY
);
461 pMapG
[ nX
] = (BYTE
) ( ( ( nY
= ( nX
+ cG
) >> 1 ) > 255 ) ? 255 : nY
);
462 pMapB
[ nX
] = (BYTE
) ( ( ( nY
= ( nX
+ cB
) >> 1 ) > 255 ) ? 255 : nY
);
465 if( pAcc
->HasPalette() )
467 for( USHORT i
= 0, nCount
= pAcc
->GetPaletteEntryCount(); i
< nCount
; i
++ )
469 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( i
);
470 aCol
.SetRed( pMapR
[ rCol
.GetRed() ] );
471 aCol
.SetGreen( pMapG
[ rCol
.GetGreen() ] );
472 aCol
.SetBlue( pMapB
[ rCol
.GetBlue() ] );
473 pAcc
->SetPaletteColor( i
, aCol
);
476 else if( pAcc
->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR
)
478 for( nY
= 0L; nY
< nH
; nY
++ )
480 Scanline pScan
= pAcc
->GetScanline( nY
);
482 for( nX
= 0L; nX
< nW
; nX
++ )
484 *pScan
= pMapB
[ *pScan
]; pScan
++;
485 *pScan
= pMapG
[ *pScan
]; pScan
++;
486 *pScan
= pMapR
[ *pScan
]; pScan
++;
492 for( nY
= 0L; nY
< nH
; nY
++ )
494 for( nX
= 0L; nX
< nW
; nX
++ )
496 aCol
= pAcc
->GetPixel( nY
, nX
);
497 aCol
.SetRed( pMapR
[ aCol
.GetRed() ] );
498 aCol
.SetGreen( pMapG
[ aCol
.GetGreen() ] );
499 aCol
.SetBlue( pMapB
[ aCol
.GetBlue() ] );
500 pAcc
->SetPixel( nY
, nX
, aCol
);
508 aTmpBmp
.ReleaseAccess( pAcc
);
512 if( nStyle
& IMAGE_DRAW_SEMITRANSPARENT
)
514 if( aTmpBmpEx
.IsTransparent() )
516 Bitmap
aAlphaBmp( aTmpBmpEx
.GetAlpha().GetBitmap() );
518 aAlphaBmp
.Adjust( 50 );
519 aTmpBmpEx
= BitmapEx( aTmpBmp
, AlphaMask( aAlphaBmp
) );
524 aTmpBmpEx
= BitmapEx( aTmpBmp
, AlphaMask( aTmpBmp
.GetSizePixel(), &cErase
) );
529 if( aTmpBmpEx
.IsAlpha() )
530 aTmpBmpEx
= BitmapEx( aTmpBmp
, aTmpBmpEx
.GetAlpha() );
531 else if( aTmpBmpEx
.IsAlpha() )
532 aTmpBmpEx
= BitmapEx( aTmpBmp
, aTmpBmpEx
.GetMask() );
535 pOutDev
->DrawBitmapEx( rPos
, aOutSize
, aTmpBmpEx
);
539 const BitmapEx
* pOutputBmp
;
541 if( pOutDev
->GetOutDevType() == OUTDEV_WINDOW
)
543 ImplUpdateDisplayBmp( pOutDev
);
544 pOutputBmp
= mpDisplayBmp
;
547 pOutputBmp
= &maBmpEx
;
550 pOutDev
->DrawBitmapEx( rPos
, aOutSize
, aSrcPos
, maSize
, *pOutputBmp
);
556 // -----------------------------------------------------------------------
558 void ImplImageBmp::ImplUpdateDisplayBmp( OutputDevice
*
559 #if defined WIN || defined WNT
564 if( !mpDisplayBmp
&& !maBmpEx
.IsEmpty() )
566 #if defined WIN || defined WNT
567 if( maBmpEx
.IsAlpha() )
568 mpDisplayBmp
= new BitmapEx( maBmpEx
);
571 const Bitmap
aBmp( maBmpEx
.GetBitmap().CreateDisplayBitmap( pOutDev
) );
573 if( maBmpEx
.IsTransparent() )
574 mpDisplayBmp
= new BitmapEx( aBmp
, maBmpEx
.GetMask().CreateDisplayBitmap( pOutDev
) );
576 mpDisplayBmp
= new BitmapEx( aBmp
);
579 mpDisplayBmp
= new BitmapEx( maBmpEx
);
584 // -----------------------------------------------------------------------
586 void ImplImageBmp::ImplUpdateDisabledBmpEx( int nPos
)
588 const Size
aTotalSize( maBmpEx
.GetSizePixel() );
590 if( maDisabledBmpEx
.IsEmpty() )
592 Bitmap
aGrey( aTotalSize
, 8, &Bitmap::GetGreyPalette( 256 ) );
593 AlphaMask
aGreyAlphaMask( aTotalSize
);
595 maDisabledBmpEx
= BitmapEx( aGrey
, aGreyAlphaMask
);
599 Bitmap
aBmp( maBmpEx
.GetBitmap() );
600 BitmapReadAccess
* pBmp( aBmp
.AcquireReadAccess() );
601 AlphaMask
aBmpAlphaMask( maBmpEx
.GetAlpha() );
602 BitmapReadAccess
* pBmpAlphaMask( aBmpAlphaMask
.AcquireReadAccess() );
603 Bitmap
aGrey( maDisabledBmpEx
.GetBitmap() );
604 BitmapWriteAccess
* pGrey( aGrey
.AcquireWriteAccess() );
605 AlphaMask
aGreyAlphaMask( maDisabledBmpEx
.GetAlpha() );
606 BitmapWriteAccess
* pGreyAlphaMask( aGreyAlphaMask
.AcquireWriteAccess() );
608 if( pBmp
&& pBmpAlphaMask
&& pGrey
&& pGreyAlphaMask
)
610 BitmapColor
aGreyVal( 0 );
611 BitmapColor
aGreyAlphaMaskVal( 0 );
612 const Point
aPos( ( nPos
< 0 ) ? 0 : ( nPos
* maSize
.Width() ), 0 );
613 const int nLeft
= aPos
.X(), nRight
= nLeft
+ ( ( nPos
< 0 ) ? aTotalSize
.Width() : maSize
.Width() );
614 const int nTop
= aPos
.Y(), nBottom
= nTop
+ maSize
.Height();
616 for( int nY
= nTop
; nY
< nBottom
; ++nY
)
618 for( int nX
= nLeft
; nX
< nRight
; ++nX
)
620 aGreyVal
.SetIndex( pBmp
->GetLuminance( nY
, nX
) );
621 pGrey
->SetPixel( nY
, nX
, aGreyVal
);
623 const BitmapColor
aBmpAlphaMaskVal( pBmpAlphaMask
->GetPixel( nY
, nX
) );
625 aGreyAlphaMaskVal
.SetIndex( static_cast< sal_uInt8
>( ::std::min( aBmpAlphaMaskVal
.GetIndex() + 178ul, 255ul ) ) );
626 pGreyAlphaMask
->SetPixel( nY
, nX
, aGreyAlphaMaskVal
);
631 aBmp
.ReleaseAccess( pBmp
);
632 aBmpAlphaMask
.ReleaseAccess( pBmpAlphaMask
);
633 aGrey
.ReleaseAccess( pGrey
);
634 aGreyAlphaMask
.ReleaseAccess( pGreyAlphaMask
);
636 maDisabledBmpEx
= BitmapEx( aGrey
, aGreyAlphaMask
);