Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / helper / canvasbitmap.cxx
blobc532606b4eb8f7db57b5ad846e45518a2555efcd
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/bmpacc.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_uLong redShift, sal_uLong greenShift, sal_uLong 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(sal::static_int_cast<sal_uInt32>(redShift));
93 pCounts[greenPos] = bitcount(sal::static_int_cast<sal_uInt32>(greenShift));
94 pCounts[bluePos] = bitcount(sal::static_int_cast<sal_uInt32>(blueShift));
97 VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
98 m_aBmpEx( rBitmap ),
99 m_aBitmap( rBitmap.GetBitmap() ),
100 m_aAlpha(),
101 m_pBmpAcc( m_aBitmap.AcquireReadAccess() ),
102 m_pAlphaAcc( NULL ),
103 m_aComponentTags(),
104 m_aComponentBitCounts(),
105 m_aLayout(),
106 m_nBitsPerInputPixel(0),
107 m_nBitsPerOutputPixel(0),
108 m_nRedIndex(-1),
109 m_nGreenIndex(-1),
110 m_nBlueIndex(-1),
111 m_nAlphaIndex(-1),
112 m_nIndexIndex(-1),
113 m_nEndianness(0),
114 m_bPalette(false)
116 if( m_aBmpEx.IsTransparent() )
118 m_aAlpha = m_aBmpEx.IsAlpha() ? m_aBmpEx.GetAlpha().GetBitmap() : m_aBmpEx.GetMask();
119 m_pAlphaAcc = m_aAlpha.AcquireReadAccess();
122 m_aLayout.ScanLines = 0;
123 m_aLayout.ScanLineBytes = 0;
124 m_aLayout.ScanLineStride = 0;
125 m_aLayout.PlaneStride = 0;
126 m_aLayout.ColorSpace.clear();
127 m_aLayout.Palette.clear();
128 m_aLayout.IsMsbFirst = false;
130 if( m_pBmpAcc )
132 m_aLayout.ScanLines = m_pBmpAcc->Height();
133 m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
134 m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
135 m_aLayout.PlaneStride = 0;
137 switch( m_pBmpAcc->GetScanlineFormat() )
139 case BMP_FORMAT_1BIT_MSB_PAL:
140 m_bPalette = true;
141 m_nBitsPerInputPixel = 1;
142 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
143 m_aLayout.IsMsbFirst = true;
144 break;
146 case BMP_FORMAT_1BIT_LSB_PAL:
147 m_bPalette = true;
148 m_nBitsPerInputPixel = 1;
149 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
150 m_aLayout.IsMsbFirst = false;
151 break;
153 case BMP_FORMAT_4BIT_MSN_PAL:
154 m_bPalette = true;
155 m_nBitsPerInputPixel = 4;
156 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
157 m_aLayout.IsMsbFirst = true;
158 break;
160 case BMP_FORMAT_4BIT_LSN_PAL:
161 m_bPalette = true;
162 m_nBitsPerInputPixel = 4;
163 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
164 m_aLayout.IsMsbFirst = false;
165 break;
167 case BMP_FORMAT_8BIT_PAL:
168 m_bPalette = true;
169 m_nBitsPerInputPixel = 8;
170 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
171 m_aLayout.IsMsbFirst = false; // doesn't matter
172 break;
174 case BMP_FORMAT_8BIT_TC_MASK:
175 m_bPalette = false;
176 m_nBitsPerInputPixel = 8;
177 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
178 m_aLayout.IsMsbFirst = false; // doesn't matter
179 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
180 m_pBmpAcc->GetColorMask().GetGreenMask(),
181 m_pBmpAcc->GetColorMask().GetBlueMask() );
182 break;
184 case BMP_FORMAT_16BIT_TC_MSB_MASK:
185 m_bPalette = false;
186 m_nBitsPerInputPixel = 16;
187 m_nEndianness = util::Endianness::BIG;
188 m_aLayout.IsMsbFirst = false; // doesn't matter
189 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
190 m_pBmpAcc->GetColorMask().GetGreenMask(),
191 m_pBmpAcc->GetColorMask().GetBlueMask() );
192 break;
194 case BMP_FORMAT_16BIT_TC_LSB_MASK:
195 m_bPalette = false;
196 m_nBitsPerInputPixel = 16;
197 m_nEndianness = util::Endianness::LITTLE;
198 m_aLayout.IsMsbFirst = false; // doesn't matter
199 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
200 m_pBmpAcc->GetColorMask().GetGreenMask(),
201 m_pBmpAcc->GetColorMask().GetBlueMask() );
202 break;
204 case BMP_FORMAT_24BIT_TC_BGR:
205 m_bPalette = false;
206 m_nBitsPerInputPixel = 24;
207 m_nEndianness = util::Endianness::LITTLE;
208 m_aLayout.IsMsbFirst = false; // doesn't matter
209 setComponentInfo( 0xff0000LL,
210 0x00ff00LL,
211 0x0000ffLL );
212 break;
214 case BMP_FORMAT_24BIT_TC_RGB:
215 m_bPalette = false;
216 m_nBitsPerInputPixel = 24;
217 m_nEndianness = util::Endianness::LITTLE;
218 m_aLayout.IsMsbFirst = false; // doesn't matter
219 setComponentInfo( 0x0000ffLL,
220 0x00ff00LL,
221 0xff0000LL );
222 break;
224 case BMP_FORMAT_24BIT_TC_MASK:
225 m_bPalette = false;
226 m_nBitsPerInputPixel = 24;
227 m_nEndianness = util::Endianness::LITTLE;
228 m_aLayout.IsMsbFirst = false; // doesn't matter
229 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
230 m_pBmpAcc->GetColorMask().GetGreenMask(),
231 m_pBmpAcc->GetColorMask().GetBlueMask() );
232 break;
234 case BMP_FORMAT_32BIT_TC_ABGR:
236 m_bPalette = false;
237 m_nBitsPerInputPixel = 32;
238 m_nEndianness = util::Endianness::LITTLE;
239 m_aLayout.IsMsbFirst = false; // doesn't matter
241 m_aComponentTags.realloc(4);
242 sal_Int8* pTags = m_aComponentTags.getArray();
243 pTags[0] = rendering::ColorComponentTag::ALPHA;
244 pTags[1] = rendering::ColorComponentTag::RGB_BLUE;
245 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
246 pTags[3] = rendering::ColorComponentTag::RGB_RED;
248 m_aComponentBitCounts.realloc(4);
249 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
250 pCounts[0] = 8;
251 pCounts[1] = 8;
252 pCounts[2] = 8;
253 pCounts[3] = 8;
255 m_nRedIndex = 3;
256 m_nGreenIndex = 2;
257 m_nBlueIndex = 1;
258 m_nAlphaIndex = 0;
260 break;
262 case BMP_FORMAT_32BIT_TC_ARGB:
264 m_bPalette = false;
265 m_nBitsPerInputPixel = 32;
266 m_nEndianness = util::Endianness::LITTLE;
267 m_aLayout.IsMsbFirst = false; // doesn't matter
269 m_aComponentTags.realloc(4);
270 sal_Int8* pTags = m_aComponentTags.getArray();
271 pTags[0] = rendering::ColorComponentTag::ALPHA;
272 pTags[1] = rendering::ColorComponentTag::RGB_RED;
273 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
274 pTags[3] = rendering::ColorComponentTag::RGB_BLUE;
276 m_aComponentBitCounts.realloc(4);
277 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
278 pCounts[0] = 8;
279 pCounts[1] = 8;
280 pCounts[2] = 8;
281 pCounts[3] = 8;
283 m_nRedIndex = 1;
284 m_nGreenIndex = 2;
285 m_nBlueIndex = 3;
286 m_nAlphaIndex = 0;
288 break;
290 case BMP_FORMAT_32BIT_TC_BGRA:
292 m_bPalette = false;
293 m_nBitsPerInputPixel = 32;
294 m_nEndianness = util::Endianness::LITTLE;
295 m_aLayout.IsMsbFirst = false; // doesn't matter
297 m_aComponentTags.realloc(4);
298 sal_Int8* pTags = m_aComponentTags.getArray();
299 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
300 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
301 pTags[2] = rendering::ColorComponentTag::RGB_RED;
302 pTags[3] = rendering::ColorComponentTag::ALPHA;
304 m_aComponentBitCounts.realloc(4);
305 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
306 pCounts[0] = 8;
307 pCounts[1] = 8;
308 pCounts[2] = 8;
309 pCounts[3] = 8;
311 m_nRedIndex = 2;
312 m_nGreenIndex = 1;
313 m_nBlueIndex = 0;
314 m_nAlphaIndex = 3;
316 break;
318 case BMP_FORMAT_32BIT_TC_RGBA:
320 m_bPalette = false;
321 m_nBitsPerInputPixel = 32;
322 m_nEndianness = util::Endianness::LITTLE;
323 m_aLayout.IsMsbFirst = false; // doesn't matter
325 m_aComponentTags.realloc(4);
326 sal_Int8* pTags = m_aComponentTags.getArray();
327 pTags[0] = rendering::ColorComponentTag::RGB_RED;
328 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
329 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
330 pTags[3] = rendering::ColorComponentTag::ALPHA;
332 m_aComponentBitCounts.realloc(4);
333 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
334 pCounts[0] = 8;
335 pCounts[1] = 8;
336 pCounts[2] = 8;
337 pCounts[3] = 8;
339 m_nRedIndex = 0;
340 m_nGreenIndex = 1;
341 m_nBlueIndex = 2;
342 m_nAlphaIndex = 3;
344 break;
346 case BMP_FORMAT_32BIT_TC_MASK:
347 m_bPalette = false;
348 m_nBitsPerInputPixel = 32;
349 m_nEndianness = util::Endianness::LITTLE;
350 m_aLayout.IsMsbFirst = false; // doesn't matter
351 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
352 m_pBmpAcc->GetColorMask().GetGreenMask(),
353 m_pBmpAcc->GetColorMask().GetBlueMask() );
354 break;
356 default:
357 OSL_FAIL( "unsupported bitmap format" );
358 break;
361 if( m_bPalette )
363 m_aComponentTags.realloc(1);
364 m_aComponentTags[0] = rendering::ColorComponentTag::INDEX;
366 m_aComponentBitCounts.realloc(1);
367 m_aComponentBitCounts[0] = m_nBitsPerInputPixel;
369 m_nIndexIndex = 0;
372 m_nBitsPerOutputPixel = m_nBitsPerInputPixel;
373 if( m_aBmpEx.IsTransparent() )
375 // TODO(P1): need to interleave alpha with bitmap data -
376 // won't fuss with less-than-8 bit for now
377 m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
379 // check whether alpha goes in front or behind the
380 // bitcount sequence. If pixel format is little endian,
381 // put it behind all the other channels. If it's big
382 // endian, put it in front (because later, the actual data
383 // always gets written after the pixel data)
385 // TODO(Q1): slight catch - in the case of the
386 // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
387 // channels might happen!
388 m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
389 m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
391 m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
392 m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
394 if( m_nEndianness == util::Endianness::BIG )
396 // put alpha in front of all the color channels
397 sal_Int8* pTags =m_aComponentTags.getArray();
398 sal_Int32* pCounts=m_aComponentBitCounts.getArray();
399 std::rotate(pTags,
400 pTags+m_aComponentTags.getLength()-1,
401 pTags+m_aComponentTags.getLength());
402 std::rotate(pCounts,
403 pCounts+m_aComponentBitCounts.getLength()-1,
404 pCounts+m_aComponentBitCounts.getLength());
405 ++m_nRedIndex;
406 ++m_nGreenIndex;
407 ++m_nBlueIndex;
408 ++m_nIndexIndex;
409 m_nAlphaIndex=0;
412 // always add a full byte to the pixel size, otherwise
413 // pixel packing hell breaks loose.
414 m_nBitsPerOutputPixel += 8;
416 // adapt scanline parameters
417 const Size aSize = m_aBitmap.GetSizePixel();
418 m_aLayout.ScanLineBytes =
419 m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
424 VclCanvasBitmap::~VclCanvasBitmap()
426 if( m_pAlphaAcc )
427 Bitmap::ReleaseAccess(m_pAlphaAcc);
428 if( m_pBmpAcc )
429 Bitmap::ReleaseAccess(m_pBmpAcc);
432 // XBitmap
433 geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize() throw (uno::RuntimeException, std::exception)
435 SolarMutexGuard aGuard;
436 return integerSize2DFromSize( m_aBitmap.GetSizePixel() );
439 sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha() throw (uno::RuntimeException, std::exception)
441 SolarMutexGuard aGuard;
442 return m_aBmpEx.IsTransparent();
445 uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
446 sal_Bool beFast ) throw (uno::RuntimeException, std::exception)
448 SolarMutexGuard aGuard;
450 BitmapEx aNewBmp( m_aBitmap );
451 aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BmpScaleFlag::Default : BmpScaleFlag::BestQuality );
452 return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
455 // XIntegerReadOnlyBitmap
456 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
457 const geometry::IntegerRectangle2D& rect ) throw( lang::IndexOutOfBoundsException,
458 rendering::VolatileContentDestroyedException,
459 uno::RuntimeException, std::exception)
461 SolarMutexGuard aGuard;
463 bitmapLayout = getMemoryLayout();
465 const ::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
466 if( aRequestedArea.IsEmpty() )
467 return uno::Sequence< sal_Int8 >();
469 // Invalid/empty bitmap: no data available
470 if( !m_pBmpAcc )
471 throw lang::IndexOutOfBoundsException();
472 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
473 throw lang::IndexOutOfBoundsException();
475 if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
476 aRequestedArea.Right() > m_pBmpAcc->Width() ||
477 aRequestedArea.Bottom() > m_pBmpAcc->Height() )
479 throw lang::IndexOutOfBoundsException();
482 uno::Sequence< sal_Int8 > aRet;
483 Rectangle aRequestedBytes( aRequestedArea );
485 // adapt to byte boundaries
486 aRequestedBytes.Left() = aRequestedArea.Left()*m_nBitsPerOutputPixel/8;
487 aRequestedBytes.Right() = (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8;
489 // copy stuff to output sequence
490 aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight());
491 sal_Int8* pOutBuf = aRet.getArray();
493 bitmapLayout.ScanLines = aRequestedBytes.getHeight();
494 bitmapLayout.ScanLineBytes =
495 bitmapLayout.ScanLineStride= aRequestedBytes.getWidth();
497 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
498 if( !(m_pBmpAcc->GetScanlineFormat() & BMP_FORMAT_TOP_DOWN) )
500 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1);
501 nScanlineStride *= -1;
504 if( !m_aBmpEx.IsTransparent() )
506 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
508 // can return bitmap data as-is
509 for( long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
511 Scanline pScan = m_pBmpAcc->GetScanline(y);
512 memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
513 pOutBuf += nScanlineStride;
516 else
518 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
519 OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
521 // interleave alpha with bitmap data - note, bitcount is
522 // always integer multiple of 8
523 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
524 "Transparent bitmap bitcount not integer multiple of 8" );
526 for( long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
528 sal_Int8* pOutScan = pOutBuf;
530 if( m_nBitsPerInputPixel < 8 )
532 // input less than a byte - copy via GetPixel()
533 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
535 *pOutScan++ = m_pBmpAcc->GetPixelIndex(y,x);
536 *pOutScan++ = m_pAlphaAcc->GetPixelIndex(y,x);
539 else
541 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
542 const long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
543 Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
545 // input integer multiple of byte - copy directly
546 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
548 for( long i=0; i<nNonAlphaBytes; ++i )
549 *pOutScan++ = *pScan++;
550 *pOutScan++ = m_pAlphaAcc->GetPixelIndex( y, x );
554 pOutBuf += nScanlineStride;
558 return aRet;
561 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
562 const geometry::IntegerPoint2D& pos ) throw (lang::IndexOutOfBoundsException,
563 rendering::VolatileContentDestroyedException,
564 uno::RuntimeException, std::exception)
566 SolarMutexGuard aGuard;
568 bitmapLayout = getMemoryLayout();
570 // Invalid/empty bitmap: no data available
571 if( !m_pBmpAcc )
572 throw lang::IndexOutOfBoundsException();
573 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
574 throw lang::IndexOutOfBoundsException();
576 if( pos.X < 0 || pos.Y < 0 ||
577 pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
579 throw lang::IndexOutOfBoundsException();
582 uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
583 sal_Int8* pOutBuf = aRet.getArray();
585 // copy stuff to output sequence
586 bitmapLayout.ScanLines = 1;
587 bitmapLayout.ScanLineBytes =
588 bitmapLayout.ScanLineStride= aRet.getLength();
590 const long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
591 if( !m_aBmpEx.IsTransparent() )
593 assert(m_pBmpAcc && "Invalid bmp read access");
595 // can return bitmap data as-is
596 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
597 memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
599 else
601 assert(m_pBmpAcc && "Invalid bmp read access");
602 assert(m_pAlphaAcc && "Invalid alpha read access");
604 // interleave alpha with bitmap data - note, bitcount is
605 // always integer multiple of 8
606 assert((m_nBitsPerOutputPixel & 0x07) == 0 &&
607 "Transparent bitmap bitcount not integer multiple of 8" );
609 if( m_nBitsPerInputPixel < 8 )
611 // input less than a byte - copy via GetPixel()
612 *pOutBuf++ = m_pBmpAcc->GetPixelIndex(pos.Y,pos.X);
613 *pOutBuf = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
615 else
617 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
618 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
620 // input integer multiple of byte - copy directly
621 memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
622 pOutBuf += nNonAlphaBytes;
623 *pOutBuf++ = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
627 return aRet;
630 uno::Reference< rendering::XBitmapPalette > SAL_CALL VclCanvasBitmap::getPalette() throw (uno::RuntimeException)
632 SolarMutexGuard aGuard;
634 uno::Reference< XBitmapPalette > aRet;
635 if( m_bPalette )
636 aRet.set(this);
638 return aRet;
641 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout() throw (uno::RuntimeException, std::exception)
643 SolarMutexGuard aGuard;
645 rendering::IntegerBitmapLayout aLayout( m_aLayout );
647 // only set references to self on separate copy of
648 // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
649 // a circular reference!
650 if( m_bPalette )
651 aLayout.Palette.set( this );
653 aLayout.ColorSpace.set( this );
655 return aLayout;
658 sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries() throw (uno::RuntimeException, std::exception)
660 SolarMutexGuard aGuard;
662 if( !m_pBmpAcc )
663 return 0;
665 return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ;
668 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
670 SolarMutexGuard aGuard;
672 const sal_uInt16 nCount( m_pBmpAcc ?
673 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
674 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
675 if( nIndex < 0 || nIndex >= nCount )
676 throw lang::IndexOutOfBoundsException("Palette index out of range",
677 static_cast<rendering::XBitmapPalette*>(this));
679 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
680 o_entry.realloc(3);
681 double* pColor=o_entry.getArray();
682 pColor[0] = aCol.GetRed();
683 pColor[1] = aCol.GetGreen();
684 pColor[2] = aCol.GetBlue();
686 return sal_True; // no palette transparency here.
689 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException, std::exception)
691 SolarMutexGuard aGuard;
693 const sal_uInt16 nCount( m_pBmpAcc ?
694 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
696 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
697 if( nIndex < 0 || nIndex >= nCount )
698 throw lang::IndexOutOfBoundsException("Palette index out of range",
699 static_cast<rendering::XBitmapPalette*>(this));
701 return sal_False; // read-only implementation
704 namespace
706 struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
707 PaletteColorSpaceHolder>
709 uno::Reference<rendering::XColorSpace> operator()()
711 return vcl::unotools::createStandardColorSpace();
716 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( ) throw (uno::RuntimeException, std::exception)
718 // this is the method from XBitmapPalette. Return palette color
719 // space here
720 return PaletteColorSpaceHolder::get();
723 sal_Int8 SAL_CALL VclCanvasBitmap::getType( ) throw (uno::RuntimeException, std::exception)
725 return rendering::ColorSpaceType::RGB;
728 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( ) throw (uno::RuntimeException, std::exception)
730 SolarMutexGuard aGuard;
731 return m_aComponentTags;
734 sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent( ) throw (uno::RuntimeException, std::exception)
736 return rendering::RenderingIntent::PERCEPTUAL;
739 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( ) throw (uno::RuntimeException, std::exception)
741 return uno::Sequence< ::beans::PropertyValue >();
744 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
745 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (uno::RuntimeException, std::exception)
747 // TODO(P3): if we know anything about target
748 // colorspace, this can be greatly sped up
749 uno::Sequence<rendering::ARGBColor> aIntermediate(
750 convertToARGB(deviceColor));
751 return targetColorSpace->convertFromARGB(aIntermediate);
754 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
756 SolarMutexGuard aGuard;
758 const sal_Size nLen( deviceColor.getLength() );
759 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
760 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
761 "number of channels no multiple of pixel element count",
762 static_cast<rendering::XBitmapPalette*>(this), 01);
764 uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
765 rendering::RGBColor* pOut( aRes.getArray() );
767 if( m_bPalette )
769 OSL_ENSURE(m_nIndexIndex != -1,
770 "Invalid color channel indices");
771 ENSURE_OR_THROW(m_pBmpAcc,
772 "Unable to get BitmapAccess");
774 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
776 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
777 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
779 // TODO(F3): Convert result to sRGB color space
780 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
781 toDoubleColor(aCol.GetGreen()),
782 toDoubleColor(aCol.GetBlue()));
785 else
787 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
788 "Invalid color channel indices");
790 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
792 // TODO(F3): Convert result to sRGB color space
793 *pOut++ = rendering::RGBColor(
794 deviceColor[i+m_nRedIndex],
795 deviceColor[i+m_nGreenIndex],
796 deviceColor[i+m_nBlueIndex]);
800 return aRes;
803 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
805 SolarMutexGuard aGuard;
807 const sal_Size nLen( deviceColor.getLength() );
808 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
809 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
810 "number of channels no multiple of pixel element count",
811 static_cast<rendering::XBitmapPalette*>(this), 01);
813 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
814 rendering::ARGBColor* pOut( aRes.getArray() );
816 if( m_bPalette )
818 OSL_ENSURE(m_nIndexIndex != -1,
819 "Invalid color channel indices");
820 ENSURE_OR_THROW(m_pBmpAcc,
821 "Unable to get BitmapAccess");
823 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
825 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
826 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
828 // TODO(F3): Convert result to sRGB color space
829 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
830 *pOut++ = rendering::ARGBColor(nAlpha,
831 toDoubleColor(aCol.GetRed()),
832 toDoubleColor(aCol.GetGreen()),
833 toDoubleColor(aCol.GetBlue()));
836 else
838 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
839 "Invalid color channel indices");
841 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
843 // TODO(F3): Convert result to sRGB color space
844 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
845 *pOut++ = rendering::ARGBColor(
846 nAlpha,
847 deviceColor[i+m_nRedIndex],
848 deviceColor[i+m_nGreenIndex],
849 deviceColor[i+m_nBlueIndex]);
853 return aRes;
856 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
858 SolarMutexGuard aGuard;
860 const sal_Size nLen( deviceColor.getLength() );
861 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
862 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
863 "number of channels no multiple of pixel element count",
864 static_cast<rendering::XBitmapPalette*>(this), 01);
866 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
867 rendering::ARGBColor* pOut( aRes.getArray() );
869 if( m_bPalette )
871 OSL_ENSURE(m_nIndexIndex != -1,
872 "Invalid color channel indices");
873 ENSURE_OR_THROW(m_pBmpAcc,
874 "Unable to get BitmapAccess");
876 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
878 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
879 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
881 // TODO(F3): Convert result to sRGB color space
882 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
883 *pOut++ = rendering::ARGBColor(nAlpha,
884 nAlpha*toDoubleColor(aCol.GetRed()),
885 nAlpha*toDoubleColor(aCol.GetGreen()),
886 nAlpha*toDoubleColor(aCol.GetBlue()));
889 else
891 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
892 "Invalid color channel indices");
894 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
896 // TODO(F3): Convert result to sRGB color space
897 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
898 *pOut++ = rendering::ARGBColor(
899 nAlpha,
900 nAlpha*deviceColor[i+m_nRedIndex],
901 nAlpha*deviceColor[i+m_nGreenIndex],
902 nAlpha*deviceColor[i+m_nBlueIndex]);
906 return aRes;
909 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
911 SolarMutexGuard aGuard;
913 const sal_Size nLen( rgbColor.getLength() );
914 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
916 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
917 double* pColors=aRes.getArray();
919 if( m_bPalette )
921 for( sal_Size i=0; i<nLen; ++i )
923 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
924 BitmapColor(toByteColor(rgbColor[i].Red),
925 toByteColor(rgbColor[i].Green),
926 toByteColor(rgbColor[i].Blue)));
927 if( m_nAlphaIndex != -1 )
928 pColors[m_nAlphaIndex] = 1.0;
930 pColors += nComponentsPerPixel;
933 else
935 for( sal_Size i=0; i<nLen; ++i )
937 pColors[m_nRedIndex] = rgbColor[i].Red;
938 pColors[m_nGreenIndex] = rgbColor[i].Green;
939 pColors[m_nBlueIndex] = rgbColor[i].Blue;
940 if( m_nAlphaIndex != -1 )
941 pColors[m_nAlphaIndex] = 1.0;
943 pColors += nComponentsPerPixel;
946 return aRes;
949 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
951 SolarMutexGuard aGuard;
953 const sal_Size nLen( rgbColor.getLength() );
954 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
956 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
957 double* pColors=aRes.getArray();
959 if( m_bPalette )
961 for( sal_Size i=0; i<nLen; ++i )
963 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
964 BitmapColor(toByteColor(rgbColor[i].Red),
965 toByteColor(rgbColor[i].Green),
966 toByteColor(rgbColor[i].Blue)));
967 if( m_nAlphaIndex != -1 )
968 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
970 pColors += nComponentsPerPixel;
973 else
975 for( sal_Size i=0; i<nLen; ++i )
977 pColors[m_nRedIndex] = rgbColor[i].Red;
978 pColors[m_nGreenIndex] = rgbColor[i].Green;
979 pColors[m_nBlueIndex] = rgbColor[i].Blue;
980 if( m_nAlphaIndex != -1 )
981 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
983 pColors += nComponentsPerPixel;
986 return aRes;
989 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
991 SolarMutexGuard aGuard;
993 const sal_Size nLen( rgbColor.getLength() );
994 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
996 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
997 double* pColors=aRes.getArray();
999 if( m_bPalette )
1001 for( sal_Size i=0; i<nLen; ++i )
1003 const double nAlpha( rgbColor[i].Alpha );
1004 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
1005 BitmapColor(toByteColor(rgbColor[i].Red / nAlpha),
1006 toByteColor(rgbColor[i].Green / nAlpha),
1007 toByteColor(rgbColor[i].Blue / nAlpha)));
1008 if( m_nAlphaIndex != -1 )
1009 pColors[m_nAlphaIndex] = nAlpha;
1011 pColors += nComponentsPerPixel;
1014 else
1016 for( sal_Size i=0; i<nLen; ++i )
1018 const double nAlpha( rgbColor[i].Alpha );
1019 pColors[m_nRedIndex] = rgbColor[i].Red / nAlpha;
1020 pColors[m_nGreenIndex] = rgbColor[i].Green / nAlpha;
1021 pColors[m_nBlueIndex] = rgbColor[i].Blue / nAlpha;
1022 if( m_nAlphaIndex != -1 )
1023 pColors[m_nAlphaIndex] = nAlpha;
1025 pColors += nComponentsPerPixel;
1028 return aRes;
1031 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( ) throw (uno::RuntimeException, std::exception)
1033 SolarMutexGuard aGuard;
1034 return m_nBitsPerOutputPixel;
1037 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( ) throw (uno::RuntimeException, std::exception)
1039 SolarMutexGuard aGuard;
1040 return m_aComponentBitCounts;
1043 sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness( ) throw (uno::RuntimeException, std::exception)
1045 SolarMutexGuard aGuard;
1046 return m_nEndianness;
1049 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1050 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1052 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1054 SolarMutexGuard aGuard;
1056 const sal_Size nLen( deviceColor.getLength() );
1057 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1058 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1059 "number of channels no multiple of pixel element count",
1060 static_cast<rendering::XBitmapPalette*>(this), 01);
1062 uno::Sequence<double> aRes(nLen);
1063 double* pOut( aRes.getArray() );
1065 if( m_bPalette )
1067 OSL_ENSURE(m_nIndexIndex != -1,
1068 "Invalid color channel indices");
1069 ENSURE_OR_THROW(m_pBmpAcc,
1070 "Unable to get BitmapAccess");
1072 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1074 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1075 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
1077 // TODO(F3): Convert result to sRGB color space
1078 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1079 *pOut++ = toDoubleColor(aCol.GetRed());
1080 *pOut++ = toDoubleColor(aCol.GetGreen());
1081 *pOut++ = toDoubleColor(aCol.GetBlue());
1082 *pOut++ = nAlpha;
1085 else
1087 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1088 "Invalid color channel indices");
1090 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1092 // TODO(F3): Convert result to sRGB color space
1093 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1094 *pOut++ = deviceColor[i+m_nRedIndex];
1095 *pOut++ = deviceColor[i+m_nGreenIndex];
1096 *pOut++ = deviceColor[i+m_nBlueIndex];
1097 *pOut++ = nAlpha;
1101 return aRes;
1103 else
1105 // TODO(P3): if we know anything about target
1106 // colorspace, this can be greatly sped up
1107 uno::Sequence<rendering::ARGBColor> aIntermediate(
1108 convertIntegerToARGB(deviceColor));
1109 return targetColorSpace->convertFromARGB(aIntermediate);
1113 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1114 const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1116 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1118 // it's us, so simply pass-through the data
1119 return deviceColor;
1121 else
1123 // TODO(P3): if we know anything about target
1124 // colorspace, this can be greatly sped up
1125 uno::Sequence<rendering::ARGBColor> aIntermediate(
1126 convertIntegerToARGB(deviceColor));
1127 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1131 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1133 SolarMutexGuard aGuard;
1135 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1136 const sal_Size nLen( deviceColor.getLength() );
1137 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1139 uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1140 rendering::RGBColor* pOut( aRes.getArray() );
1142 ENSURE_OR_THROW(m_pBmpAcc,
1143 "Unable to get BitmapAccess");
1145 if( m_aBmpEx.IsTransparent() )
1147 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1148 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1150 // if palette, index is guaranteed to be 8 bit
1151 const BitmapColor aCol =
1152 m_bPalette ?
1153 m_pBmpAcc->GetPaletteColor(*pIn) :
1154 m_pBmpAcc->GetPixelFromData(pIn,0);
1156 // TODO(F3): Convert result to sRGB color space
1157 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1158 toDoubleColor(aCol.GetGreen()),
1159 toDoubleColor(aCol.GetBlue()));
1160 // skips alpha
1161 pIn += nBytesPerPixel;
1164 else
1166 for( sal_Int32 i=0; i<nNumColors; ++i )
1168 const BitmapColor aCol =
1169 m_bPalette ?
1170 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
1171 m_pBmpAcc->GetPixelFromData(pIn, i);
1173 // TODO(F3): Convert result to sRGB color space
1174 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1175 toDoubleColor(aCol.GetGreen()),
1176 toDoubleColor(aCol.GetBlue()));
1180 return aRes;
1183 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1185 SolarMutexGuard aGuard;
1187 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1188 const sal_Size nLen( deviceColor.getLength() );
1189 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1191 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1192 rendering::ARGBColor* pOut( aRes.getArray() );
1194 ENSURE_OR_THROW(m_pBmpAcc,
1195 "Unable to get BitmapAccess");
1197 if( m_aBmpEx.IsTransparent() )
1199 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1200 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1201 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1202 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1204 // if palette, index is guaranteed to be 8 bit
1205 const BitmapColor aCol =
1206 m_bPalette ?
1207 m_pBmpAcc->GetPaletteColor(*pIn) :
1208 m_pBmpAcc->GetPixelFromData(pIn,0);
1210 // TODO(F3): Convert result to sRGB color space
1211 *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1212 toDoubleColor(aCol.GetRed()),
1213 toDoubleColor(aCol.GetGreen()),
1214 toDoubleColor(aCol.GetBlue()));
1215 pIn += nBytesPerPixel;
1218 else
1220 for( sal_Int32 i=0; i<nNumColors; ++i )
1222 const BitmapColor aCol =
1223 m_bPalette ?
1224 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1225 m_pBmpAcc->GetPixelFromData(pIn, i);
1227 // TODO(F3): Convert result to sRGB color space
1228 *pOut++ = rendering::ARGBColor(1.0,
1229 toDoubleColor(aCol.GetRed()),
1230 toDoubleColor(aCol.GetGreen()),
1231 toDoubleColor(aCol.GetBlue()));
1235 return aRes;
1238 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1240 SolarMutexGuard aGuard;
1242 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1243 const sal_Size nLen( deviceColor.getLength() );
1244 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1246 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1247 rendering::ARGBColor* pOut( aRes.getArray() );
1249 ENSURE_OR_THROW(m_pBmpAcc,
1250 "Unable to get BitmapAccess");
1252 if( m_aBmpEx.IsTransparent() )
1254 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1255 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1256 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1257 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1259 // if palette, index is guaranteed to be 8 bit
1260 const BitmapColor aCol =
1261 m_bPalette ?
1262 m_pBmpAcc->GetPaletteColor(*pIn) :
1263 m_pBmpAcc->GetPixelFromData(pIn,0);
1265 // TODO(F3): Convert result to sRGB color space
1266 const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1267 *pOut++ = rendering::ARGBColor(nAlpha,
1268 nAlpha*toDoubleColor(aCol.GetRed()),
1269 nAlpha*toDoubleColor(aCol.GetGreen()),
1270 nAlpha*toDoubleColor(aCol.GetBlue()));
1271 pIn += nBytesPerPixel;
1274 else
1276 for( sal_Int32 i=0; i<nNumColors; ++i )
1278 const BitmapColor aCol =
1279 m_bPalette ?
1280 m_pBmpAcc->GetPaletteColor( m_pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1281 m_pBmpAcc->GetPixelFromData(pIn, i);
1283 // TODO(F3): Convert result to sRGB color space
1284 *pOut++ = rendering::ARGBColor(1.0,
1285 toDoubleColor(aCol.GetRed()),
1286 toDoubleColor(aCol.GetGreen()),
1287 toDoubleColor(aCol.GetBlue()));
1291 return aRes;
1294 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1296 SolarMutexGuard aGuard;
1298 const sal_Size 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());
1304 if( m_aBmpEx.IsTransparent() )
1306 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1307 for( sal_Size i=0; i<nLen; ++i )
1309 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1310 toByteColor(rgbColor[i].Green),
1311 toByteColor(rgbColor[i].Blue));
1312 const BitmapColor aCol2 =
1313 m_bPalette ?
1314 BitmapColor(
1315 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1316 aCol;
1318 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1319 pColors += nNonAlphaBytes;
1320 *pColors++ = sal_uInt8(255);
1323 else
1325 for( sal_Size i=0; i<nLen; ++i )
1327 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1328 toByteColor(rgbColor[i].Green),
1329 toByteColor(rgbColor[i].Blue));
1330 const BitmapColor aCol2 =
1331 m_bPalette ?
1332 BitmapColor(
1333 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1334 aCol;
1336 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1340 return aRes;
1343 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1345 SolarMutexGuard aGuard;
1347 const sal_Size nLen( rgbColor.getLength() );
1348 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1350 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1351 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1353 if( m_aBmpEx.IsTransparent() )
1355 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1356 for( sal_Size i=0; i<nLen; ++i )
1358 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1359 toByteColor(rgbColor[i].Green),
1360 toByteColor(rgbColor[i].Blue));
1361 const BitmapColor aCol2 =
1362 m_bPalette ?
1363 BitmapColor(
1364 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1365 aCol;
1367 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1368 pColors += nNonAlphaBytes;
1369 *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1372 else
1374 for( sal_Size i=0; i<nLen; ++i )
1376 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1377 toByteColor(rgbColor[i].Green),
1378 toByteColor(rgbColor[i].Blue));
1379 const BitmapColor aCol2 =
1380 m_bPalette ?
1381 BitmapColor(
1382 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1383 aCol;
1385 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1389 return aRes;
1392 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException, std::exception)
1394 SolarMutexGuard aGuard;
1396 const sal_Size nLen( rgbColor.getLength() );
1397 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1399 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1400 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1402 if( m_aBmpEx.IsTransparent() )
1404 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1405 for( sal_Size i=0; i<nLen; ++i )
1407 const double nAlpha( rgbColor[i].Alpha );
1408 const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1409 toByteColor(rgbColor[i].Green / nAlpha),
1410 toByteColor(rgbColor[i].Blue / nAlpha));
1411 const BitmapColor aCol2 =
1412 m_bPalette ?
1413 BitmapColor(
1414 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1415 aCol;
1417 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1418 pColors += nNonAlphaBytes;
1419 *pColors++ = 255 - toByteColor(nAlpha);
1422 else
1424 for( sal_Size i=0; i<nLen; ++i )
1426 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1427 toByteColor(rgbColor[i].Green),
1428 toByteColor(rgbColor[i].Blue));
1429 const BitmapColor aCol2 =
1430 m_bPalette ?
1431 BitmapColor(
1432 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1433 aCol;
1435 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1439 return aRes;
1443 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */