2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/bitmap.hxx>
21 #include <vcl/BitmapAccessMode.hxx>
22 #include <vcl/BitmapBuffer.hxx>
23 #include <vcl/BitmapPalette.hxx>
24 #include <vcl/ColorMask.hxx>
25 #include <vcl/Scanline.hxx>
26 #include <com/sun/star/beans/XFastPropertySet.hpp>
27 #include <win/wincomp.hxx>
28 #include <win/salgdi.h>
29 #include <win/saldata.hxx>
30 #include <win/salbmp.h>
32 #include <vcl/timer.hxx>
33 #include <cppuhelper/basemutex.hxx>
34 #include <sal/log.hxx>
35 #include <tools/helpers.hxx>
47 WinSalBitmap::WinSalBitmap()
49 basegfx::SystemDependentDataHolder(),
57 WinSalBitmap::~WinSalBitmap()
62 void WinSalBitmap::Destroy()
67 DeleteObject( mhDDB
);
75 class SystemDependentData_GdiPlusBitmap
: public basegfx::SystemDependentData
78 std::shared_ptr
<Gdiplus::Bitmap
> mpGdiPlusBitmap
;
79 const WinSalBitmap
* mpAssociatedAlpha
;
82 SystemDependentData_GdiPlusBitmap(
83 const std::shared_ptr
<Gdiplus::Bitmap
>& rGdiPlusBitmap
,
84 const WinSalBitmap
* pAssociatedAlpha
);
86 const WinSalBitmap
* getAssociatedAlpha() const { return mpAssociatedAlpha
; }
87 const std::shared_ptr
<Gdiplus::Bitmap
>& getGdiPlusBitmap() const { return mpGdiPlusBitmap
; }
89 virtual sal_Int64
estimateUsageInBytes() const override
;
94 SystemDependentData_GdiPlusBitmap::SystemDependentData_GdiPlusBitmap(
95 const std::shared_ptr
<Gdiplus::Bitmap
>& rGdiPlusBitmap
,
96 const WinSalBitmap
* pAssociatedAlpha
)
97 : basegfx::SystemDependentData(Application::GetSystemDependentDataManager()),
98 mpGdiPlusBitmap(rGdiPlusBitmap
),
99 mpAssociatedAlpha(pAssociatedAlpha
)
103 sal_Int64
SystemDependentData_GdiPlusBitmap::estimateUsageInBytes() const
105 sal_Int64
nRetval(0);
109 const UINT
nWidth(mpGdiPlusBitmap
->GetWidth());
110 const UINT
nHeight(mpGdiPlusBitmap
->GetHeight());
112 if(0 != nWidth
&& 0 != nHeight
)
114 nRetval
= nWidth
* nHeight
;
116 switch(mpGdiPlusBitmap
->GetPixelFormat())
118 case PixelFormat1bppIndexed
:
121 case PixelFormat4bppIndexed
:
124 case PixelFormat16bppGrayScale
:
125 case PixelFormat16bppRGB555
:
126 case PixelFormat16bppRGB565
:
127 case PixelFormat16bppARGB1555
:
130 case PixelFormat24bppRGB
:
133 case PixelFormat32bppRGB
:
134 case PixelFormat32bppARGB
:
135 case PixelFormat32bppPARGB
:
136 case PixelFormat32bppCMYK
:
139 case PixelFormat48bppRGB
:
142 case PixelFormat64bppARGB
:
143 case PixelFormat64bppPARGB
:
147 case PixelFormat8bppIndexed
:
156 std::shared_ptr
< Gdiplus::Bitmap
> WinSalBitmap::ImplGetGdiPlusBitmap(const WinSalBitmap
* pAlphaSource
) const
158 std::shared_ptr
< Gdiplus::Bitmap
> aRetval
;
160 // try to access buffered data
161 std::shared_ptr
<SystemDependentData_GdiPlusBitmap
> pSystemDependentData_GdiPlusBitmap(
162 getSystemDependentData
<SystemDependentData_GdiPlusBitmap
>());
164 if(pSystemDependentData_GdiPlusBitmap
)
166 // check data validity
167 if(pSystemDependentData_GdiPlusBitmap
->getAssociatedAlpha() != pAlphaSource
168 || 0 == maSize
.Width()
169 || 0 == maSize
.Height())
171 // #122350# if associated alpha with which the GDIPlus was constructed has changed
172 // it is necessary to remove it from buffer, reset reference to it and reconstruct
173 // data invalid, forget
174 pSystemDependentData_GdiPlusBitmap
.reset();
178 if(pSystemDependentData_GdiPlusBitmap
)
181 aRetval
= pSystemDependentData_GdiPlusBitmap
->getGdiPlusBitmap();
183 else if(!maSize
.IsEmpty())
185 // create and set data
186 const WinSalBitmap
* pAssociatedAlpha(nullptr);
190 aRetval
= const_cast< WinSalBitmap
* >(this)->ImplCreateGdiPlusBitmap(*pAlphaSource
);
191 pAssociatedAlpha
= pAlphaSource
;
195 aRetval
= const_cast< WinSalBitmap
* >(this)->ImplCreateGdiPlusBitmap();
196 pAssociatedAlpha
= nullptr;
199 // add to buffering mechanism
200 addOrReplaceSystemDependentData
<SystemDependentData_GdiPlusBitmap
>(
208 std::shared_ptr
<Gdiplus::Bitmap
> WinSalBitmap::ImplCreateGdiPlusBitmap()
210 std::shared_ptr
<Gdiplus::Bitmap
> pRetval
;
211 WinSalBitmap
* pSalRGB
= this;
212 std::unique_ptr
<WinSalBitmap
> pExtraWinSalRGB
;
214 if(!pSalRGB
->ImplGethDIB())
216 // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
217 pExtraWinSalRGB
.reset(new WinSalBitmap());
218 pExtraWinSalRGB
->Create(*pSalRGB
, vcl::bitDepthToPixelFormat(pSalRGB
->GetBitCount()));
219 pSalRGB
= pExtraWinSalRGB
.get();
222 BitmapBuffer
* pRGB
= pSalRGB
->AcquireBuffer(BitmapAccessMode::Read
);
223 std::unique_ptr
<BitmapBuffer
> pExtraRGB
;
225 if(pRGB
&& ScanlineFormat::N24BitTcBgr
!= RemoveScanline(pRGB
->mnFormat
))
227 // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format
228 SalTwoRect
aSalTwoRect(0, 0, pRGB
->mnWidth
, pRGB
->mnHeight
, 0, 0, pRGB
->mnWidth
, pRGB
->mnHeight
);
229 pExtraRGB
= StretchAndConvert(
232 ScanlineFormat::N24BitTcBgr
);
234 pSalRGB
->ReleaseBuffer(pRGB
, BitmapAccessMode::Write
);
235 pRGB
= pExtraRGB
.get();
240 && pRGB
->mnHeight
> 0
241 && ScanlineFormat::N24BitTcBgr
== RemoveScanline(pRGB
->mnFormat
))
243 const sal_uInt32
nW(pRGB
->mnWidth
);
244 const sal_uInt32
nH(pRGB
->mnHeight
);
246 pRetval
= std::make_shared
<Gdiplus::Bitmap
>(nW
, nH
, PixelFormat24bppRGB
);
248 if ( pRetval
->GetLastStatus() == Gdiplus::Ok
)
250 sal_uInt8
* pSrcRGB(pRGB
->mpBits
);
251 const sal_uInt32
nExtraRGB(pRGB
->mnScanlineSize
- (nW
* 3));
252 const bool bTopDown(pRGB
->mnFormat
& ScanlineFormat::TopDown
);
253 const Gdiplus::Rect
aAllRect(0, 0, nW
, nH
);
254 Gdiplus::BitmapData aGdiPlusBitmapData
;
255 pRetval
->LockBits(&aAllRect
, Gdiplus::ImageLockModeWrite
, PixelFormat24bppRGB
, &aGdiPlusBitmapData
);
257 // copy data to Gdiplus::Bitmap; format is BGR here in both cases, so memcpy is possible
258 for(sal_uInt32
y(0); y
< nH
; y
++)
260 const sal_uInt32
nYInsert(bTopDown
? y
: nH
- y
- 1);
261 sal_uInt8
* targetPixels
= static_cast<sal_uInt8
*>(aGdiPlusBitmapData
.Scan0
) + (nYInsert
* aGdiPlusBitmapData
.Stride
);
263 memcpy(targetPixels
, pSrcRGB
, nW
* 3);
264 pSrcRGB
+= nW
* 3 + nExtraRGB
;
267 pRetval
->UnlockBits(&aGdiPlusBitmapData
);
277 // #i123478# shockingly, BitmapBuffer does not free the memory it is controlling
278 // in its destructor, this *has to be done by hand*. Doing it here now
279 delete[] pExtraRGB
->mpBits
;
284 pSalRGB
->ReleaseBuffer(pRGB
, BitmapAccessMode::Read
);
290 std::shared_ptr
<Gdiplus::Bitmap
> WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap
& rAlphaSource
)
292 std::shared_ptr
<Gdiplus::Bitmap
> pRetval
;
293 WinSalBitmap
* pSalRGB
= this;
294 std::unique_ptr
<WinSalBitmap
> pExtraWinSalRGB
;
296 if(!pSalRGB
->ImplGethDIB())
298 // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
299 pExtraWinSalRGB
.reset(new WinSalBitmap());
300 pExtraWinSalRGB
->Create(*pSalRGB
, vcl::bitDepthToPixelFormat(pSalRGB
->GetBitCount()));
301 pSalRGB
= pExtraWinSalRGB
.get();
304 BitmapBuffer
* pRGB
= pSalRGB
->AcquireBuffer(BitmapAccessMode::Read
);
305 std::unique_ptr
<BitmapBuffer
> pExtraRGB
;
307 if(pRGB
&& ScanlineFormat::N24BitTcBgr
!= RemoveScanline(pRGB
->mnFormat
))
309 // convert source bitmap to canlineFormat::N24BitTcBgr format if not yet in that format
310 SalTwoRect
aSalTwoRect(0, 0, pRGB
->mnWidth
, pRGB
->mnHeight
, 0, 0, pRGB
->mnWidth
, pRGB
->mnHeight
);
311 pExtraRGB
= StretchAndConvert(
314 ScanlineFormat::N24BitTcBgr
);
316 pSalRGB
->ReleaseBuffer(pRGB
, BitmapAccessMode::Read
);
317 pRGB
= pExtraRGB
.get();
320 WinSalBitmap
* pSalA
= const_cast< WinSalBitmap
* >(&rAlphaSource
);
321 std::unique_ptr
<WinSalBitmap
> pExtraWinSalA
;
323 if(!pSalA
->ImplGethDIB())
325 // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap
326 pExtraWinSalA
.reset(new WinSalBitmap());
327 pExtraWinSalA
->Create(*pSalA
, vcl::bitDepthToPixelFormat(pSalA
->GetBitCount()));
328 pSalA
= pExtraWinSalA
.get();
331 BitmapBuffer
* pA
= pSalA
->AcquireBuffer(BitmapAccessMode::Read
);
332 std::unique_ptr
<BitmapBuffer
> pExtraA
;
334 if(pA
&& ScanlineFormat::N8BitPal
!= RemoveScanline(pA
->mnFormat
))
336 // convert alpha bitmap to ScanlineFormat::N8BitPal format if not yet in that format
337 SalTwoRect
aSalTwoRect(0, 0, pA
->mnWidth
, pA
->mnHeight
, 0, 0, pA
->mnWidth
, pA
->mnHeight
);
338 const BitmapPalette
& rTargetPalette
= Bitmap::GetGreyPalette(256);
340 pExtraA
= StretchAndConvert(
343 ScanlineFormat::N8BitPal
,
346 pSalA
->ReleaseBuffer(pA
, BitmapAccessMode::Read
);
353 && pRGB
->mnHeight
> 0
354 && pRGB
->mnWidth
== pA
->mnWidth
355 && pRGB
->mnHeight
== pA
->mnHeight
356 && ScanlineFormat::N24BitTcBgr
== RemoveScanline(pRGB
->mnFormat
)
357 && ScanlineFormat::N8BitPal
== RemoveScanline(pA
->mnFormat
))
359 // we have alpha and bitmap in known formats, create GdiPlus Bitmap as 32bit ARGB
360 const sal_uInt32
nW(pRGB
->mnWidth
);
361 const sal_uInt32
nH(pRGB
->mnHeight
);
363 pRetval
= std::make_shared
<Gdiplus::Bitmap
>(nW
, nH
, PixelFormat32bppARGB
);
365 if ( pRetval
->GetLastStatus() == Gdiplus::Ok
) // 2nd place to secure with new Gdiplus::Bitmap
367 sal_uInt8
* pSrcRGB(pRGB
->mpBits
);
368 sal_uInt8
* pSrcA(pA
->mpBits
);
369 const sal_uInt32
nExtraRGB(pRGB
->mnScanlineSize
- (nW
* 3));
370 const sal_uInt32
nExtraA(pA
->mnScanlineSize
- nW
);
371 const bool bTopDown(pRGB
->mnFormat
& ScanlineFormat::TopDown
);
372 const Gdiplus::Rect
aAllRect(0, 0, nW
, nH
);
373 Gdiplus::BitmapData aGdiPlusBitmapData
;
374 pRetval
->LockBits(&aAllRect
, Gdiplus::ImageLockModeWrite
, PixelFormat32bppARGB
, &aGdiPlusBitmapData
);
376 // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR from Bitmap and
377 // A from alpha, so inner loop is needed (who invented BitmapEx..?)
378 for(sal_uInt32
y(0); y
< nH
; y
++)
380 const sal_uInt32
nYInsert(bTopDown
? y
: nH
- y
- 1);
381 sal_uInt8
* targetPixels
= static_cast<sal_uInt8
*>(aGdiPlusBitmapData
.Scan0
) + (nYInsert
* aGdiPlusBitmapData
.Stride
);
383 for(sal_uInt32
x(0); x
< nW
; x
++)
385 *targetPixels
++ = *pSrcRGB
++;
386 *targetPixels
++ = *pSrcRGB
++;
387 *targetPixels
++ = *pSrcRGB
++;
388 *targetPixels
++ = 0xff - *pSrcA
++;
391 pSrcRGB
+= nExtraRGB
;
395 pRetval
->UnlockBits(&aGdiPlusBitmapData
);
405 // #i123478# shockingly, BitmapBuffer does not free the memory it is controlling
406 // in its destructor, this *has to be done handish*. Doing it here now
407 delete[] pExtraA
->mpBits
;
412 pSalA
->ReleaseBuffer(pA
, BitmapAccessMode::Read
);
415 pExtraWinSalA
.reset();
419 // #i123478# shockingly, BitmapBuffer does not free the memory it is controlling
420 // in its destructor, this *has to be done by hand*. Doing it here now
421 delete[] pExtraRGB
->mpBits
;
426 pSalRGB
->ReleaseBuffer(pRGB
, BitmapAccessMode::Read
);
429 pExtraWinSalRGB
.reset();
434 bool WinSalBitmap::Create( HANDLE hBitmap
)
438 mhDDB
= static_cast<HBITMAP
>( hBitmap
);
442 PBITMAPINFOHEADER pBIH
= static_cast<PBITMAPINFOHEADER
>(GlobalLock( mhDIB
));
444 maSize
= Size( pBIH
->biWidth
, pBIH
->biHeight
);
445 mnBitCount
= pBIH
->biBitCount
;
448 mnBitCount
= ( mnBitCount
<= 1 ) ? 1 : ( mnBitCount
<= 4 ) ? 4 : ( mnBitCount
<= 8 ) ? 8 : 24;
450 GlobalUnlock( mhDIB
);
456 if( GetObjectW( mhDDB
, sizeof( aDDBInfo
), &aDDBInfo
) )
458 maSize
= Size( aDDBInfo
.bmWidth
, aDDBInfo
.bmHeight
);
459 mnBitCount
= aDDBInfo
.bmPlanes
* aDDBInfo
.bmBitsPixel
;
463 mnBitCount
= ( mnBitCount
<= 1 ) ? 1 :
464 ( mnBitCount
<= 4 ) ? 4 :
465 ( mnBitCount
<= 8 ) ? 8 : 24;
480 bool WinSalBitmap::Create(const Size
& rSize
, vcl::PixelFormat ePixelFormat
, const BitmapPalette
& rPal
)
484 mhDIB
= ImplCreateDIB(rSize
, ePixelFormat
, rPal
);
489 mnBitCount
= vcl::pixelFormatBitCount(ePixelFormat
);
496 bool WinSalBitmap::Create( const SalBitmap
& rSSalBitmap
)
499 const WinSalBitmap
& rSalBitmap
= static_cast<const WinSalBitmap
&>(rSSalBitmap
);
501 if ( rSalBitmap
.mhDIB
|| rSalBitmap
.mhDDB
)
503 HANDLE hNewHdl
= ImplCopyDIBOrDDB( rSalBitmap
.mhDIB
? rSalBitmap
.mhDIB
: rSalBitmap
.mhDDB
,
504 rSalBitmap
.mhDIB
!= nullptr );
508 if( rSalBitmap
.mhDIB
)
509 mhDIB
= static_cast<HGLOBAL
>(hNewHdl
);
510 else if( rSalBitmap
.mhDDB
)
511 mhDDB
= static_cast<HBITMAP
>(hNewHdl
);
513 maSize
= rSalBitmap
.maSize
;
514 mnBitCount
= rSalBitmap
.mnBitCount
;
523 bool WinSalBitmap::Create( const SalBitmap
& rSSalBmp
, SalGraphics
* pSGraphics
)
527 const WinSalBitmap
& rSalBmp
= static_cast<const WinSalBitmap
&>(rSSalBmp
);
528 WinSalGraphics
* pGraphics
= static_cast<WinSalGraphics
*>(pSGraphics
);
532 PBITMAPINFO pBI
= static_cast<PBITMAPINFO
>(GlobalLock( rSalBmp
.mhDIB
));
533 HDC hDC
= pGraphics
->getHDC();
536 PBYTE pBits
= reinterpret_cast<PBYTE
>(pBI
) + pBI
->bmiHeader
.biSize
+
537 ImplGetDIBColorCount( rSalBmp
.mhDIB
) * sizeof( RGBQUAD
);
539 if( pBI
->bmiHeader
.biBitCount
== 1 )
541 hNewDDB
= CreateBitmap( pBI
->bmiHeader
.biWidth
, pBI
->bmiHeader
.biHeight
, 1, 1, nullptr );
544 SetDIBits( hDC
, hNewDDB
, 0, pBI
->bmiHeader
.biHeight
, pBits
, pBI
, DIB_RGB_COLORS
);
547 hNewDDB
= CreateDIBitmap( hDC
, &pBI
->bmiHeader
, CBM_INIT
, pBits
, pBI
, DIB_RGB_COLORS
);
549 GlobalUnlock( rSalBmp
.mhDIB
);
551 if( hNewDDB
&& GetObjectW( hNewDDB
, sizeof( aDDBInfo
), &aDDBInfo
) )
554 maSize
= Size( aDDBInfo
.bmWidth
, aDDBInfo
.bmHeight
);
555 mnBitCount
= aDDBInfo
.bmPlanes
* aDDBInfo
.bmBitsPixel
;
560 DeleteObject( hNewDDB
);
566 bool WinSalBitmap::Create(const SalBitmap
& rSSalBmp
, vcl::PixelFormat eNewPixelFormat
)
570 const WinSalBitmap
& rSalBmp
= static_cast<const WinSalBitmap
&>(rSSalBmp
);
574 mhDIB
= ImplCreateDIB( rSalBmp
.maSize
, eNewPixelFormat
, BitmapPalette() );
578 PBITMAPINFO pBI
= static_cast<PBITMAPINFO
>(GlobalLock( mhDIB
));
579 const int nLines
= static_cast<int>(rSalBmp
.maSize
.Height());
580 HDC hDC
= GetDC( nullptr );
581 PBYTE pBits
= reinterpret_cast<PBYTE
>(pBI
) + pBI
->bmiHeader
.biSize
+
582 ImplGetDIBColorCount( mhDIB
) * sizeof( RGBQUAD
);
583 SalData
* pSalData
= GetSalData();
584 HPALETTE hOldPal
= nullptr;
586 if ( pSalData
->mhDitherPal
)
588 hOldPal
= SelectPalette( hDC
, pSalData
->mhDitherPal
, TRUE
);
589 RealizePalette( hDC
);
592 if( GetDIBits( hDC
, rSalBmp
.mhDDB
, 0, nLines
, pBits
, pBI
, DIB_RGB_COLORS
) == nLines
)
594 GlobalUnlock( mhDIB
);
595 maSize
= rSalBmp
.maSize
;
596 mnBitCount
= vcl::pixelFormatBitCount(eNewPixelFormat
);
601 GlobalUnlock( mhDIB
);
607 SelectPalette( hDC
, hOldPal
, TRUE
);
609 ReleaseDC( nullptr, hDC
);
616 bool WinSalBitmap::Create( const css::uno::Reference
< css::rendering::XBitmapCanvas
>& rBitmapCanvas
, Size
& /*rSize*/, bool bMask
)
618 css::uno::Reference
< css::beans::XFastPropertySet
>
619 xFastPropertySet( rBitmapCanvas
, css::uno::UNO_QUERY
);
621 if( xFastPropertySet
) {
622 css::uno::Sequence
< css::uno::Any
> args
;
624 if( xFastPropertySet
->getFastPropertyValue(bMask
? 2 : 1) >>= args
) {
627 if( args
[0] >>= aHBmp64
) {
628 return Create( reinterpret_cast<HANDLE
>(aHBmp64
) );
635 sal_uInt16
WinSalBitmap::ImplGetDIBColorCount( HGLOBAL hDIB
)
637 sal_uInt16 nColors
= 0;
641 PBITMAPINFO pBI
= static_cast<PBITMAPINFO
>(GlobalLock( hDIB
));
643 if ( pBI
->bmiHeader
.biSize
!= sizeof( BITMAPCOREHEADER
) )
645 if( pBI
->bmiHeader
.biBitCount
<= 8 )
647 if ( pBI
->bmiHeader
.biClrUsed
)
648 nColors
= static_cast<sal_uInt16
>(pBI
->bmiHeader
.biClrUsed
);
650 nColors
= 1 << pBI
->bmiHeader
.biBitCount
;
653 else if( reinterpret_cast<PBITMAPCOREHEADER
>(pBI
)->bcBitCount
<= 8 )
654 nColors
= 1 << reinterpret_cast<PBITMAPCOREHEADER
>(pBI
)->bcBitCount
;
656 GlobalUnlock( hDIB
);
662 HGLOBAL
WinSalBitmap::ImplCreateDIB(const Size
& rSize
, vcl::PixelFormat ePixelFormat
, const BitmapPalette
& rPal
)
664 HGLOBAL hDIB
= nullptr;
666 if( rSize
.IsEmpty() )
669 const auto nBits
= vcl::pixelFormatBitCount(ePixelFormat
);
671 // calculate bitmap size in Bytes
672 const sal_uLong nAlignedWidth4Bytes
= AlignedWidth4Bytes(nBits
* rSize
.Width());
673 const sal_uLong nImageSize
= nAlignedWidth4Bytes
* rSize
.Height();
674 bool bOverflow
= (nImageSize
/ nAlignedWidth4Bytes
) != static_cast<sal_uLong
>(rSize
.Height());
678 // allocate bitmap memory including header and palette
679 sal_uInt16 nColors
= 0;
680 if (ePixelFormat
<= vcl::PixelFormat::N8_BPP
)
681 nColors
= vcl::numberOfColors(ePixelFormat
);
683 const sal_uLong nHeaderSize
= sizeof( BITMAPINFOHEADER
) + nColors
* sizeof( RGBQUAD
);
684 bOverflow
= (nHeaderSize
+ nImageSize
) < nImageSize
;
688 hDIB
= GlobalAlloc( GHND
, nHeaderSize
+ nImageSize
);
692 PBITMAPINFO pBI
= static_cast<PBITMAPINFO
>( GlobalLock( hDIB
) );
693 PBITMAPINFOHEADER pBIH
= reinterpret_cast<PBITMAPINFOHEADER
>( pBI
);
695 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
696 pBIH
->biWidth
= rSize
.Width();
697 pBIH
->biHeight
= rSize
.Height();
699 pBIH
->biBitCount
= nBits
;
700 pBIH
->biCompression
= BI_RGB
;
701 pBIH
->biSizeImage
= nImageSize
;
702 pBIH
->biXPelsPerMeter
= 0;
703 pBIH
->biYPelsPerMeter
= 0;
705 pBIH
->biClrImportant
= 0;
709 // copy the palette entries if any
710 const sal_uInt16 nMinCount
= std::min( nColors
, rPal
.GetEntryCount() );
712 memcpy( pBI
->bmiColors
, rPal
.ImplGetColorBuffer(), nMinCount
* sizeof(RGBQUAD
) );
715 GlobalUnlock( hDIB
);
720 HANDLE
WinSalBitmap::ImplCopyDIBOrDDB( HANDLE hHdl
, bool bDIB
)
722 HANDLE hCopy
= nullptr;
726 const sal_uLong nSize
= GlobalSize( hHdl
);
728 if ( (hCopy
= GlobalAlloc( GHND
, nSize
)) != nullptr )
730 memcpy( GlobalLock( hCopy
), GlobalLock( hHdl
), nSize
);
732 GlobalUnlock( hCopy
);
733 GlobalUnlock( hHdl
);
740 // find out size of source bitmap
741 GetObjectW( hHdl
, sizeof( aBmp
), &aBmp
);
743 // create destination bitmap
744 if ( (hCopy
= CreateBitmapIndirect( &aBmp
)) != nullptr )
746 HDC hBmpDC
= CreateCompatibleDC( nullptr );
747 HBITMAP hBmpOld
= static_cast<HBITMAP
>(SelectObject( hBmpDC
, hHdl
));
748 HDC hCopyDC
= CreateCompatibleDC( hBmpDC
);
749 HBITMAP hCopyOld
= static_cast<HBITMAP
>(SelectObject( hCopyDC
, hCopy
));
751 BitBlt( hCopyDC
, 0, 0, aBmp
.bmWidth
, aBmp
.bmHeight
, hBmpDC
, 0, 0, SRCCOPY
);
753 SelectObject( hCopyDC
, hCopyOld
);
756 SelectObject( hBmpDC
, hBmpOld
);
764 BitmapBuffer
* WinSalBitmap::AcquireBuffer( BitmapAccessMode
/*nMode*/ )
766 std::unique_ptr
<BitmapBuffer
> pBuffer
;
770 PBITMAPINFO pBI
= static_cast<PBITMAPINFO
>(GlobalLock( mhDIB
));
771 PBITMAPINFOHEADER pBIH
= &pBI
->bmiHeader
;
773 if( pBIH
->biPlanes
== 1 )
775 pBuffer
.reset(new BitmapBuffer
);
777 pBuffer
->mnFormat
= pBIH
->biBitCount
== 1 ? ScanlineFormat::N1BitMsbPal
:
778 pBIH
->biBitCount
== 8 ? ScanlineFormat::N8BitPal
:
779 pBIH
->biBitCount
== 24 ? ScanlineFormat::N24BitTcBgr
:
780 pBIH
->biBitCount
== 32 ? ScanlineFormat::N32BitTcMask
:
781 ScanlineFormat::NONE
;
783 if( RemoveScanline( pBuffer
->mnFormat
) != ScanlineFormat::NONE
)
785 pBuffer
->mnWidth
= maSize
.Width();
786 pBuffer
->mnHeight
= maSize
.Height();
787 pBuffer
->mnScanlineSize
= AlignedWidth4Bytes( maSize
.Width() * pBIH
->biBitCount
);
788 pBuffer
->mnBitCount
= static_cast<sal_uInt16
>(pBIH
->biBitCount
);
790 if( pBuffer
->mnBitCount
<= 8 )
792 const sal_uInt16 nPalCount
= ImplGetDIBColorCount( mhDIB
);
794 pBuffer
->maPalette
.SetEntryCount( nPalCount
);
795 memcpy( pBuffer
->maPalette
.ImplGetColorBuffer(), pBI
->bmiColors
, nPalCount
* sizeof( RGBQUAD
) );
796 pBuffer
->mpBits
= reinterpret_cast<PBYTE
>(pBI
) + pBI
->bmiHeader
.biSize
+ nPalCount
* sizeof( RGBQUAD
);
798 else if( ( pBIH
->biBitCount
== 16 ) || ( pBIH
->biBitCount
== 32 ) )
800 sal_uLong nOffset
= 0;
802 if( pBIH
->biCompression
== BI_BITFIELDS
)
804 nOffset
= 3 * sizeof( RGBQUAD
);
805 ColorMaskElement
aRedMask(*reinterpret_cast<UINT32
*>(&pBI
->bmiColors
[ 0 ]));
806 aRedMask
.CalcMaskShift();
807 ColorMaskElement
aGreenMask(*reinterpret_cast<UINT32
*>(&pBI
->bmiColors
[ 1 ]));
808 aGreenMask
.CalcMaskShift();
809 ColorMaskElement
aBlueMask(*reinterpret_cast<UINT32
*>(&pBI
->bmiColors
[ 2 ]));
810 aBlueMask
.CalcMaskShift();
811 pBuffer
->maColorMask
= ColorMask(aRedMask
, aGreenMask
, aBlueMask
);
813 else if( pBIH
->biBitCount
== 16 )
815 ColorMaskElement
aRedMask(0x00007c00UL
);
816 aRedMask
.CalcMaskShift();
817 ColorMaskElement
aGreenMask(0x000003e0UL
);
818 aGreenMask
.CalcMaskShift();
819 ColorMaskElement
aBlueMask(0x0000001fUL
);
820 aBlueMask
.CalcMaskShift();
821 pBuffer
->maColorMask
= ColorMask(aRedMask
, aGreenMask
, aBlueMask
);
825 ColorMaskElement
aRedMask(0x00ff0000UL
);
826 aRedMask
.CalcMaskShift();
827 ColorMaskElement
aGreenMask(0x0000ff00UL
);
828 aGreenMask
.CalcMaskShift();
829 ColorMaskElement
aBlueMask(0x000000ffUL
);
830 aBlueMask
.CalcMaskShift();
831 pBuffer
->maColorMask
= ColorMask(aRedMask
, aGreenMask
, aBlueMask
);
834 pBuffer
->mpBits
= reinterpret_cast<PBYTE
>(pBI
) + pBI
->bmiHeader
.biSize
+ nOffset
;
837 pBuffer
->mpBits
= reinterpret_cast<PBYTE
>(pBI
) + pBI
->bmiHeader
.biSize
;
841 GlobalUnlock( mhDIB
);
846 GlobalUnlock( mhDIB
);
849 return pBuffer
.release();
852 void WinSalBitmap::ReleaseBuffer( BitmapBuffer
* pBuffer
, BitmapAccessMode nMode
)
858 if( nMode
== BitmapAccessMode::Write
&& !!pBuffer
->maPalette
)
860 PBITMAPINFO pBI
= static_cast<PBITMAPINFO
>(GlobalLock( mhDIB
));
861 const sal_uInt16 nCount
= pBuffer
->maPalette
.GetEntryCount();
862 const sal_uInt16 nDIBColorCount
= ImplGetDIBColorCount( mhDIB
);
863 memcpy( pBI
->bmiColors
, pBuffer
->maPalette
.ImplGetColorBuffer(), std::min( nDIBColorCount
, nCount
) * sizeof( RGBQUAD
) );
864 GlobalUnlock( mhDIB
);
867 GlobalUnlock( mhDIB
);
872 if( nMode
== BitmapAccessMode::Write
)
873 InvalidateChecksum();
876 bool WinSalBitmap::GetSystemData( BitmapSystemData
& rData
)
883 const Size
& rSize
= GetSize ();
884 rData
.mnWidth
= rSize
.Width();
885 rData
.mnHeight
= rSize
.Height();
890 bool WinSalBitmap::ScalingSupported() const
895 bool WinSalBitmap::Scale( const double& /*rScaleX*/, const double& /*rScaleY*/, BmpScaleFlag
/*nScaleFlag*/ )
900 bool WinSalBitmap::Replace( const Color
& /*rSearchColor*/, const Color
& /*rReplaceColor*/, sal_uInt8
/*nTol*/ )
905 const basegfx::SystemDependentDataHolder
* WinSalBitmap::accessSystemDependentDataHolder() const
910 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */