odk: don't run compiler -dumpversion for eaach include of settings.mk
[LibreOffice.git] / vcl / source / helper / canvasbitmap.cxx
blob2806aa0726cfba1376ad43883f569a8a71275956
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23 #include <com/sun/star/util/Endianness.hpp>
24 #include <com/sun/star/rendering/ColorComponentTag.hpp>
25 #include <com/sun/star/rendering/ColorSpaceType.hpp>
26 #include <com/sun/star/rendering/RenderingIntent.hpp>
28 #include <comphelper/diagnose_ex.hxx>
29 #include <canvasbitmap.hxx>
30 #include <vcl/canvastools.hxx>
31 #include <vcl/BitmapReadAccess.hxx>
32 #include <vcl/svapp.hxx>
34 #include <algorithm>
36 using namespace vcl::unotools;
37 using namespace ::com::sun::star;
39 namespace
41 // TODO(Q3): move to o3tl bithacks or somesuch. A similar method is in canvas/canvastools.hxx
43 // Good ole HAKMEM tradition. Calc number of 1 bits in 32bit word,
44 // unrolled loop. See e.g. Hackers Delight, p. 66
45 sal_Int32 bitcount( sal_uInt32 val )
47 val = val - ((val >> 1) & 0x55555555);
48 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
49 val = (val + (val >> 4)) & 0x0F0F0F0F;
50 val = val + (val >> 8);
51 val = val + (val >> 16);
52 return sal_Int32(val & 0x0000003F);
56 void VclCanvasBitmap::setComponentInfo( sal_uInt32 redShift, sal_uInt32 greenShift, sal_uInt32 blueShift )
58 // sort channels in increasing order of appearance in the pixel
59 // (starting with the least significant bits)
60 sal_Int8 redPos(0);
61 sal_Int8 greenPos(1);
62 sal_Int8 bluePos(2);
64 if( redShift > greenShift )
66 std::swap(redPos,greenPos);
67 if( redShift > blueShift )
69 std::swap(redPos,bluePos);
70 if( greenShift > blueShift )
71 std::swap(greenPos,bluePos);
74 else
76 if( greenShift > blueShift )
78 std::swap(greenPos,bluePos);
79 if( redShift > blueShift )
80 std::swap(redPos,bluePos);
84 m_aComponentTags.realloc(3);
85 sal_Int8* pTags = m_aComponentTags.getArray();
86 pTags[redPos] = rendering::ColorComponentTag::RGB_RED;
87 pTags[greenPos] = rendering::ColorComponentTag::RGB_GREEN;
88 pTags[bluePos] = rendering::ColorComponentTag::RGB_BLUE;
90 m_aComponentBitCounts.realloc(3);
91 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
92 pCounts[redPos] = bitcount(redShift);
93 pCounts[greenPos] = bitcount(greenShift);
94 pCounts[bluePos] = bitcount(blueShift);
97 BitmapScopedReadAccess& VclCanvasBitmap::getBitmapReadAccess()
99 // BitmapReadAccess is more expensive than BitmapInfoAccess,
100 // as the latter requires also pixels, which may need converted
101 // from the system format (and even fetched). Most calls here
102 // need only info access, create read access only on demand.
103 if(!m_pBmpReadAcc)
104 m_pBmpReadAcc.emplace(m_aBitmap);
105 return *m_pBmpReadAcc;
108 BitmapScopedReadAccess& VclCanvasBitmap::getAlphaReadAccess()
110 if(!m_pAlphaReadAcc)
111 m_pAlphaReadAcc.emplace(m_aAlpha);
112 return *m_pAlphaReadAcc;
115 VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
116 m_aBmpEx( rBitmap ),
117 m_aBitmap( rBitmap.GetBitmap() ),
118 m_pBmpAcc( m_aBitmap ),
119 m_nBitsPerInputPixel(0),
120 m_nBitsPerOutputPixel(0),
121 m_nRedIndex(-1),
122 m_nGreenIndex(-1),
123 m_nBlueIndex(-1),
124 m_nAlphaIndex(-1),
125 m_nIndexIndex(-1),
126 m_bPalette(false)
128 if( m_aBmpEx.IsAlpha() )
130 m_aAlpha = m_aBmpEx.GetAlphaMask().GetBitmap();
131 m_pAlphaAcc = m_aAlpha;
134 m_aLayout.ScanLines = 0;
135 m_aLayout.ScanLineBytes = 0;
136 m_aLayout.ScanLineStride = 0;
137 m_aLayout.PlaneStride = 0;
138 m_aLayout.ColorSpace.clear();
139 m_aLayout.Palette.clear();
140 m_aLayout.IsMsbFirst = false;
142 if( !m_pBmpAcc )
143 return;
145 m_aLayout.ScanLines = m_pBmpAcc->Height();
146 m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
147 m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
148 m_aLayout.PlaneStride = 0;
150 switch( m_pBmpAcc->GetScanlineFormat() )
152 case ScanlineFormat::N1BitMsbPal:
153 m_bPalette = true;
154 m_nBitsPerInputPixel = 1;
155 m_aLayout.IsMsbFirst = true;
156 break;
158 case ScanlineFormat::N8BitPal:
159 m_bPalette = true;
160 m_nBitsPerInputPixel = 8;
161 m_aLayout.IsMsbFirst = false; // doesn't matter
162 break;
164 case ScanlineFormat::N24BitTcBgr:
165 m_bPalette = false;
166 m_nBitsPerInputPixel = 24;
167 m_aLayout.IsMsbFirst = false; // doesn't matter
168 setComponentInfo( static_cast<sal_uInt32>(0xff0000UL),
169 static_cast<sal_uInt32>(0x00ff00UL),
170 static_cast<sal_uInt32>(0x0000ffUL) );
171 break;
173 case ScanlineFormat::N24BitTcRgb:
174 m_bPalette = false;
175 m_nBitsPerInputPixel = 24;
176 m_aLayout.IsMsbFirst = false; // doesn't matter
177 setComponentInfo( static_cast<sal_uInt32>(0x0000ffUL),
178 static_cast<sal_uInt32>(0x00ff00UL),
179 static_cast<sal_uInt32>(0xff0000UL) );
180 break;
182 case ScanlineFormat::N32BitTcAbgr:
184 m_bPalette = false;
185 m_nBitsPerInputPixel = 32;
186 m_aLayout.IsMsbFirst = false; // doesn't matter
188 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::ALPHA,
189 /* 1 */ rendering::ColorComponentTag::RGB_BLUE,
190 /* 2 */ rendering::ColorComponentTag::RGB_GREEN,
191 /* 3 */ rendering::ColorComponentTag::RGB_RED };
193 m_aComponentBitCounts = { /* 0 */ 8,
194 /* 1 */ 8,
195 /* 2 */ 8,
196 /* 3 */ 8 };
198 m_nRedIndex = 3;
199 m_nGreenIndex = 2;
200 m_nBlueIndex = 1;
201 m_nAlphaIndex = 0;
203 break;
205 case ScanlineFormat::N32BitTcArgb:
207 m_bPalette = false;
208 m_nBitsPerInputPixel = 32;
209 m_aLayout.IsMsbFirst = false; // doesn't matter
211 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::ALPHA,
212 /* 1 */ rendering::ColorComponentTag::RGB_RED,
213 /* 2 */ rendering::ColorComponentTag::RGB_GREEN,
214 /* 3 */ rendering::ColorComponentTag::RGB_BLUE };
216 m_aComponentBitCounts = { /* 0 */ 8,
217 /* 1 */ 8,
218 /* 2 */ 8,
219 /* 3 */ 8 };
221 m_nRedIndex = 1;
222 m_nGreenIndex = 2;
223 m_nBlueIndex = 3;
224 m_nAlphaIndex = 0;
226 break;
228 case ScanlineFormat::N32BitTcBgra:
230 m_bPalette = false;
231 m_nBitsPerInputPixel = 32;
232 m_aLayout.IsMsbFirst = false; // doesn't matter
234 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::RGB_BLUE,
235 /* 1 */ rendering::ColorComponentTag::RGB_GREEN,
236 /* 2 */ rendering::ColorComponentTag::RGB_RED,
237 /* 3 */ rendering::ColorComponentTag::ALPHA };
239 m_aComponentBitCounts = { /* 0 */ 8,
240 /* 1 */ 8,
241 /* 2 */ 8,
242 /* 3 */ 8 };
244 m_nRedIndex = 2;
245 m_nGreenIndex = 1;
246 m_nBlueIndex = 0;
247 m_nAlphaIndex = 3;
249 break;
251 case ScanlineFormat::N32BitTcRgba:
253 m_bPalette = false;
254 m_nBitsPerInputPixel = 32;
255 m_aLayout.IsMsbFirst = false; // doesn't matter
257 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::RGB_RED,
258 /* 1 */ rendering::ColorComponentTag::RGB_GREEN,
259 /* 2 */ rendering::ColorComponentTag::RGB_BLUE,
260 /* 3 */ rendering::ColorComponentTag::ALPHA };
262 m_aComponentBitCounts = { /* 0 */ 8,
263 /* 1 */ 8,
264 /* 2 */ 8,
265 /* 3 */ 8 };
267 m_nRedIndex = 0;
268 m_nGreenIndex = 1;
269 m_nBlueIndex = 2;
270 m_nAlphaIndex = 3;
272 break;
274 case ScanlineFormat::N32BitTcMask:
275 m_bPalette = false;
276 m_nBitsPerInputPixel = 32;
277 m_aLayout.IsMsbFirst = false; // doesn't matter
278 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
279 m_pBmpAcc->GetColorMask().GetGreenMask(),
280 m_pBmpAcc->GetColorMask().GetBlueMask() );
281 break;
283 default:
284 OSL_FAIL( "unsupported bitmap format" );
285 break;
288 if( m_bPalette )
290 m_aComponentTags = { rendering::ColorComponentTag::INDEX };
292 m_aComponentBitCounts = { m_nBitsPerInputPixel };
294 m_nIndexIndex = 0;
297 m_nBitsPerOutputPixel = m_nBitsPerInputPixel;
298 if( !m_aBmpEx.IsAlpha() )
299 return;
301 // TODO(P1): need to interleave alpha with bitmap data -
302 // won't fuss with less-than-8 bit for now
303 m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
305 // check whether alpha goes in front or behind the
306 // bitcount sequence. If pixel format is little endian,
307 // put it behind all the other channels. If it's big
308 // endian, put it in front (because later, the actual data
309 // always gets written after the pixel data)
311 // TODO(Q1): slight catch - in the case of the
312 // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
313 // channels might happen!
314 m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
315 m_aComponentTags.getArray()[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
317 m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
318 m_aComponentBitCounts.getArray()[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
320 // always add a full byte to the pixel size, otherwise
321 // pixel packing hell breaks loose.
322 m_nBitsPerOutputPixel += 8;
324 // adapt scanline parameters
325 const Size aSize = m_aBitmap.GetSizePixel();
326 m_aLayout.ScanLineBytes =
327 m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
330 VclCanvasBitmap::~VclCanvasBitmap()
334 // XBitmap
335 geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize()
337 SolarMutexGuard aGuard;
338 return integerSize2DFromSize( m_aBitmap.GetSizePixel() );
341 sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha()
343 SolarMutexGuard aGuard;
344 return m_aBmpEx.IsAlpha();
347 uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
348 sal_Bool beFast )
350 SolarMutexGuard aGuard;
352 BitmapEx aNewBmp( m_aBitmap );
353 aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BmpScaleFlag::Default : BmpScaleFlag::BestQuality );
354 return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
357 // XIntegerReadOnlyBitmap
358 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
359 const geometry::IntegerRectangle2D& rect )
361 SolarMutexGuard aGuard;
363 bitmapLayout = getMemoryLayout();
365 const ::tools::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
366 if( aRequestedArea.IsEmpty() )
367 return uno::Sequence< sal_Int8 >();
369 // Invalid/empty bitmap: no data available
370 if( !m_pBmpAcc )
371 throw lang::IndexOutOfBoundsException();
372 if( m_aBmpEx.IsAlpha() && !m_pAlphaAcc )
373 throw lang::IndexOutOfBoundsException();
375 if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
376 aRequestedArea.Right() > m_pBmpAcc->Width() ||
377 aRequestedArea.Bottom() > m_pBmpAcc->Height() )
379 throw lang::IndexOutOfBoundsException();
382 uno::Sequence< sal_Int8 > aRet;
383 tools::Rectangle aRequestedBytes( aRequestedArea );
385 // adapt to byte boundaries
386 aRequestedBytes.SetLeft( aRequestedArea.Left()*m_nBitsPerOutputPixel/8 );
387 aRequestedBytes.SetRight( (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8 );
389 // copy stuff to output sequence
390 aRet.realloc(aRequestedBytes.getOpenWidth()*aRequestedBytes.getOpenHeight());
391 sal_Int8* pOutBuf = aRet.getArray();
393 bitmapLayout.ScanLines = aRequestedBytes.getOpenHeight();
394 bitmapLayout.ScanLineBytes =
395 bitmapLayout.ScanLineStride= aRequestedBytes.getOpenWidth();
397 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
398 if (m_pBmpAcc->IsBottomUp())
400 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getOpenHeight()-1);
401 nScanlineStride *= -1;
404 if( !m_aBmpEx.IsAlpha() )
406 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
407 OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
409 // can return bitmap data as-is
410 for( tools::Long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
412 Scanline pScan = pBmpAcc->GetScanline(y);
413 memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getOpenWidth());
414 pOutBuf += nScanlineStride;
417 else
419 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
420 BitmapScopedReadAccess& pAlphaAcc = getAlphaReadAccess();
421 OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
422 OSL_ENSURE(pAlphaAcc,"Invalid alpha read access");
424 // interleave alpha with bitmap data - note, bitcount is
425 // always integer multiple of 8
426 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
427 "Transparent bitmap bitcount not integer multiple of 8" );
429 for( tools::Long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
431 sal_Int8* pOutScan = pOutBuf;
433 if( m_nBitsPerInputPixel < 8 )
435 // input less than a byte - copy via GetPixel()
436 for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
438 *pOutScan++ = pBmpAcc->GetPixelIndex(y,x);
439 // vcl used to store transparency. Now it stores alpha. But we need the UNO
440 // interface to still preserve the old interface.
441 *pOutScan++ = 255 - pAlphaAcc->GetPixelIndex(y,x);
444 else
446 const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
447 const tools::Long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
448 Scanline pScan = pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
449 Scanline pScanlineAlpha = pAlphaAcc->GetScanline( y );
451 // input integer multiple of byte - copy directly
452 for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
454 for( tools::Long i=0; i<nNonAlphaBytes; ++i )
455 *pOutScan++ = *pScan++;
456 // vcl used to store transparency. Now it stores alpha. But we need the UNO
457 // interface to still preserve the old interface.
458 *pOutScan++ = 255 - pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
462 pOutBuf += nScanlineStride;
466 return aRet;
469 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
470 const geometry::IntegerPoint2D& pos )
472 SolarMutexGuard aGuard;
474 bitmapLayout = getMemoryLayout();
476 // Invalid/empty bitmap: no data available
477 if( !m_pBmpAcc )
478 throw lang::IndexOutOfBoundsException();
479 if( m_aBmpEx.IsAlpha() && !m_pAlphaAcc )
480 throw lang::IndexOutOfBoundsException();
482 if( pos.X < 0 || pos.Y < 0 ||
483 pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
485 throw lang::IndexOutOfBoundsException();
488 uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
489 sal_Int8* pOutBuf = aRet.getArray();
491 // copy stuff to output sequence
492 bitmapLayout.ScanLines = 1;
493 bitmapLayout.ScanLineBytes =
494 bitmapLayout.ScanLineStride= aRet.getLength();
496 const tools::Long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
497 if( !m_aBmpEx.IsAlpha() )
499 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
500 assert(pBmpAcc && "Invalid bmp read access");
502 // can return bitmap data as-is
503 Scanline pScan = pBmpAcc->GetScanline(pos.Y);
504 memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
506 else
508 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
509 BitmapScopedReadAccess& pAlphaAcc = getAlphaReadAccess();
510 assert(pBmpAcc && "Invalid bmp read access");
511 assert(pAlphaAcc && "Invalid alpha read access");
513 // interleave alpha with bitmap data - note, bitcount is
514 // always integer multiple of 8
515 assert((m_nBitsPerOutputPixel & 0x07) == 0 &&
516 "Transparent bitmap bitcount not integer multiple of 8" );
518 if( m_nBitsPerInputPixel < 8 )
520 // input less than a byte - copy via GetPixel()
521 *pOutBuf++ = pBmpAcc->GetPixelIndex(pos.Y,pos.X);
522 // vcl used to store transparency. Now it stores alpha. But we need the UNO
523 // interface to still preserve the old interface.
524 *pOutBuf = 255 - pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
526 else
528 const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
529 Scanline pScan = pBmpAcc->GetScanline(pos.Y);
531 // input integer multiple of byte - copy directly
532 memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
533 pOutBuf += nNonAlphaBytes;
534 // vcl used to store transparency. Now it stores alpha. But we need the UNO
535 // interface to still preserve the old interface.
536 *pOutBuf++ = 255 - pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
540 return aRet;
543 uno::Reference< rendering::XBitmapPalette > VclCanvasBitmap::getPalette()
545 SolarMutexGuard aGuard;
547 uno::Reference< XBitmapPalette > aRet;
548 if( m_bPalette )
549 aRet.set(this);
551 return aRet;
554 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout()
556 SolarMutexGuard aGuard;
558 rendering::IntegerBitmapLayout aLayout( m_aLayout );
560 // only set references to self on separate copy of
561 // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
562 // a circular reference!
563 if( m_bPalette )
564 aLayout.Palette.set( this );
566 aLayout.ColorSpace.set( this );
568 return aLayout;
571 sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries()
573 SolarMutexGuard aGuard;
575 if( !m_pBmpAcc )
576 return 0;
578 return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ;
581 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex )
583 SolarMutexGuard aGuard;
585 const sal_uInt16 nCount( m_pBmpAcc ?
586 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
587 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
588 if( nIndex < 0 || nIndex >= nCount )
589 throw lang::IndexOutOfBoundsException(u"Palette index out of range"_ustr,
590 static_cast<rendering::XBitmapPalette*>(this));
592 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
593 o_entry.realloc(3);
594 double* pColor=o_entry.getArray();
595 pColor[0] = aCol.GetRed();
596 pColor[1] = aCol.GetGreen();
597 pColor[2] = aCol.GetBlue();
599 return true; // no palette transparency here.
602 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex )
604 SolarMutexGuard aGuard;
606 const sal_uInt16 nCount( m_pBmpAcc ?
607 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
609 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
610 if( nIndex < 0 || nIndex >= nCount )
611 throw lang::IndexOutOfBoundsException(u"Palette index out of range"_ustr,
612 static_cast<rendering::XBitmapPalette*>(this));
614 return false; // read-only implementation
617 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( )
619 // this is the method from XBitmapPalette. Return palette color
620 // space here
621 static uno::Reference<rendering::XColorSpace> gColorSpace = vcl::unotools::createStandardColorSpace();
622 return gColorSpace;
625 sal_Int8 SAL_CALL VclCanvasBitmap::getType( )
627 return rendering::ColorSpaceType::RGB;
630 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( )
632 SolarMutexGuard aGuard;
633 return m_aComponentTags;
636 sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent( )
638 return rendering::RenderingIntent::PERCEPTUAL;
641 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( )
643 return uno::Sequence< ::beans::PropertyValue >();
646 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
647 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
649 // TODO(P3): if we know anything about target
650 // colorspace, this can be greatly sped up
651 uno::Sequence<rendering::ARGBColor> aIntermediate(
652 convertToARGB(deviceColor));
653 return targetColorSpace->convertFromARGB(aIntermediate);
656 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor )
658 SolarMutexGuard aGuard;
660 const std::size_t nLen( deviceColor.getLength() );
661 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
662 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
663 "number of channels no multiple of pixel element count",
664 static_cast<rendering::XBitmapPalette*>(this), 01);
666 uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
667 rendering::RGBColor* pOut( aRes.getArray() );
669 if( m_bPalette )
671 OSL_ENSURE(m_nIndexIndex != -1,
672 "Invalid color channel indices");
673 ENSURE_OR_THROW(m_pBmpAcc,
674 "Unable to get BitmapAccess");
676 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
678 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
679 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
681 // TODO(F3): Convert result to sRGB color space
682 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
683 toDoubleColor(aCol.GetGreen()),
684 toDoubleColor(aCol.GetBlue()));
687 else
689 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
690 "Invalid color channel indices");
692 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
694 // TODO(F3): Convert result to sRGB color space
695 *pOut++ = rendering::RGBColor(
696 deviceColor[i+m_nRedIndex],
697 deviceColor[i+m_nGreenIndex],
698 deviceColor[i+m_nBlueIndex]);
702 return aRes;
705 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor )
707 SolarMutexGuard aGuard;
709 const std::size_t nLen( deviceColor.getLength() );
710 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
711 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
712 "number of channels no multiple of pixel element count",
713 static_cast<rendering::XBitmapPalette*>(this), 01);
715 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
716 rendering::ARGBColor* pOut( aRes.getArray() );
718 if( m_bPalette )
720 OSL_ENSURE(m_nIndexIndex != -1,
721 "Invalid color channel indices");
722 ENSURE_OR_THROW(m_pBmpAcc,
723 "Unable to get BitmapAccess");
725 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
727 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
728 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
730 // TODO(F3): Convert result to sRGB color space
731 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
732 *pOut++ = rendering::ARGBColor(nAlpha,
733 toDoubleColor(aCol.GetRed()),
734 toDoubleColor(aCol.GetGreen()),
735 toDoubleColor(aCol.GetBlue()));
738 else
740 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
741 "Invalid color channel indices");
743 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
745 // TODO(F3): Convert result to sRGB color space
746 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
747 *pOut++ = rendering::ARGBColor(
748 nAlpha,
749 deviceColor[i+m_nRedIndex],
750 deviceColor[i+m_nGreenIndex],
751 deviceColor[i+m_nBlueIndex]);
755 return aRes;
758 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor )
760 SolarMutexGuard aGuard;
762 const std::size_t nLen( deviceColor.getLength() );
763 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
764 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
765 "number of channels no multiple of pixel element count",
766 static_cast<rendering::XBitmapPalette*>(this), 01);
768 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
769 rendering::ARGBColor* pOut( aRes.getArray() );
771 if( m_bPalette )
773 OSL_ENSURE(m_nIndexIndex != -1,
774 "Invalid color channel indices");
775 ENSURE_OR_THROW(m_pBmpAcc,
776 "Unable to get BitmapAccess");
778 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
780 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
781 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
783 // TODO(F3): Convert result to sRGB color space
784 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
785 *pOut++ = rendering::ARGBColor(nAlpha,
786 nAlpha*toDoubleColor(aCol.GetRed()),
787 nAlpha*toDoubleColor(aCol.GetGreen()),
788 nAlpha*toDoubleColor(aCol.GetBlue()));
791 else
793 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
794 "Invalid color channel indices");
796 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
798 // TODO(F3): Convert result to sRGB color space
799 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
800 *pOut++ = rendering::ARGBColor(
801 nAlpha,
802 nAlpha*deviceColor[i+m_nRedIndex],
803 nAlpha*deviceColor[i+m_nGreenIndex],
804 nAlpha*deviceColor[i+m_nBlueIndex]);
808 return aRes;
811 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
813 SolarMutexGuard aGuard;
815 const std::size_t nLen( rgbColor.getLength() );
816 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
818 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
819 double* pColors=aRes.getArray();
821 if( m_bPalette )
823 for( const auto& rIn : rgbColor )
825 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
826 BitmapColor(toByteColor(rIn.Red),
827 toByteColor(rIn.Green),
828 toByteColor(rIn.Blue)));
829 if( m_nAlphaIndex != -1 )
830 pColors[m_nAlphaIndex] = 1.0;
832 pColors += nComponentsPerPixel;
835 else
837 for( const auto& rIn : rgbColor )
839 pColors[m_nRedIndex] = rIn.Red;
840 pColors[m_nGreenIndex] = rIn.Green;
841 pColors[m_nBlueIndex] = rIn.Blue;
842 if( m_nAlphaIndex != -1 )
843 pColors[m_nAlphaIndex] = 1.0;
845 pColors += nComponentsPerPixel;
848 return aRes;
851 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
853 SolarMutexGuard aGuard;
855 const std::size_t nLen( rgbColor.getLength() );
856 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
858 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
859 double* pColors=aRes.getArray();
861 if( m_bPalette )
863 for( const auto& rIn : rgbColor )
865 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
866 BitmapColor(toByteColor(rIn.Red),
867 toByteColor(rIn.Green),
868 toByteColor(rIn.Blue)));
869 if( m_nAlphaIndex != -1 )
870 pColors[m_nAlphaIndex] = rIn.Alpha;
872 pColors += nComponentsPerPixel;
875 else
877 for( const auto& rIn : rgbColor )
879 pColors[m_nRedIndex] = rIn.Red;
880 pColors[m_nGreenIndex] = rIn.Green;
881 pColors[m_nBlueIndex] = rIn.Blue;
882 if( m_nAlphaIndex != -1 )
883 pColors[m_nAlphaIndex] = rIn.Alpha;
885 pColors += nComponentsPerPixel;
888 return aRes;
891 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
893 SolarMutexGuard aGuard;
895 const std::size_t nLen( rgbColor.getLength() );
896 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
898 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
899 double* pColors=aRes.getArray();
901 if( m_bPalette )
903 for( const auto& rIn : rgbColor )
905 const double nAlpha( rIn.Alpha );
906 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
907 BitmapColor(toByteColor(rIn.Red / nAlpha),
908 toByteColor(rIn.Green / nAlpha),
909 toByteColor(rIn.Blue / nAlpha)));
910 if( m_nAlphaIndex != -1 )
911 pColors[m_nAlphaIndex] = nAlpha;
913 pColors += nComponentsPerPixel;
916 else
918 for( const auto& rIn : rgbColor )
920 const double nAlpha( rIn.Alpha );
921 pColors[m_nRedIndex] = rIn.Red / nAlpha;
922 pColors[m_nGreenIndex] = rIn.Green / nAlpha;
923 pColors[m_nBlueIndex] = rIn.Blue / nAlpha;
924 if( m_nAlphaIndex != -1 )
925 pColors[m_nAlphaIndex] = nAlpha;
927 pColors += nComponentsPerPixel;
930 return aRes;
933 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( )
935 return m_nBitsPerOutputPixel;
938 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( )
940 return m_aComponentBitCounts;
943 sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness( )
945 return util::Endianness::LITTLE;
948 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
949 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
951 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
953 SolarMutexGuard aGuard;
955 const std::size_t nLen( deviceColor.getLength() );
956 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
957 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
958 "number of channels no multiple of pixel element count",
959 static_cast<rendering::XBitmapPalette*>(this), 01);
961 uno::Sequence<double> aRes(nLen);
962 double* pOut( aRes.getArray() );
964 if( m_bPalette )
966 OSL_ENSURE(m_nIndexIndex != -1,
967 "Invalid color channel indices");
968 ENSURE_OR_THROW(m_pBmpAcc,
969 "Unable to get BitmapAccess");
971 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
973 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
974 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
976 // TODO(F3): Convert result to sRGB color space
977 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
978 *pOut++ = toDoubleColor(aCol.GetRed());
979 *pOut++ = toDoubleColor(aCol.GetGreen());
980 *pOut++ = toDoubleColor(aCol.GetBlue());
981 *pOut++ = nAlpha;
984 else
986 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
987 "Invalid color channel indices");
989 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
991 // TODO(F3): Convert result to sRGB color space
992 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
993 *pOut++ = deviceColor[i+m_nRedIndex];
994 *pOut++ = deviceColor[i+m_nGreenIndex];
995 *pOut++ = deviceColor[i+m_nBlueIndex];
996 *pOut++ = nAlpha;
1000 return aRes;
1002 else
1004 // TODO(P3): if we know anything about target
1005 // colorspace, this can be greatly sped up
1006 uno::Sequence<rendering::ARGBColor> aIntermediate(
1007 convertIntegerToARGB(deviceColor));
1008 return targetColorSpace->convertFromARGB(aIntermediate);
1012 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1013 const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace )
1015 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1017 // it's us, so simply pass-through the data
1018 return deviceColor;
1020 else
1022 // TODO(P3): if we know anything about target
1023 // colorspace, this can be greatly sped up
1024 uno::Sequence<rendering::ARGBColor> aIntermediate(
1025 convertIntegerToARGB(deviceColor));
1026 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1030 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1032 SolarMutexGuard aGuard;
1034 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1035 const std::size_t nLen( deviceColor.getLength() );
1036 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1038 uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1039 rendering::RGBColor* pOut( aRes.getArray() );
1041 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
1042 ENSURE_OR_THROW(pBmpAcc,
1043 "Unable to get BitmapAccess");
1045 if( m_aBmpEx.IsAlpha() )
1047 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1048 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1050 // if palette, index is guaranteed to be 8 bit
1051 const BitmapColor aCol =
1052 m_bPalette ?
1053 pBmpAcc->GetPaletteColor(*pIn) :
1054 pBmpAcc->GetPixelFromData(pIn,0);
1056 // TODO(F3): Convert result to sRGB color space
1057 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1058 toDoubleColor(aCol.GetGreen()),
1059 toDoubleColor(aCol.GetBlue()));
1060 // skips alpha
1061 pIn += nBytesPerPixel;
1064 else
1066 for( sal_Int32 i=0; i<nNumColors; ++i )
1068 const BitmapColor aCol =
1069 m_bPalette ?
1070 pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
1071 pBmpAcc->GetPixelFromData(pIn, i);
1073 // TODO(F3): Convert result to sRGB color space
1074 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1075 toDoubleColor(aCol.GetGreen()),
1076 toDoubleColor(aCol.GetBlue()));
1080 return aRes;
1083 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1085 SolarMutexGuard aGuard;
1087 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1088 const std::size_t nLen( deviceColor.getLength() );
1089 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1091 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1092 rendering::ARGBColor* pOut( aRes.getArray() );
1094 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
1095 ENSURE_OR_THROW(pBmpAcc,
1096 "Unable to get BitmapAccess");
1098 if( m_aBmpEx.IsAlpha() )
1100 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1101 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1102 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1104 // if palette, index is guaranteed to be 8 bit
1105 const BitmapColor aCol =
1106 m_bPalette ?
1107 pBmpAcc->GetPaletteColor(*pIn) :
1108 pBmpAcc->GetPixelFromData(pIn,0);
1110 // TODO(F3): Convert result to sRGB color space
1111 *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(pIn[nNonAlphaBytes]),
1112 toDoubleColor(aCol.GetRed()),
1113 toDoubleColor(aCol.GetGreen()),
1114 toDoubleColor(aCol.GetBlue()));
1115 pIn += nBytesPerPixel;
1118 else
1120 for( sal_Int32 i=0; i<nNumColors; ++i )
1122 const BitmapColor aCol =
1123 m_bPalette ?
1124 pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1125 pBmpAcc->GetPixelFromData(pIn, i);
1127 // TODO(F3): Convert result to sRGB color space
1128 *pOut++ = rendering::ARGBColor(1.0,
1129 toDoubleColor(aCol.GetRed()),
1130 toDoubleColor(aCol.GetGreen()),
1131 toDoubleColor(aCol.GetBlue()));
1135 return aRes;
1138 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1140 SolarMutexGuard aGuard;
1142 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1143 const std::size_t nLen( deviceColor.getLength() );
1144 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1146 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1147 rendering::ARGBColor* pOut( aRes.getArray() );
1149 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
1150 ENSURE_OR_THROW(pBmpAcc,
1151 "Unable to get BitmapAccess");
1153 if( m_aBmpEx.IsAlpha() )
1155 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1156 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1157 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1159 // if palette, index is guaranteed to be 8 bit
1160 const BitmapColor aCol =
1161 m_bPalette ?
1162 pBmpAcc->GetPaletteColor(*pIn) :
1163 pBmpAcc->GetPixelFromData(pIn,0);
1165 // TODO(F3): Convert result to sRGB color space
1166 const double nAlpha( 1.0 - toDoubleColor(pIn[nNonAlphaBytes]) );
1167 *pOut++ = rendering::ARGBColor(nAlpha,
1168 nAlpha*toDoubleColor(aCol.GetRed()),
1169 nAlpha*toDoubleColor(aCol.GetGreen()),
1170 nAlpha*toDoubleColor(aCol.GetBlue()));
1171 pIn += nBytesPerPixel;
1174 else
1176 for( sal_Int32 i=0; i<nNumColors; ++i )
1178 const BitmapColor aCol =
1179 m_bPalette ?
1180 pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1181 pBmpAcc->GetPixelFromData(pIn, i);
1183 // TODO(F3): Convert result to sRGB color space
1184 *pOut++ = rendering::ARGBColor(1.0,
1185 toDoubleColor(aCol.GetRed()),
1186 toDoubleColor(aCol.GetGreen()),
1187 toDoubleColor(aCol.GetBlue()));
1191 return aRes;
1194 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
1196 SolarMutexGuard aGuard;
1198 const std::size_t nLen( rgbColor.getLength() );
1199 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1201 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1202 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1203 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
1205 if( m_aBmpEx.IsAlpha() )
1207 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1208 for( std::size_t i=0; i<nLen; ++i )
1210 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1211 toByteColor(rgbColor[i].Green),
1212 toByteColor(rgbColor[i].Blue));
1213 const BitmapColor aCol2 =
1214 m_bPalette ?
1215 BitmapColor(
1216 sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1217 aCol;
1219 pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1220 pColors += nNonAlphaBytes;
1221 *pColors++ = sal_uInt8(255);
1224 else
1226 for( std::size_t i=0; i<nLen; ++i )
1228 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1229 toByteColor(rgbColor[i].Green),
1230 toByteColor(rgbColor[i].Blue));
1231 const BitmapColor aCol2 =
1232 m_bPalette ?
1233 BitmapColor(
1234 sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1235 aCol;
1237 pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1241 return aRes;
1244 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1246 SolarMutexGuard aGuard;
1248 const std::size_t nLen( rgbColor.getLength() );
1249 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1251 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1252 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1253 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
1255 if( m_aBmpEx.IsAlpha() )
1257 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1258 for( std::size_t i=0; i<nLen; ++i )
1260 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1261 toByteColor(rgbColor[i].Green),
1262 toByteColor(rgbColor[i].Blue));
1263 const BitmapColor aCol2 =
1264 m_bPalette ?
1265 BitmapColor(
1266 sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1267 aCol;
1269 pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1270 pColors += nNonAlphaBytes;
1271 *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1274 else
1276 for( std::size_t i=0; i<nLen; ++i )
1278 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1279 toByteColor(rgbColor[i].Green),
1280 toByteColor(rgbColor[i].Blue));
1281 const BitmapColor aCol2 =
1282 m_bPalette ?
1283 BitmapColor(
1284 sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1285 aCol;
1287 pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1291 return aRes;
1294 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1296 SolarMutexGuard aGuard;
1298 const std::size_t nLen( rgbColor.getLength() );
1299 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1301 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1302 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1303 BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
1305 if( m_aBmpEx.IsAlpha() )
1307 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1308 for( std::size_t i=0; i<nLen; ++i )
1310 const double nAlpha( rgbColor[i].Alpha );
1311 const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1312 toByteColor(rgbColor[i].Green / nAlpha),
1313 toByteColor(rgbColor[i].Blue / nAlpha));
1314 const BitmapColor aCol2 =
1315 m_bPalette ?
1316 BitmapColor(
1317 sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1318 aCol;
1320 pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1321 pColors += nNonAlphaBytes;
1322 *pColors++ = 255 - toByteColor(nAlpha);
1325 else
1327 for( std::size_t i=0; i<nLen; ++i )
1329 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1330 toByteColor(rgbColor[i].Green),
1331 toByteColor(rgbColor[i].Blue));
1332 const BitmapColor aCol2 =
1333 m_bPalette ?
1334 BitmapColor(
1335 sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1336 aCol;
1338 pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1342 return aRes;
1346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */