build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / helper / canvasbitmap.cxx
blobcbf05245d34314146f504dab6d014703f7a56e1c
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 <com/sun/star/util/Endianness.hpp>
21 #include <com/sun/star/rendering/ColorComponentTag.hpp>
22 #include <com/sun/star/rendering/ColorSpaceType.hpp>
23 #include <com/sun/star/rendering/RenderingIntent.hpp>
25 #include <rtl/instance.hxx>
26 #include <osl/mutex.hxx>
28 #include <tools/diagnose_ex.h>
29 #include <canvasbitmap.hxx>
30 #include <vcl/canvastools.hxx>
31 #include <vcl/bitmapaccess.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 inline 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 VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
98 m_aBmpEx( rBitmap ),
99 m_aBitmap( rBitmap.GetBitmap() ),
100 m_aAlpha(),
101 m_pBmpAcc( m_aBitmap ),
102 m_aComponentTags(),
103 m_aComponentBitCounts(),
104 m_aLayout(),
105 m_nBitsPerInputPixel(0),
106 m_nBitsPerOutputPixel(0),
107 m_nRedIndex(-1),
108 m_nGreenIndex(-1),
109 m_nBlueIndex(-1),
110 m_nAlphaIndex(-1),
111 m_nIndexIndex(-1),
112 m_nEndianness(0),
113 m_bPalette(false)
115 if( m_aBmpEx.IsTransparent() )
117 m_aAlpha = m_aBmpEx.IsAlpha() ? m_aBmpEx.GetAlpha().GetBitmap() : m_aBmpEx.GetMask();
118 m_pAlphaAcc = Bitmap::ScopedReadAccess(m_aAlpha);
121 m_aLayout.ScanLines = 0;
122 m_aLayout.ScanLineBytes = 0;
123 m_aLayout.ScanLineStride = 0;
124 m_aLayout.PlaneStride = 0;
125 m_aLayout.ColorSpace.clear();
126 m_aLayout.Palette.clear();
127 m_aLayout.IsMsbFirst = false;
129 if( m_pBmpAcc )
131 m_aLayout.ScanLines = m_pBmpAcc->Height();
132 m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
133 m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
134 m_aLayout.PlaneStride = 0;
136 switch( m_pBmpAcc->GetScanlineFormat() )
138 case ScanlineFormat::N1BitMsbPal:
139 m_bPalette = true;
140 m_nBitsPerInputPixel = 1;
141 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
142 m_aLayout.IsMsbFirst = true;
143 break;
145 case ScanlineFormat::N1BitLsbPal:
146 m_bPalette = true;
147 m_nBitsPerInputPixel = 1;
148 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
149 m_aLayout.IsMsbFirst = false;
150 break;
152 case ScanlineFormat::N4BitMsnPal:
153 m_bPalette = true;
154 m_nBitsPerInputPixel = 4;
155 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
156 m_aLayout.IsMsbFirst = true;
157 break;
159 case ScanlineFormat::N4BitLsnPal:
160 m_bPalette = true;
161 m_nBitsPerInputPixel = 4;
162 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
163 m_aLayout.IsMsbFirst = false;
164 break;
166 case ScanlineFormat::N8BitPal:
167 m_bPalette = true;
168 m_nBitsPerInputPixel = 8;
169 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
170 m_aLayout.IsMsbFirst = false; // doesn't matter
171 break;
173 case ScanlineFormat::N8BitTcMask:
174 m_bPalette = false;
175 m_nBitsPerInputPixel = 8;
176 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
177 m_aLayout.IsMsbFirst = false; // doesn't matter
178 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
179 m_pBmpAcc->GetColorMask().GetGreenMask(),
180 m_pBmpAcc->GetColorMask().GetBlueMask() );
181 break;
183 case ScanlineFormat::N16BitTcMsbMask:
184 m_bPalette = false;
185 m_nBitsPerInputPixel = 16;
186 m_nEndianness = util::Endianness::BIG;
187 m_aLayout.IsMsbFirst = false; // doesn't matter
188 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
189 m_pBmpAcc->GetColorMask().GetGreenMask(),
190 m_pBmpAcc->GetColorMask().GetBlueMask() );
191 break;
193 case ScanlineFormat::N16BitTcLsbMask:
194 m_bPalette = false;
195 m_nBitsPerInputPixel = 16;
196 m_nEndianness = util::Endianness::LITTLE;
197 m_aLayout.IsMsbFirst = false; // doesn't matter
198 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
199 m_pBmpAcc->GetColorMask().GetGreenMask(),
200 m_pBmpAcc->GetColorMask().GetBlueMask() );
201 break;
203 case ScanlineFormat::N24BitTcBgr:
204 m_bPalette = false;
205 m_nBitsPerInputPixel = 24;
206 m_nEndianness = util::Endianness::LITTLE;
207 m_aLayout.IsMsbFirst = false; // doesn't matter
208 setComponentInfo( static_cast<sal_uInt32>(0xff0000UL),
209 static_cast<sal_uInt32>(0x00ff00UL),
210 static_cast<sal_uInt32>(0x0000ffUL) );
211 break;
213 case ScanlineFormat::N24BitTcRgb:
214 m_bPalette = false;
215 m_nBitsPerInputPixel = 24;
216 m_nEndianness = util::Endianness::LITTLE;
217 m_aLayout.IsMsbFirst = false; // doesn't matter
218 setComponentInfo( static_cast<sal_uInt32>(0x0000ffUL),
219 static_cast<sal_uInt32>(0x00ff00UL),
220 static_cast<sal_uInt32>(0xff0000UL) );
221 break;
223 case ScanlineFormat::N24BitTcMask:
224 m_bPalette = false;
225 m_nBitsPerInputPixel = 24;
226 m_nEndianness = util::Endianness::LITTLE;
227 m_aLayout.IsMsbFirst = false; // doesn't matter
228 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
229 m_pBmpAcc->GetColorMask().GetGreenMask(),
230 m_pBmpAcc->GetColorMask().GetBlueMask() );
231 break;
233 case ScanlineFormat::N32BitTcAbgr:
235 m_bPalette = false;
236 m_nBitsPerInputPixel = 32;
237 m_nEndianness = util::Endianness::LITTLE;
238 m_aLayout.IsMsbFirst = false; // doesn't matter
240 m_aComponentTags.realloc(4);
241 sal_Int8* pTags = m_aComponentTags.getArray();
242 pTags[0] = rendering::ColorComponentTag::ALPHA;
243 pTags[1] = rendering::ColorComponentTag::RGB_BLUE;
244 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
245 pTags[3] = rendering::ColorComponentTag::RGB_RED;
247 m_aComponentBitCounts.realloc(4);
248 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
249 pCounts[0] = 8;
250 pCounts[1] = 8;
251 pCounts[2] = 8;
252 pCounts[3] = 8;
254 m_nRedIndex = 3;
255 m_nGreenIndex = 2;
256 m_nBlueIndex = 1;
257 m_nAlphaIndex = 0;
259 break;
261 case ScanlineFormat::N32BitTcArgb:
263 m_bPalette = false;
264 m_nBitsPerInputPixel = 32;
265 m_nEndianness = util::Endianness::LITTLE;
266 m_aLayout.IsMsbFirst = false; // doesn't matter
268 m_aComponentTags.realloc(4);
269 sal_Int8* pTags = m_aComponentTags.getArray();
270 pTags[0] = rendering::ColorComponentTag::ALPHA;
271 pTags[1] = rendering::ColorComponentTag::RGB_RED;
272 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
273 pTags[3] = rendering::ColorComponentTag::RGB_BLUE;
275 m_aComponentBitCounts.realloc(4);
276 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
277 pCounts[0] = 8;
278 pCounts[1] = 8;
279 pCounts[2] = 8;
280 pCounts[3] = 8;
282 m_nRedIndex = 1;
283 m_nGreenIndex = 2;
284 m_nBlueIndex = 3;
285 m_nAlphaIndex = 0;
287 break;
289 case ScanlineFormat::N32BitTcBgra:
291 m_bPalette = false;
292 m_nBitsPerInputPixel = 32;
293 m_nEndianness = util::Endianness::LITTLE;
294 m_aLayout.IsMsbFirst = false; // doesn't matter
296 m_aComponentTags.realloc(4);
297 sal_Int8* pTags = m_aComponentTags.getArray();
298 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
299 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
300 pTags[2] = rendering::ColorComponentTag::RGB_RED;
301 pTags[3] = rendering::ColorComponentTag::ALPHA;
303 m_aComponentBitCounts.realloc(4);
304 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
305 pCounts[0] = 8;
306 pCounts[1] = 8;
307 pCounts[2] = 8;
308 pCounts[3] = 8;
310 m_nRedIndex = 2;
311 m_nGreenIndex = 1;
312 m_nBlueIndex = 0;
313 m_nAlphaIndex = 3;
315 break;
317 case ScanlineFormat::N32BitTcRgba:
319 m_bPalette = false;
320 m_nBitsPerInputPixel = 32;
321 m_nEndianness = util::Endianness::LITTLE;
322 m_aLayout.IsMsbFirst = false; // doesn't matter
324 m_aComponentTags.realloc(4);
325 sal_Int8* pTags = m_aComponentTags.getArray();
326 pTags[0] = rendering::ColorComponentTag::RGB_RED;
327 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
328 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
329 pTags[3] = rendering::ColorComponentTag::ALPHA;
331 m_aComponentBitCounts.realloc(4);
332 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
333 pCounts[0] = 8;
334 pCounts[1] = 8;
335 pCounts[2] = 8;
336 pCounts[3] = 8;
338 m_nRedIndex = 0;
339 m_nGreenIndex = 1;
340 m_nBlueIndex = 2;
341 m_nAlphaIndex = 3;
343 break;
345 case ScanlineFormat::N32BitTcMask:
346 m_bPalette = false;
347 m_nBitsPerInputPixel = 32;
348 m_nEndianness = util::Endianness::LITTLE;
349 m_aLayout.IsMsbFirst = false; // doesn't matter
350 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
351 m_pBmpAcc->GetColorMask().GetGreenMask(),
352 m_pBmpAcc->GetColorMask().GetBlueMask() );
353 break;
355 default:
356 OSL_FAIL( "unsupported bitmap format" );
357 break;
360 if( m_bPalette )
362 m_aComponentTags.realloc(1);
363 m_aComponentTags[0] = rendering::ColorComponentTag::INDEX;
365 m_aComponentBitCounts.realloc(1);
366 m_aComponentBitCounts[0] = m_nBitsPerInputPixel;
368 m_nIndexIndex = 0;
371 m_nBitsPerOutputPixel = m_nBitsPerInputPixel;
372 if( m_aBmpEx.IsTransparent() )
374 // TODO(P1): need to interleave alpha with bitmap data -
375 // won't fuss with less-than-8 bit for now
376 m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
378 // check whether alpha goes in front or behind the
379 // bitcount sequence. If pixel format is little endian,
380 // put it behind all the other channels. If it's big
381 // endian, put it in front (because later, the actual data
382 // always gets written after the pixel data)
384 // TODO(Q1): slight catch - in the case of the
385 // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
386 // channels might happen!
387 m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
388 m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
390 m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
391 m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
393 if( m_nEndianness == util::Endianness::BIG )
395 // put alpha in front of all the color channels
396 sal_Int8* pTags =m_aComponentTags.getArray();
397 sal_Int32* pCounts=m_aComponentBitCounts.getArray();
398 std::rotate(pTags,
399 pTags+m_aComponentTags.getLength()-1,
400 pTags+m_aComponentTags.getLength());
401 std::rotate(pCounts,
402 pCounts+m_aComponentBitCounts.getLength()-1,
403 pCounts+m_aComponentBitCounts.getLength());
404 ++m_nRedIndex;
405 ++m_nGreenIndex;
406 ++m_nBlueIndex;
407 ++m_nIndexIndex;
408 m_nAlphaIndex=0;
411 // always add a full byte to the pixel size, otherwise
412 // pixel packing hell breaks loose.
413 m_nBitsPerOutputPixel += 8;
415 // adapt scanline parameters
416 const Size aSize = m_aBitmap.GetSizePixel();
417 m_aLayout.ScanLineBytes =
418 m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
423 VclCanvasBitmap::~VclCanvasBitmap()
427 // XBitmap
428 geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize() throw (uno::RuntimeException, std::exception)
430 SolarMutexGuard aGuard;
431 return integerSize2DFromSize( m_aBitmap.GetSizePixel() );
434 sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha() throw (uno::RuntimeException, std::exception)
436 SolarMutexGuard aGuard;
437 return m_aBmpEx.IsTransparent();
440 uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
441 sal_Bool beFast ) throw (uno::RuntimeException, std::exception)
443 SolarMutexGuard aGuard;
445 BitmapEx aNewBmp( m_aBitmap );
446 aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BmpScaleFlag::Default : BmpScaleFlag::BestQuality );
447 return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
450 // XIntegerReadOnlyBitmap
451 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
452 const geometry::IntegerRectangle2D& rect ) throw( lang::IndexOutOfBoundsException,
453 rendering::VolatileContentDestroyedException,
454 uno::RuntimeException, std::exception)
456 SolarMutexGuard aGuard;
458 bitmapLayout = getMemoryLayout();
460 const ::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
461 if( aRequestedArea.IsEmpty() )
462 return uno::Sequence< sal_Int8 >();
464 // Invalid/empty bitmap: no data available
465 if( !m_pBmpAcc )
466 throw lang::IndexOutOfBoundsException();
467 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
468 throw lang::IndexOutOfBoundsException();
470 if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
471 aRequestedArea.Right() > m_pBmpAcc->Width() ||
472 aRequestedArea.Bottom() > m_pBmpAcc->Height() )
474 throw lang::IndexOutOfBoundsException();
477 uno::Sequence< sal_Int8 > aRet;
478 Rectangle aRequestedBytes( aRequestedArea );
480 // adapt to byte boundaries
481 aRequestedBytes.Left() = aRequestedArea.Left()*m_nBitsPerOutputPixel/8;
482 aRequestedBytes.Right() = (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8;
484 // copy stuff to output sequence
485 aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight());
486 sal_Int8* pOutBuf = aRet.getArray();
488 bitmapLayout.ScanLines = aRequestedBytes.getHeight();
489 bitmapLayout.ScanLineBytes =
490 bitmapLayout.ScanLineStride= aRequestedBytes.getWidth();
492 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
493 if( !(m_pBmpAcc->GetScanlineFormat() & ScanlineFormat::TopDown) )
495 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1);
496 nScanlineStride *= -1;
499 if( !m_aBmpEx.IsTransparent() )
501 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
503 // can return bitmap data as-is
504 for( long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
506 Scanline pScan = m_pBmpAcc->GetScanline(y);
507 memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
508 pOutBuf += nScanlineStride;
511 else
513 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
514 OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
516 // interleave alpha with bitmap data - note, bitcount is
517 // always integer multiple of 8
518 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
519 "Transparent bitmap bitcount not integer multiple of 8" );
521 for( long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
523 sal_Int8* pOutScan = pOutBuf;
525 if( m_nBitsPerInputPixel < 8 )
527 // input less than a byte - copy via GetPixel()
528 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
530 *pOutScan++ = m_pBmpAcc->GetPixelIndex(y,x);
531 *pOutScan++ = m_pAlphaAcc->GetPixelIndex(y,x);
534 else
536 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
537 const long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
538 Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
540 // input integer multiple of byte - copy directly
541 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
543 for( long i=0; i<nNonAlphaBytes; ++i )
544 *pOutScan++ = *pScan++;
545 *pOutScan++ = m_pAlphaAcc->GetPixelIndex( y, x );
549 pOutBuf += nScanlineStride;
553 return aRet;
556 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
557 const geometry::IntegerPoint2D& pos ) throw (lang::IndexOutOfBoundsException,
558 rendering::VolatileContentDestroyedException,
559 uno::RuntimeException, std::exception)
561 SolarMutexGuard aGuard;
563 bitmapLayout = getMemoryLayout();
565 // Invalid/empty bitmap: no data available
566 if( !m_pBmpAcc )
567 throw lang::IndexOutOfBoundsException();
568 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
569 throw lang::IndexOutOfBoundsException();
571 if( pos.X < 0 || pos.Y < 0 ||
572 pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
574 throw lang::IndexOutOfBoundsException();
577 uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
578 sal_Int8* pOutBuf = aRet.getArray();
580 // copy stuff to output sequence
581 bitmapLayout.ScanLines = 1;
582 bitmapLayout.ScanLineBytes =
583 bitmapLayout.ScanLineStride= aRet.getLength();
585 const long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
586 if( !m_aBmpEx.IsTransparent() )
588 assert(m_pBmpAcc && "Invalid bmp read access");
590 // can return bitmap data as-is
591 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
592 memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
594 else
596 assert(m_pBmpAcc && "Invalid bmp read access");
597 assert(m_pAlphaAcc && "Invalid alpha read access");
599 // interleave alpha with bitmap data - note, bitcount is
600 // always integer multiple of 8
601 assert((m_nBitsPerOutputPixel & 0x07) == 0 &&
602 "Transparent bitmap bitcount not integer multiple of 8" );
604 if( m_nBitsPerInputPixel < 8 )
606 // input less than a byte - copy via GetPixel()
607 *pOutBuf++ = m_pBmpAcc->GetPixelIndex(pos.Y,pos.X);
608 *pOutBuf = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
610 else
612 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
613 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
615 // input integer multiple of byte - copy directly
616 memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
617 pOutBuf += nNonAlphaBytes;
618 *pOutBuf++ = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
622 return aRet;
625 uno::Reference< rendering::XBitmapPalette > SAL_CALL VclCanvasBitmap::getPalette() throw (uno::RuntimeException)
627 SolarMutexGuard aGuard;
629 uno::Reference< XBitmapPalette > aRet;
630 if( m_bPalette )
631 aRet.set(this);
633 return aRet;
636 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout() throw (uno::RuntimeException, std::exception)
638 SolarMutexGuard aGuard;
640 rendering::IntegerBitmapLayout aLayout( m_aLayout );
642 // only set references to self on separate copy of
643 // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
644 // a circular reference!
645 if( m_bPalette )
646 aLayout.Palette.set( this );
648 aLayout.ColorSpace.set( this );
650 return aLayout;
653 sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries() throw (uno::RuntimeException, std::exception)
655 SolarMutexGuard aGuard;
657 if( !m_pBmpAcc )
658 return 0;
660 return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ;
663 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
665 SolarMutexGuard aGuard;
667 const sal_uInt16 nCount( m_pBmpAcc ?
668 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
669 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
670 if( nIndex < 0 || nIndex >= nCount )
671 throw lang::IndexOutOfBoundsException("Palette index out of range",
672 static_cast<rendering::XBitmapPalette*>(this));
674 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
675 o_entry.realloc(3);
676 double* pColor=o_entry.getArray();
677 pColor[0] = aCol.GetRed();
678 pColor[1] = aCol.GetGreen();
679 pColor[2] = aCol.GetBlue();
681 return true; // no palette transparency here.
684 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException, std::exception)
686 SolarMutexGuard aGuard;
688 const sal_uInt16 nCount( m_pBmpAcc ?
689 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
691 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
692 if( nIndex < 0 || nIndex >= nCount )
693 throw lang::IndexOutOfBoundsException("Palette index out of range",
694 static_cast<rendering::XBitmapPalette*>(this));
696 return false; // read-only implementation
699 namespace
701 struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
702 PaletteColorSpaceHolder>
704 uno::Reference<rendering::XColorSpace> operator()()
706 return vcl::unotools::createStandardColorSpace();
711 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( ) throw (uno::RuntimeException, std::exception)
713 // this is the method from XBitmapPalette. Return palette color
714 // space here
715 return PaletteColorSpaceHolder::get();
718 sal_Int8 SAL_CALL VclCanvasBitmap::getType( ) throw (uno::RuntimeException, std::exception)
720 return rendering::ColorSpaceType::RGB;
723 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( ) throw (uno::RuntimeException, std::exception)
725 SolarMutexGuard aGuard;
726 return m_aComponentTags;
729 sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent( ) throw (uno::RuntimeException, std::exception)
731 return rendering::RenderingIntent::PERCEPTUAL;
734 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( ) throw (uno::RuntimeException, std::exception)
736 return uno::Sequence< ::beans::PropertyValue >();
739 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
740 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (uno::RuntimeException, std::exception)
742 // TODO(P3): if we know anything about target
743 // colorspace, this can be greatly sped up
744 uno::Sequence<rendering::ARGBColor> aIntermediate(
745 convertToARGB(deviceColor));
746 return targetColorSpace->convertFromARGB(aIntermediate);
749 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
751 SolarMutexGuard aGuard;
753 const std::size_t nLen( deviceColor.getLength() );
754 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
755 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
756 "number of channels no multiple of pixel element count",
757 static_cast<rendering::XBitmapPalette*>(this), 01);
759 uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
760 rendering::RGBColor* pOut( aRes.getArray() );
762 if( m_bPalette )
764 OSL_ENSURE(m_nIndexIndex != -1,
765 "Invalid color channel indices");
766 ENSURE_OR_THROW(m_pBmpAcc,
767 "Unable to get BitmapAccess");
769 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
771 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
772 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
774 // TODO(F3): Convert result to sRGB color space
775 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
776 toDoubleColor(aCol.GetGreen()),
777 toDoubleColor(aCol.GetBlue()));
780 else
782 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
783 "Invalid color channel indices");
785 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
787 // TODO(F3): Convert result to sRGB color space
788 *pOut++ = rendering::RGBColor(
789 deviceColor[i+m_nRedIndex],
790 deviceColor[i+m_nGreenIndex],
791 deviceColor[i+m_nBlueIndex]);
795 return aRes;
798 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
800 SolarMutexGuard aGuard;
802 const std::size_t nLen( deviceColor.getLength() );
803 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
804 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
805 "number of channels no multiple of pixel element count",
806 static_cast<rendering::XBitmapPalette*>(this), 01);
808 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
809 rendering::ARGBColor* pOut( aRes.getArray() );
811 if( m_bPalette )
813 OSL_ENSURE(m_nIndexIndex != -1,
814 "Invalid color channel indices");
815 ENSURE_OR_THROW(m_pBmpAcc,
816 "Unable to get BitmapAccess");
818 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
820 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
821 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
823 // TODO(F3): Convert result to sRGB color space
824 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
825 *pOut++ = rendering::ARGBColor(nAlpha,
826 toDoubleColor(aCol.GetRed()),
827 toDoubleColor(aCol.GetGreen()),
828 toDoubleColor(aCol.GetBlue()));
831 else
833 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
834 "Invalid color channel indices");
836 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
838 // TODO(F3): Convert result to sRGB color space
839 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
840 *pOut++ = rendering::ARGBColor(
841 nAlpha,
842 deviceColor[i+m_nRedIndex],
843 deviceColor[i+m_nGreenIndex],
844 deviceColor[i+m_nBlueIndex]);
848 return aRes;
851 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
853 SolarMutexGuard aGuard;
855 const std::size_t nLen( deviceColor.getLength() );
856 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
857 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
858 "number of channels no multiple of pixel element count",
859 static_cast<rendering::XBitmapPalette*>(this), 01);
861 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
862 rendering::ARGBColor* pOut( aRes.getArray() );
864 if( m_bPalette )
866 OSL_ENSURE(m_nIndexIndex != -1,
867 "Invalid color channel indices");
868 ENSURE_OR_THROW(m_pBmpAcc,
869 "Unable to get BitmapAccess");
871 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
873 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
874 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
876 // TODO(F3): Convert result to sRGB color space
877 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
878 *pOut++ = rendering::ARGBColor(nAlpha,
879 nAlpha*toDoubleColor(aCol.GetRed()),
880 nAlpha*toDoubleColor(aCol.GetGreen()),
881 nAlpha*toDoubleColor(aCol.GetBlue()));
884 else
886 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
887 "Invalid color channel indices");
889 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
891 // TODO(F3): Convert result to sRGB color space
892 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
893 *pOut++ = rendering::ARGBColor(
894 nAlpha,
895 nAlpha*deviceColor[i+m_nRedIndex],
896 nAlpha*deviceColor[i+m_nGreenIndex],
897 nAlpha*deviceColor[i+m_nBlueIndex]);
901 return aRes;
904 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
906 SolarMutexGuard aGuard;
908 const std::size_t nLen( rgbColor.getLength() );
909 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
911 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
912 double* pColors=aRes.getArray();
914 if( m_bPalette )
916 for( std::size_t i=0; i<nLen; ++i )
918 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
919 BitmapColor(toByteColor(rgbColor[i].Red),
920 toByteColor(rgbColor[i].Green),
921 toByteColor(rgbColor[i].Blue)));
922 if( m_nAlphaIndex != -1 )
923 pColors[m_nAlphaIndex] = 1.0;
925 pColors += nComponentsPerPixel;
928 else
930 for( std::size_t i=0; i<nLen; ++i )
932 pColors[m_nRedIndex] = rgbColor[i].Red;
933 pColors[m_nGreenIndex] = rgbColor[i].Green;
934 pColors[m_nBlueIndex] = rgbColor[i].Blue;
935 if( m_nAlphaIndex != -1 )
936 pColors[m_nAlphaIndex] = 1.0;
938 pColors += nComponentsPerPixel;
941 return aRes;
944 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
946 SolarMutexGuard aGuard;
948 const std::size_t nLen( rgbColor.getLength() );
949 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
951 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
952 double* pColors=aRes.getArray();
954 if( m_bPalette )
956 for( std::size_t i=0; i<nLen; ++i )
958 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
959 BitmapColor(toByteColor(rgbColor[i].Red),
960 toByteColor(rgbColor[i].Green),
961 toByteColor(rgbColor[i].Blue)));
962 if( m_nAlphaIndex != -1 )
963 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
965 pColors += nComponentsPerPixel;
968 else
970 for( std::size_t i=0; i<nLen; ++i )
972 pColors[m_nRedIndex] = rgbColor[i].Red;
973 pColors[m_nGreenIndex] = rgbColor[i].Green;
974 pColors[m_nBlueIndex] = rgbColor[i].Blue;
975 if( m_nAlphaIndex != -1 )
976 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
978 pColors += nComponentsPerPixel;
981 return aRes;
984 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
986 SolarMutexGuard aGuard;
988 const std::size_t nLen( rgbColor.getLength() );
989 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
991 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
992 double* pColors=aRes.getArray();
994 if( m_bPalette )
996 for( std::size_t i=0; i<nLen; ++i )
998 const double nAlpha( rgbColor[i].Alpha );
999 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
1000 BitmapColor(toByteColor(rgbColor[i].Red / nAlpha),
1001 toByteColor(rgbColor[i].Green / nAlpha),
1002 toByteColor(rgbColor[i].Blue / nAlpha)));
1003 if( m_nAlphaIndex != -1 )
1004 pColors[m_nAlphaIndex] = nAlpha;
1006 pColors += nComponentsPerPixel;
1009 else
1011 for( std::size_t i=0; i<nLen; ++i )
1013 const double nAlpha( rgbColor[i].Alpha );
1014 pColors[m_nRedIndex] = rgbColor[i].Red / nAlpha;
1015 pColors[m_nGreenIndex] = rgbColor[i].Green / nAlpha;
1016 pColors[m_nBlueIndex] = rgbColor[i].Blue / nAlpha;
1017 if( m_nAlphaIndex != -1 )
1018 pColors[m_nAlphaIndex] = nAlpha;
1020 pColors += nComponentsPerPixel;
1023 return aRes;
1026 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( ) throw (uno::RuntimeException, std::exception)
1028 SolarMutexGuard aGuard;
1029 return m_nBitsPerOutputPixel;
1032 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( ) throw (uno::RuntimeException, std::exception)
1034 SolarMutexGuard aGuard;
1035 return m_aComponentBitCounts;
1038 sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness( ) throw (uno::RuntimeException, std::exception)
1040 SolarMutexGuard aGuard;
1041 return m_nEndianness;
1044 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1045 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1047 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1049 SolarMutexGuard aGuard;
1051 const std::size_t nLen( deviceColor.getLength() );
1052 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1053 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1054 "number of channels no multiple of pixel element count",
1055 static_cast<rendering::XBitmapPalette*>(this), 01);
1057 uno::Sequence<double> aRes(nLen);
1058 double* pOut( aRes.getArray() );
1060 if( m_bPalette )
1062 OSL_ENSURE(m_nIndexIndex != -1,
1063 "Invalid color channel indices");
1064 ENSURE_OR_THROW(m_pBmpAcc,
1065 "Unable to get BitmapAccess");
1067 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1069 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1070 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
1072 // TODO(F3): Convert result to sRGB color space
1073 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1074 *pOut++ = toDoubleColor(aCol.GetRed());
1075 *pOut++ = toDoubleColor(aCol.GetGreen());
1076 *pOut++ = toDoubleColor(aCol.GetBlue());
1077 *pOut++ = nAlpha;
1080 else
1082 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1083 "Invalid color channel indices");
1085 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1087 // TODO(F3): Convert result to sRGB color space
1088 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1089 *pOut++ = deviceColor[i+m_nRedIndex];
1090 *pOut++ = deviceColor[i+m_nGreenIndex];
1091 *pOut++ = deviceColor[i+m_nBlueIndex];
1092 *pOut++ = nAlpha;
1096 return aRes;
1098 else
1100 // TODO(P3): if we know anything about target
1101 // colorspace, this can be greatly sped up
1102 uno::Sequence<rendering::ARGBColor> aIntermediate(
1103 convertIntegerToARGB(deviceColor));
1104 return targetColorSpace->convertFromARGB(aIntermediate);
1108 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1109 const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1111 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1113 // it's us, so simply pass-through the data
1114 return deviceColor;
1116 else
1118 // TODO(P3): if we know anything about target
1119 // colorspace, this can be greatly sped up
1120 uno::Sequence<rendering::ARGBColor> aIntermediate(
1121 convertIntegerToARGB(deviceColor));
1122 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1126 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1128 SolarMutexGuard aGuard;
1130 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1131 const std::size_t nLen( deviceColor.getLength() );
1132 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1134 uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1135 rendering::RGBColor* pOut( aRes.getArray() );
1137 ENSURE_OR_THROW(m_pBmpAcc,
1138 "Unable to get BitmapAccess");
1140 if( m_aBmpEx.IsTransparent() )
1142 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1143 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1145 // if palette, index is guaranteed to be 8 bit
1146 const BitmapColor aCol =
1147 m_bPalette ?
1148 m_pBmpAcc->GetPaletteColor(*pIn) :
1149 m_pBmpAcc->GetPixelFromData(pIn,0);
1151 // TODO(F3): Convert result to sRGB color space
1152 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1153 toDoubleColor(aCol.GetGreen()),
1154 toDoubleColor(aCol.GetBlue()));
1155 // skips alpha
1156 pIn += nBytesPerPixel;
1159 else
1161 for( sal_Int32 i=0; i<nNumColors; ++i )
1163 const BitmapColor aCol =
1164 m_bPalette ?
1165 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
1166 m_pBmpAcc->GetPixelFromData(pIn, i);
1168 // TODO(F3): Convert result to sRGB color space
1169 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1170 toDoubleColor(aCol.GetGreen()),
1171 toDoubleColor(aCol.GetBlue()));
1175 return aRes;
1178 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1180 SolarMutexGuard aGuard;
1182 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1183 const std::size_t nLen( deviceColor.getLength() );
1184 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1186 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1187 rendering::ARGBColor* pOut( aRes.getArray() );
1189 ENSURE_OR_THROW(m_pBmpAcc,
1190 "Unable to get BitmapAccess");
1192 if( m_aBmpEx.IsTransparent() )
1194 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1195 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1196 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1197 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1199 // if palette, index is guaranteed to be 8 bit
1200 const BitmapColor aCol =
1201 m_bPalette ?
1202 m_pBmpAcc->GetPaletteColor(*pIn) :
1203 m_pBmpAcc->GetPixelFromData(pIn,0);
1205 // TODO(F3): Convert result to sRGB color space
1206 *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1207 toDoubleColor(aCol.GetRed()),
1208 toDoubleColor(aCol.GetGreen()),
1209 toDoubleColor(aCol.GetBlue()));
1210 pIn += nBytesPerPixel;
1213 else
1215 for( sal_Int32 i=0; i<nNumColors; ++i )
1217 const BitmapColor aCol =
1218 m_bPalette ?
1219 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1220 m_pBmpAcc->GetPixelFromData(pIn, i);
1222 // TODO(F3): Convert result to sRGB color space
1223 *pOut++ = rendering::ARGBColor(1.0,
1224 toDoubleColor(aCol.GetRed()),
1225 toDoubleColor(aCol.GetGreen()),
1226 toDoubleColor(aCol.GetBlue()));
1230 return aRes;
1233 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1235 SolarMutexGuard aGuard;
1237 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1238 const std::size_t nLen( deviceColor.getLength() );
1239 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1241 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1242 rendering::ARGBColor* pOut( aRes.getArray() );
1244 ENSURE_OR_THROW(m_pBmpAcc,
1245 "Unable to get BitmapAccess");
1247 if( m_aBmpEx.IsTransparent() )
1249 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1250 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1251 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1252 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1254 // if palette, index is guaranteed to be 8 bit
1255 const BitmapColor aCol =
1256 m_bPalette ?
1257 m_pBmpAcc->GetPaletteColor(*pIn) :
1258 m_pBmpAcc->GetPixelFromData(pIn,0);
1260 // TODO(F3): Convert result to sRGB color space
1261 const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1262 *pOut++ = rendering::ARGBColor(nAlpha,
1263 nAlpha*toDoubleColor(aCol.GetRed()),
1264 nAlpha*toDoubleColor(aCol.GetGreen()),
1265 nAlpha*toDoubleColor(aCol.GetBlue()));
1266 pIn += nBytesPerPixel;
1269 else
1271 for( sal_Int32 i=0; i<nNumColors; ++i )
1273 const BitmapColor aCol =
1274 m_bPalette ?
1275 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1276 m_pBmpAcc->GetPixelFromData(pIn, i);
1278 // TODO(F3): Convert result to sRGB color space
1279 *pOut++ = rendering::ARGBColor(1.0,
1280 toDoubleColor(aCol.GetRed()),
1281 toDoubleColor(aCol.GetGreen()),
1282 toDoubleColor(aCol.GetBlue()));
1286 return aRes;
1289 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1291 SolarMutexGuard aGuard;
1293 const std::size_t nLen( rgbColor.getLength() );
1294 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1296 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1297 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1299 if( m_aBmpEx.IsTransparent() )
1301 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1302 for( std::size_t i=0; i<nLen; ++i )
1304 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1305 toByteColor(rgbColor[i].Green),
1306 toByteColor(rgbColor[i].Blue));
1307 const BitmapColor aCol2 =
1308 m_bPalette ?
1309 BitmapColor(
1310 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1311 aCol;
1313 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1314 pColors += nNonAlphaBytes;
1315 *pColors++ = sal_uInt8(255);
1318 else
1320 for( std::size_t i=0; i<nLen; ++i )
1322 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1323 toByteColor(rgbColor[i].Green),
1324 toByteColor(rgbColor[i].Blue));
1325 const BitmapColor aCol2 =
1326 m_bPalette ?
1327 BitmapColor(
1328 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1329 aCol;
1331 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1335 return aRes;
1338 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1340 SolarMutexGuard aGuard;
1342 const std::size_t nLen( rgbColor.getLength() );
1343 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1345 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1346 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1348 if( m_aBmpEx.IsTransparent() )
1350 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1351 for( std::size_t i=0; i<nLen; ++i )
1353 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1354 toByteColor(rgbColor[i].Green),
1355 toByteColor(rgbColor[i].Blue));
1356 const BitmapColor aCol2 =
1357 m_bPalette ?
1358 BitmapColor(
1359 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1360 aCol;
1362 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1363 pColors += nNonAlphaBytes;
1364 *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1367 else
1369 for( std::size_t i=0; i<nLen; ++i )
1371 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1372 toByteColor(rgbColor[i].Green),
1373 toByteColor(rgbColor[i].Blue));
1374 const BitmapColor aCol2 =
1375 m_bPalette ?
1376 BitmapColor(
1377 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1378 aCol;
1380 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1384 return aRes;
1387 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1389 SolarMutexGuard aGuard;
1391 const std::size_t nLen( rgbColor.getLength() );
1392 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1394 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1395 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1397 if( m_aBmpEx.IsTransparent() )
1399 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1400 for( std::size_t i=0; i<nLen; ++i )
1402 const double nAlpha( rgbColor[i].Alpha );
1403 const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1404 toByteColor(rgbColor[i].Green / nAlpha),
1405 toByteColor(rgbColor[i].Blue / nAlpha));
1406 const BitmapColor aCol2 =
1407 m_bPalette ?
1408 BitmapColor(
1409 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1410 aCol;
1412 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1413 pColors += nNonAlphaBytes;
1414 *pColors++ = 255 - toByteColor(nAlpha);
1417 else
1419 for( std::size_t i=0; i<nLen; ++i )
1421 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1422 toByteColor(rgbColor[i].Green),
1423 toByteColor(rgbColor[i].Blue));
1424 const BitmapColor aCol2 =
1425 m_bPalette ?
1426 BitmapColor(
1427 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1428 aCol;
1430 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1434 return aRes;
1438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */