nss: upgrade to release 3.73
[LibreOffice.git] / vcl / source / helper / canvasbitmap.cxx
blobb323c8654a59e440ff82543782cf7524e00c428a
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 <rtl/instance.hxx>
30 #include <tools/diagnose_ex.h>
31 #include <canvasbitmap.hxx>
32 #include <vcl/canvastools.hxx>
33 #include <vcl/bitmapaccess.hxx>
34 #include <vcl/svapp.hxx>
36 #include <algorithm>
38 using namespace vcl::unotools;
39 using namespace ::com::sun::star;
41 namespace
43 // TODO(Q3): move to o3tl bithacks or somesuch. A similar method is in canvas/canvastools.hxx
45 // Good ole HAKMEM tradition. Calc number of 1 bits in 32bit word,
46 // unrolled loop. See e.g. Hackers Delight, p. 66
47 sal_Int32 bitcount( sal_uInt32 val )
49 val = val - ((val >> 1) & 0x55555555);
50 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
51 val = (val + (val >> 4)) & 0x0F0F0F0F;
52 val = val + (val >> 8);
53 val = val + (val >> 16);
54 return sal_Int32(val & 0x0000003F);
58 void VclCanvasBitmap::setComponentInfo( sal_uInt32 redShift, sal_uInt32 greenShift, sal_uInt32 blueShift )
60 // sort channels in increasing order of appearance in the pixel
61 // (starting with the least significant bits)
62 sal_Int8 redPos(0);
63 sal_Int8 greenPos(1);
64 sal_Int8 bluePos(2);
66 if( redShift > greenShift )
68 std::swap(redPos,greenPos);
69 if( redShift > blueShift )
71 std::swap(redPos,bluePos);
72 if( greenShift > blueShift )
73 std::swap(greenPos,bluePos);
76 else
78 if( greenShift > blueShift )
80 std::swap(greenPos,bluePos);
81 if( redShift > blueShift )
82 std::swap(redPos,bluePos);
86 m_aComponentTags.realloc(3);
87 sal_Int8* pTags = m_aComponentTags.getArray();
88 pTags[redPos] = rendering::ColorComponentTag::RGB_RED;
89 pTags[greenPos] = rendering::ColorComponentTag::RGB_GREEN;
90 pTags[bluePos] = rendering::ColorComponentTag::RGB_BLUE;
92 m_aComponentBitCounts.realloc(3);
93 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
94 pCounts[redPos] = bitcount(redShift);
95 pCounts[greenPos] = bitcount(greenShift);
96 pCounts[bluePos] = bitcount(blueShift);
99 VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
100 m_aBmpEx( rBitmap ),
101 m_aBitmap( rBitmap.GetBitmap() ),
102 m_aAlpha(),
103 m_pBmpAcc( m_aBitmap ),
104 m_aComponentTags(),
105 m_aComponentBitCounts(),
106 m_aLayout(),
107 m_nBitsPerInputPixel(0),
108 m_nBitsPerOutputPixel(0),
109 m_nRedIndex(-1),
110 m_nGreenIndex(-1),
111 m_nBlueIndex(-1),
112 m_nAlphaIndex(-1),
113 m_nIndexIndex(-1),
114 m_nEndianness(0),
115 m_bPalette(false)
117 if( m_aBmpEx.IsTransparent() )
119 m_aAlpha = m_aBmpEx.IsAlpha() ? m_aBmpEx.GetAlpha().GetBitmap() : m_aBmpEx.GetMask();
120 m_pAlphaAcc = Bitmap::ScopedReadAccess(m_aAlpha);
123 m_aLayout.ScanLines = 0;
124 m_aLayout.ScanLineBytes = 0;
125 m_aLayout.ScanLineStride = 0;
126 m_aLayout.PlaneStride = 0;
127 m_aLayout.ColorSpace.clear();
128 m_aLayout.Palette.clear();
129 m_aLayout.IsMsbFirst = false;
131 if( !m_pBmpAcc )
132 return;
134 m_aLayout.ScanLines = m_pBmpAcc->Height();
135 m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
136 m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
137 m_aLayout.PlaneStride = 0;
139 switch( m_pBmpAcc->GetScanlineFormat() )
141 case ScanlineFormat::N1BitMsbPal:
142 m_bPalette = true;
143 m_nBitsPerInputPixel = 1;
144 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
145 m_aLayout.IsMsbFirst = true;
146 break;
148 case ScanlineFormat::N1BitLsbPal:
149 m_bPalette = true;
150 m_nBitsPerInputPixel = 1;
151 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
152 m_aLayout.IsMsbFirst = false;
153 break;
155 case ScanlineFormat::N4BitMsnPal:
156 m_bPalette = true;
157 m_nBitsPerInputPixel = 4;
158 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
159 m_aLayout.IsMsbFirst = true;
160 break;
162 case ScanlineFormat::N4BitLsnPal:
163 m_bPalette = true;
164 m_nBitsPerInputPixel = 4;
165 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
166 m_aLayout.IsMsbFirst = false;
167 break;
169 case ScanlineFormat::N8BitPal:
170 m_bPalette = true;
171 m_nBitsPerInputPixel = 8;
172 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
173 m_aLayout.IsMsbFirst = false; // doesn't matter
174 break;
176 case ScanlineFormat::N24BitTcBgr:
177 m_bPalette = false;
178 m_nBitsPerInputPixel = 24;
179 m_nEndianness = util::Endianness::LITTLE;
180 m_aLayout.IsMsbFirst = false; // doesn't matter
181 setComponentInfo( static_cast<sal_uInt32>(0xff0000UL),
182 static_cast<sal_uInt32>(0x00ff00UL),
183 static_cast<sal_uInt32>(0x0000ffUL) );
184 break;
186 case ScanlineFormat::N24BitTcRgb:
187 m_bPalette = false;
188 m_nBitsPerInputPixel = 24;
189 m_nEndianness = util::Endianness::LITTLE;
190 m_aLayout.IsMsbFirst = false; // doesn't matter
191 setComponentInfo( static_cast<sal_uInt32>(0x0000ffUL),
192 static_cast<sal_uInt32>(0x00ff00UL),
193 static_cast<sal_uInt32>(0xff0000UL) );
194 break;
196 case ScanlineFormat::N32BitTcAbgr:
198 m_bPalette = false;
199 m_nBitsPerInputPixel = 32;
200 m_nEndianness = util::Endianness::LITTLE;
201 m_aLayout.IsMsbFirst = false; // doesn't matter
203 m_aComponentTags.realloc(4);
204 sal_Int8* pTags = m_aComponentTags.getArray();
205 pTags[0] = rendering::ColorComponentTag::ALPHA;
206 pTags[1] = rendering::ColorComponentTag::RGB_BLUE;
207 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
208 pTags[3] = rendering::ColorComponentTag::RGB_RED;
210 m_aComponentBitCounts.realloc(4);
211 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
212 pCounts[0] = 8;
213 pCounts[1] = 8;
214 pCounts[2] = 8;
215 pCounts[3] = 8;
217 m_nRedIndex = 3;
218 m_nGreenIndex = 2;
219 m_nBlueIndex = 1;
220 m_nAlphaIndex = 0;
222 break;
224 case ScanlineFormat::N32BitTcArgb:
226 m_bPalette = false;
227 m_nBitsPerInputPixel = 32;
228 m_nEndianness = util::Endianness::LITTLE;
229 m_aLayout.IsMsbFirst = false; // doesn't matter
231 m_aComponentTags.realloc(4);
232 sal_Int8* pTags = m_aComponentTags.getArray();
233 pTags[0] = rendering::ColorComponentTag::ALPHA;
234 pTags[1] = rendering::ColorComponentTag::RGB_RED;
235 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
236 pTags[3] = rendering::ColorComponentTag::RGB_BLUE;
238 m_aComponentBitCounts.realloc(4);
239 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
240 pCounts[0] = 8;
241 pCounts[1] = 8;
242 pCounts[2] = 8;
243 pCounts[3] = 8;
245 m_nRedIndex = 1;
246 m_nGreenIndex = 2;
247 m_nBlueIndex = 3;
248 m_nAlphaIndex = 0;
250 break;
252 case ScanlineFormat::N32BitTcBgra:
254 m_bPalette = false;
255 m_nBitsPerInputPixel = 32;
256 m_nEndianness = util::Endianness::LITTLE;
257 m_aLayout.IsMsbFirst = false; // doesn't matter
259 m_aComponentTags.realloc(4);
260 sal_Int8* pTags = m_aComponentTags.getArray();
261 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
262 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
263 pTags[2] = rendering::ColorComponentTag::RGB_RED;
264 pTags[3] = rendering::ColorComponentTag::ALPHA;
266 m_aComponentBitCounts.realloc(4);
267 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
268 pCounts[0] = 8;
269 pCounts[1] = 8;
270 pCounts[2] = 8;
271 pCounts[3] = 8;
273 m_nRedIndex = 2;
274 m_nGreenIndex = 1;
275 m_nBlueIndex = 0;
276 m_nAlphaIndex = 3;
278 break;
280 case ScanlineFormat::N32BitTcRgba:
282 m_bPalette = false;
283 m_nBitsPerInputPixel = 32;
284 m_nEndianness = util::Endianness::LITTLE;
285 m_aLayout.IsMsbFirst = false; // doesn't matter
287 m_aComponentTags.realloc(4);
288 sal_Int8* pTags = m_aComponentTags.getArray();
289 pTags[0] = rendering::ColorComponentTag::RGB_RED;
290 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
291 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
292 pTags[3] = rendering::ColorComponentTag::ALPHA;
294 m_aComponentBitCounts.realloc(4);
295 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
296 pCounts[0] = 8;
297 pCounts[1] = 8;
298 pCounts[2] = 8;
299 pCounts[3] = 8;
301 m_nRedIndex = 0;
302 m_nGreenIndex = 1;
303 m_nBlueIndex = 2;
304 m_nAlphaIndex = 3;
306 break;
308 case ScanlineFormat::N32BitTcMask:
309 m_bPalette = false;
310 m_nBitsPerInputPixel = 32;
311 m_nEndianness = util::Endianness::LITTLE;
312 m_aLayout.IsMsbFirst = false; // doesn't matter
313 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
314 m_pBmpAcc->GetColorMask().GetGreenMask(),
315 m_pBmpAcc->GetColorMask().GetBlueMask() );
316 break;
318 default:
319 OSL_FAIL( "unsupported bitmap format" );
320 break;
323 if( m_bPalette )
325 m_aComponentTags.realloc(1);
326 m_aComponentTags[0] = rendering::ColorComponentTag::INDEX;
328 m_aComponentBitCounts.realloc(1);
329 m_aComponentBitCounts[0] = m_nBitsPerInputPixel;
331 m_nIndexIndex = 0;
334 m_nBitsPerOutputPixel = m_nBitsPerInputPixel;
335 if( !m_aBmpEx.IsTransparent() )
336 return;
338 // TODO(P1): need to interleave alpha with bitmap data -
339 // won't fuss with less-than-8 bit for now
340 m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
342 // check whether alpha goes in front or behind the
343 // bitcount sequence. If pixel format is little endian,
344 // put it behind all the other channels. If it's big
345 // endian, put it in front (because later, the actual data
346 // always gets written after the pixel data)
348 // TODO(Q1): slight catch - in the case of the
349 // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
350 // channels might happen!
351 m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
352 m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
354 m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
355 m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
357 if( m_nEndianness == util::Endianness::BIG )
359 // put alpha in front of all the color channels
360 sal_Int8* pTags =m_aComponentTags.getArray();
361 sal_Int32* pCounts=m_aComponentBitCounts.getArray();
362 std::rotate(pTags,
363 pTags+m_aComponentTags.getLength()-1,
364 pTags+m_aComponentTags.getLength());
365 std::rotate(pCounts,
366 pCounts+m_aComponentBitCounts.getLength()-1,
367 pCounts+m_aComponentBitCounts.getLength());
368 ++m_nRedIndex;
369 ++m_nGreenIndex;
370 ++m_nBlueIndex;
371 ++m_nIndexIndex;
372 m_nAlphaIndex=0;
375 // always add a full byte to the pixel size, otherwise
376 // pixel packing hell breaks loose.
377 m_nBitsPerOutputPixel += 8;
379 // adapt scanline parameters
380 const Size aSize = m_aBitmap.GetSizePixel();
381 m_aLayout.ScanLineBytes =
382 m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
385 VclCanvasBitmap::~VclCanvasBitmap()
389 // XBitmap
390 geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize()
392 SolarMutexGuard aGuard;
393 return integerSize2DFromSize( m_aBitmap.GetSizePixel() );
396 sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha()
398 SolarMutexGuard aGuard;
399 return m_aBmpEx.IsTransparent();
402 uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
403 sal_Bool beFast )
405 SolarMutexGuard aGuard;
407 BitmapEx aNewBmp( m_aBitmap );
408 aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BmpScaleFlag::Default : BmpScaleFlag::BestQuality );
409 return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
412 // XIntegerReadOnlyBitmap
413 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
414 const geometry::IntegerRectangle2D& rect )
416 SolarMutexGuard aGuard;
418 bitmapLayout = getMemoryLayout();
420 const ::tools::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
421 if( aRequestedArea.IsEmpty() )
422 return uno::Sequence< sal_Int8 >();
424 // Invalid/empty bitmap: no data available
425 if( !m_pBmpAcc )
426 throw lang::IndexOutOfBoundsException();
427 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
428 throw lang::IndexOutOfBoundsException();
430 if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
431 aRequestedArea.Right() > m_pBmpAcc->Width() ||
432 aRequestedArea.Bottom() > m_pBmpAcc->Height() )
434 throw lang::IndexOutOfBoundsException();
437 uno::Sequence< sal_Int8 > aRet;
438 tools::Rectangle aRequestedBytes( aRequestedArea );
440 // adapt to byte boundaries
441 aRequestedBytes.SetLeft( aRequestedArea.Left()*m_nBitsPerOutputPixel/8 );
442 aRequestedBytes.SetRight( (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8 );
444 // copy stuff to output sequence
445 aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight());
446 sal_Int8* pOutBuf = aRet.getArray();
448 bitmapLayout.ScanLines = aRequestedBytes.getHeight();
449 bitmapLayout.ScanLineBytes =
450 bitmapLayout.ScanLineStride= aRequestedBytes.getWidth();
452 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
453 if( !(m_pBmpAcc->GetScanlineFormat() & ScanlineFormat::TopDown) )
455 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1);
456 nScanlineStride *= -1;
459 if( !m_aBmpEx.IsTransparent() )
461 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
463 // can return bitmap data as-is
464 for( tools::Long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
466 Scanline pScan = m_pBmpAcc->GetScanline(y);
467 memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
468 pOutBuf += nScanlineStride;
471 else
473 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
474 OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
476 // interleave alpha with bitmap data - note, bitcount is
477 // always integer multiple of 8
478 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
479 "Transparent bitmap bitcount not integer multiple of 8" );
481 for( tools::Long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
483 sal_Int8* pOutScan = pOutBuf;
485 if( m_nBitsPerInputPixel < 8 )
487 // input less than a byte - copy via GetPixel()
488 for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
490 *pOutScan++ = m_pBmpAcc->GetPixelIndex(y,x);
491 *pOutScan++ = m_pAlphaAcc->GetPixelIndex(y,x);
494 else
496 const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
497 const tools::Long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
498 Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
499 Scanline pScanlineAlpha = m_pAlphaAcc->GetScanline( y );
501 // input integer multiple of byte - copy directly
502 for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
504 for( tools::Long i=0; i<nNonAlphaBytes; ++i )
505 *pOutScan++ = *pScan++;
506 *pOutScan++ = m_pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
510 pOutBuf += nScanlineStride;
514 return aRet;
517 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
518 const geometry::IntegerPoint2D& pos )
520 SolarMutexGuard aGuard;
522 bitmapLayout = getMemoryLayout();
524 // Invalid/empty bitmap: no data available
525 if( !m_pBmpAcc )
526 throw lang::IndexOutOfBoundsException();
527 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
528 throw lang::IndexOutOfBoundsException();
530 if( pos.X < 0 || pos.Y < 0 ||
531 pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
533 throw lang::IndexOutOfBoundsException();
536 uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
537 sal_Int8* pOutBuf = aRet.getArray();
539 // copy stuff to output sequence
540 bitmapLayout.ScanLines = 1;
541 bitmapLayout.ScanLineBytes =
542 bitmapLayout.ScanLineStride= aRet.getLength();
544 const tools::Long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
545 if( !m_aBmpEx.IsTransparent() )
547 assert(m_pBmpAcc && "Invalid bmp read access");
549 // can return bitmap data as-is
550 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
551 memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
553 else
555 assert(m_pBmpAcc && "Invalid bmp read access");
556 assert(m_pAlphaAcc && "Invalid alpha read access");
558 // interleave alpha with bitmap data - note, bitcount is
559 // always integer multiple of 8
560 assert((m_nBitsPerOutputPixel & 0x07) == 0 &&
561 "Transparent bitmap bitcount not integer multiple of 8" );
563 if( m_nBitsPerInputPixel < 8 )
565 // input less than a byte - copy via GetPixel()
566 *pOutBuf++ = m_pBmpAcc->GetPixelIndex(pos.Y,pos.X);
567 *pOutBuf = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
569 else
571 const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
572 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
574 // input integer multiple of byte - copy directly
575 memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
576 pOutBuf += nNonAlphaBytes;
577 *pOutBuf++ = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
581 return aRet;
584 uno::Reference< rendering::XBitmapPalette > VclCanvasBitmap::getPalette()
586 SolarMutexGuard aGuard;
588 uno::Reference< XBitmapPalette > aRet;
589 if( m_bPalette )
590 aRet.set(this);
592 return aRet;
595 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout()
597 SolarMutexGuard aGuard;
599 rendering::IntegerBitmapLayout aLayout( m_aLayout );
601 // only set references to self on separate copy of
602 // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
603 // a circular reference!
604 if( m_bPalette )
605 aLayout.Palette.set( this );
607 aLayout.ColorSpace.set( this );
609 return aLayout;
612 sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries()
614 SolarMutexGuard aGuard;
616 if( !m_pBmpAcc )
617 return 0;
619 return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ;
622 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex )
624 SolarMutexGuard aGuard;
626 const sal_uInt16 nCount( m_pBmpAcc ?
627 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
628 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
629 if( nIndex < 0 || nIndex >= nCount )
630 throw lang::IndexOutOfBoundsException("Palette index out of range",
631 static_cast<rendering::XBitmapPalette*>(this));
633 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
634 o_entry.realloc(3);
635 double* pColor=o_entry.getArray();
636 pColor[0] = aCol.GetRed();
637 pColor[1] = aCol.GetGreen();
638 pColor[2] = aCol.GetBlue();
640 return true; // no palette transparency here.
643 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex )
645 SolarMutexGuard aGuard;
647 const sal_uInt16 nCount( m_pBmpAcc ?
648 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
650 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
651 if( nIndex < 0 || nIndex >= nCount )
652 throw lang::IndexOutOfBoundsException("Palette index out of range",
653 static_cast<rendering::XBitmapPalette*>(this));
655 return false; // read-only implementation
658 namespace
660 struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
661 PaletteColorSpaceHolder>
663 uno::Reference<rendering::XColorSpace> operator()()
665 return vcl::unotools::createStandardColorSpace();
670 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( )
672 // this is the method from XBitmapPalette. Return palette color
673 // space here
674 return PaletteColorSpaceHolder::get();
677 sal_Int8 SAL_CALL VclCanvasBitmap::getType( )
679 return rendering::ColorSpaceType::RGB;
682 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( )
684 SolarMutexGuard aGuard;
685 return m_aComponentTags;
688 sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent( )
690 return rendering::RenderingIntent::PERCEPTUAL;
693 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( )
695 return uno::Sequence< ::beans::PropertyValue >();
698 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
699 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
701 // TODO(P3): if we know anything about target
702 // colorspace, this can be greatly sped up
703 uno::Sequence<rendering::ARGBColor> aIntermediate(
704 convertToARGB(deviceColor));
705 return targetColorSpace->convertFromARGB(aIntermediate);
708 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor )
710 SolarMutexGuard aGuard;
712 const std::size_t nLen( deviceColor.getLength() );
713 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
714 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
715 "number of channels no multiple of pixel element count",
716 static_cast<rendering::XBitmapPalette*>(this), 01);
718 uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
719 rendering::RGBColor* pOut( aRes.getArray() );
721 if( m_bPalette )
723 OSL_ENSURE(m_nIndexIndex != -1,
724 "Invalid color channel indices");
725 ENSURE_OR_THROW(m_pBmpAcc,
726 "Unable to get BitmapAccess");
728 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
730 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
731 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
733 // TODO(F3): Convert result to sRGB color space
734 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
735 toDoubleColor(aCol.GetGreen()),
736 toDoubleColor(aCol.GetBlue()));
739 else
741 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
742 "Invalid color channel indices");
744 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
746 // TODO(F3): Convert result to sRGB color space
747 *pOut++ = rendering::RGBColor(
748 deviceColor[i+m_nRedIndex],
749 deviceColor[i+m_nGreenIndex],
750 deviceColor[i+m_nBlueIndex]);
754 return aRes;
757 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor )
759 SolarMutexGuard aGuard;
761 const std::size_t nLen( deviceColor.getLength() );
762 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
763 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
764 "number of channels no multiple of pixel element count",
765 static_cast<rendering::XBitmapPalette*>(this), 01);
767 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
768 rendering::ARGBColor* pOut( aRes.getArray() );
770 if( m_bPalette )
772 OSL_ENSURE(m_nIndexIndex != -1,
773 "Invalid color channel indices");
774 ENSURE_OR_THROW(m_pBmpAcc,
775 "Unable to get BitmapAccess");
777 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
779 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
780 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
782 // TODO(F3): Convert result to sRGB color space
783 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
784 *pOut++ = rendering::ARGBColor(nAlpha,
785 toDoubleColor(aCol.GetRed()),
786 toDoubleColor(aCol.GetGreen()),
787 toDoubleColor(aCol.GetBlue()));
790 else
792 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
793 "Invalid color channel indices");
795 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
797 // TODO(F3): Convert result to sRGB color space
798 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
799 *pOut++ = rendering::ARGBColor(
800 nAlpha,
801 deviceColor[i+m_nRedIndex],
802 deviceColor[i+m_nGreenIndex],
803 deviceColor[i+m_nBlueIndex]);
807 return aRes;
810 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor )
812 SolarMutexGuard aGuard;
814 const std::size_t nLen( deviceColor.getLength() );
815 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
816 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
817 "number of channels no multiple of pixel element count",
818 static_cast<rendering::XBitmapPalette*>(this), 01);
820 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
821 rendering::ARGBColor* pOut( aRes.getArray() );
823 if( m_bPalette )
825 OSL_ENSURE(m_nIndexIndex != -1,
826 "Invalid color channel indices");
827 ENSURE_OR_THROW(m_pBmpAcc,
828 "Unable to get BitmapAccess");
830 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
832 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
833 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
835 // TODO(F3): Convert result to sRGB color space
836 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
837 *pOut++ = rendering::ARGBColor(nAlpha,
838 nAlpha*toDoubleColor(aCol.GetRed()),
839 nAlpha*toDoubleColor(aCol.GetGreen()),
840 nAlpha*toDoubleColor(aCol.GetBlue()));
843 else
845 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
846 "Invalid color channel indices");
848 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
850 // TODO(F3): Convert result to sRGB color space
851 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
852 *pOut++ = rendering::ARGBColor(
853 nAlpha,
854 nAlpha*deviceColor[i+m_nRedIndex],
855 nAlpha*deviceColor[i+m_nGreenIndex],
856 nAlpha*deviceColor[i+m_nBlueIndex]);
860 return aRes;
863 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
865 SolarMutexGuard aGuard;
867 const std::size_t nLen( rgbColor.getLength() );
868 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
870 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
871 double* pColors=aRes.getArray();
873 if( m_bPalette )
875 for( const auto& rIn : rgbColor )
877 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
878 BitmapColor(toByteColor(rIn.Red),
879 toByteColor(rIn.Green),
880 toByteColor(rIn.Blue)));
881 if( m_nAlphaIndex != -1 )
882 pColors[m_nAlphaIndex] = 1.0;
884 pColors += nComponentsPerPixel;
887 else
889 for( const auto& rIn : rgbColor )
891 pColors[m_nRedIndex] = rIn.Red;
892 pColors[m_nGreenIndex] = rIn.Green;
893 pColors[m_nBlueIndex] = rIn.Blue;
894 if( m_nAlphaIndex != -1 )
895 pColors[m_nAlphaIndex] = 1.0;
897 pColors += nComponentsPerPixel;
900 return aRes;
903 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
905 SolarMutexGuard aGuard;
907 const std::size_t nLen( rgbColor.getLength() );
908 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
910 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
911 double* pColors=aRes.getArray();
913 if( m_bPalette )
915 for( const auto& rIn : rgbColor )
917 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
918 BitmapColor(toByteColor(rIn.Red),
919 toByteColor(rIn.Green),
920 toByteColor(rIn.Blue)));
921 if( m_nAlphaIndex != -1 )
922 pColors[m_nAlphaIndex] = rIn.Alpha;
924 pColors += nComponentsPerPixel;
927 else
929 for( const auto& rIn : rgbColor )
931 pColors[m_nRedIndex] = rIn.Red;
932 pColors[m_nGreenIndex] = rIn.Green;
933 pColors[m_nBlueIndex] = rIn.Blue;
934 if( m_nAlphaIndex != -1 )
935 pColors[m_nAlphaIndex] = rIn.Alpha;
937 pColors += nComponentsPerPixel;
940 return aRes;
943 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
945 SolarMutexGuard aGuard;
947 const std::size_t nLen( rgbColor.getLength() );
948 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
950 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
951 double* pColors=aRes.getArray();
953 if( m_bPalette )
955 for( const auto& rIn : rgbColor )
957 const double nAlpha( rIn.Alpha );
958 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
959 BitmapColor(toByteColor(rIn.Red / nAlpha),
960 toByteColor(rIn.Green / nAlpha),
961 toByteColor(rIn.Blue / nAlpha)));
962 if( m_nAlphaIndex != -1 )
963 pColors[m_nAlphaIndex] = nAlpha;
965 pColors += nComponentsPerPixel;
968 else
970 for( const auto& rIn : rgbColor )
972 const double nAlpha( rIn.Alpha );
973 pColors[m_nRedIndex] = rIn.Red / nAlpha;
974 pColors[m_nGreenIndex] = rIn.Green / nAlpha;
975 pColors[m_nBlueIndex] = rIn.Blue / nAlpha;
976 if( m_nAlphaIndex != -1 )
977 pColors[m_nAlphaIndex] = nAlpha;
979 pColors += nComponentsPerPixel;
982 return aRes;
985 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( )
987 SolarMutexGuard aGuard;
988 return m_nBitsPerOutputPixel;
991 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( )
993 SolarMutexGuard aGuard;
994 return m_aComponentBitCounts;
997 sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness( )
999 SolarMutexGuard aGuard;
1000 return m_nEndianness;
1003 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1004 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
1006 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1008 SolarMutexGuard aGuard;
1010 const std::size_t nLen( deviceColor.getLength() );
1011 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1012 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1013 "number of channels no multiple of pixel element count",
1014 static_cast<rendering::XBitmapPalette*>(this), 01);
1016 uno::Sequence<double> aRes(nLen);
1017 double* pOut( aRes.getArray() );
1019 if( m_bPalette )
1021 OSL_ENSURE(m_nIndexIndex != -1,
1022 "Invalid color channel indices");
1023 ENSURE_OR_THROW(m_pBmpAcc,
1024 "Unable to get BitmapAccess");
1026 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1028 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1029 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
1031 // TODO(F3): Convert result to sRGB color space
1032 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1033 *pOut++ = toDoubleColor(aCol.GetRed());
1034 *pOut++ = toDoubleColor(aCol.GetGreen());
1035 *pOut++ = toDoubleColor(aCol.GetBlue());
1036 *pOut++ = nAlpha;
1039 else
1041 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1042 "Invalid color channel indices");
1044 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1046 // TODO(F3): Convert result to sRGB color space
1047 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1048 *pOut++ = deviceColor[i+m_nRedIndex];
1049 *pOut++ = deviceColor[i+m_nGreenIndex];
1050 *pOut++ = deviceColor[i+m_nBlueIndex];
1051 *pOut++ = nAlpha;
1055 return aRes;
1057 else
1059 // TODO(P3): if we know anything about target
1060 // colorspace, this can be greatly sped up
1061 uno::Sequence<rendering::ARGBColor> aIntermediate(
1062 convertIntegerToARGB(deviceColor));
1063 return targetColorSpace->convertFromARGB(aIntermediate);
1067 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1068 const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace )
1070 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1072 // it's us, so simply pass-through the data
1073 return deviceColor;
1075 else
1077 // TODO(P3): if we know anything about target
1078 // colorspace, this can be greatly sped up
1079 uno::Sequence<rendering::ARGBColor> aIntermediate(
1080 convertIntegerToARGB(deviceColor));
1081 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1085 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1087 SolarMutexGuard aGuard;
1089 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1090 const std::size_t nLen( deviceColor.getLength() );
1091 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1093 uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1094 rendering::RGBColor* pOut( aRes.getArray() );
1096 ENSURE_OR_THROW(m_pBmpAcc,
1097 "Unable to get BitmapAccess");
1099 if( m_aBmpEx.IsTransparent() )
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 m_pBmpAcc->GetPaletteColor(*pIn) :
1108 m_pBmpAcc->GetPixelFromData(pIn,0);
1110 // TODO(F3): Convert result to sRGB color space
1111 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1112 toDoubleColor(aCol.GetGreen()),
1113 toDoubleColor(aCol.GetBlue()));
1114 // skips alpha
1115 pIn += nBytesPerPixel;
1118 else
1120 for( sal_Int32 i=0; i<nNumColors; ++i )
1122 const BitmapColor aCol =
1123 m_bPalette ?
1124 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
1125 m_pBmpAcc->GetPixelFromData(pIn, i);
1127 // TODO(F3): Convert result to sRGB color space
1128 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1129 toDoubleColor(aCol.GetGreen()),
1130 toDoubleColor(aCol.GetBlue()));
1134 return aRes;
1137 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1139 SolarMutexGuard aGuard;
1141 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1142 const std::size_t nLen( deviceColor.getLength() );
1143 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1145 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1146 rendering::ARGBColor* pOut( aRes.getArray() );
1148 ENSURE_OR_THROW(m_pBmpAcc,
1149 "Unable to get BitmapAccess");
1151 if( m_aBmpEx.IsTransparent() )
1153 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1154 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1155 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1156 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1158 // if palette, index is guaranteed to be 8 bit
1159 const BitmapColor aCol =
1160 m_bPalette ?
1161 m_pBmpAcc->GetPaletteColor(*pIn) :
1162 m_pBmpAcc->GetPixelFromData(pIn,0);
1164 // TODO(F3): Convert result to sRGB color space
1165 *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1166 toDoubleColor(aCol.GetRed()),
1167 toDoubleColor(aCol.GetGreen()),
1168 toDoubleColor(aCol.GetBlue()));
1169 pIn += nBytesPerPixel;
1172 else
1174 for( sal_Int32 i=0; i<nNumColors; ++i )
1176 const BitmapColor aCol =
1177 m_bPalette ?
1178 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1179 m_pBmpAcc->GetPixelFromData(pIn, i);
1181 // TODO(F3): Convert result to sRGB color space
1182 *pOut++ = rendering::ARGBColor(1.0,
1183 toDoubleColor(aCol.GetRed()),
1184 toDoubleColor(aCol.GetGreen()),
1185 toDoubleColor(aCol.GetBlue()));
1189 return aRes;
1192 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1194 SolarMutexGuard aGuard;
1196 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1197 const std::size_t nLen( deviceColor.getLength() );
1198 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1200 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1201 rendering::ARGBColor* pOut( aRes.getArray() );
1203 ENSURE_OR_THROW(m_pBmpAcc,
1204 "Unable to get BitmapAccess");
1206 if( m_aBmpEx.IsTransparent() )
1208 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1209 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1210 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1211 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1213 // if palette, index is guaranteed to be 8 bit
1214 const BitmapColor aCol =
1215 m_bPalette ?
1216 m_pBmpAcc->GetPaletteColor(*pIn) :
1217 m_pBmpAcc->GetPixelFromData(pIn,0);
1219 // TODO(F3): Convert result to sRGB color space
1220 const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1221 *pOut++ = rendering::ARGBColor(nAlpha,
1222 nAlpha*toDoubleColor(aCol.GetRed()),
1223 nAlpha*toDoubleColor(aCol.GetGreen()),
1224 nAlpha*toDoubleColor(aCol.GetBlue()));
1225 pIn += nBytesPerPixel;
1228 else
1230 for( sal_Int32 i=0; i<nNumColors; ++i )
1232 const BitmapColor aCol =
1233 m_bPalette ?
1234 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1235 m_pBmpAcc->GetPixelFromData(pIn, i);
1237 // TODO(F3): Convert result to sRGB color space
1238 *pOut++ = rendering::ARGBColor(1.0,
1239 toDoubleColor(aCol.GetRed()),
1240 toDoubleColor(aCol.GetGreen()),
1241 toDoubleColor(aCol.GetBlue()));
1245 return aRes;
1248 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
1250 SolarMutexGuard aGuard;
1252 const std::size_t nLen( rgbColor.getLength() );
1253 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1255 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1256 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1258 if( m_aBmpEx.IsTransparent() )
1260 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1261 for( std::size_t i=0; i<nLen; ++i )
1263 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1264 toByteColor(rgbColor[i].Green),
1265 toByteColor(rgbColor[i].Blue));
1266 const BitmapColor aCol2 =
1267 m_bPalette ?
1268 BitmapColor(
1269 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1270 aCol;
1272 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1273 pColors += nNonAlphaBytes;
1274 *pColors++ = sal_uInt8(255);
1277 else
1279 for( std::size_t i=0; i<nLen; ++i )
1281 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1282 toByteColor(rgbColor[i].Green),
1283 toByteColor(rgbColor[i].Blue));
1284 const BitmapColor aCol2 =
1285 m_bPalette ?
1286 BitmapColor(
1287 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1288 aCol;
1290 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1294 return aRes;
1297 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1299 SolarMutexGuard aGuard;
1301 const std::size_t nLen( rgbColor.getLength() );
1302 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1304 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1305 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1307 if( m_aBmpEx.IsTransparent() )
1309 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1310 for( std::size_t i=0; i<nLen; ++i )
1312 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1313 toByteColor(rgbColor[i].Green),
1314 toByteColor(rgbColor[i].Blue));
1315 const BitmapColor aCol2 =
1316 m_bPalette ?
1317 BitmapColor(
1318 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1319 aCol;
1321 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1322 pColors += nNonAlphaBytes;
1323 *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1326 else
1328 for( std::size_t i=0; i<nLen; ++i )
1330 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1331 toByteColor(rgbColor[i].Green),
1332 toByteColor(rgbColor[i].Blue));
1333 const BitmapColor aCol2 =
1334 m_bPalette ?
1335 BitmapColor(
1336 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1337 aCol;
1339 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1343 return aRes;
1346 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1348 SolarMutexGuard aGuard;
1350 const std::size_t nLen( rgbColor.getLength() );
1351 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1353 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1354 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1356 if( m_aBmpEx.IsTransparent() )
1358 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1359 for( std::size_t i=0; i<nLen; ++i )
1361 const double nAlpha( rgbColor[i].Alpha );
1362 const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1363 toByteColor(rgbColor[i].Green / nAlpha),
1364 toByteColor(rgbColor[i].Blue / nAlpha));
1365 const BitmapColor aCol2 =
1366 m_bPalette ?
1367 BitmapColor(
1368 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1369 aCol;
1371 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1372 pColors += nNonAlphaBytes;
1373 *pColors++ = 255 - toByteColor(nAlpha);
1376 else
1378 for( std::size_t i=0; i<nLen; ++i )
1380 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1381 toByteColor(rgbColor[i].Green),
1382 toByteColor(rgbColor[i].Blue));
1383 const BitmapColor aCol2 =
1384 m_bPalette ?
1385 BitmapColor(
1386 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1387 aCol;
1389 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1393 return aRes;
1397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */