Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / vcl / source / helper / canvasbitmap.cxx
blob5b38618a52779661a96200a4c83e37e8abc5f71c
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 .
21 #include <com/sun/star/util/Endianness.hpp>
22 #include <com/sun/star/rendering/ColorComponentTag.hpp>
23 #include <com/sun/star/rendering/ColorSpaceType.hpp>
24 #include <com/sun/star/rendering/RenderingIntent.hpp>
26 #include <rtl/instance.hxx>
27 #include <osl/mutex.hxx>
29 #include <tools/diagnose_ex.h>
30 #include <canvasbitmap.hxx>
31 #include <vcl/canvastools.hxx>
32 #include <vcl/bmpacc.hxx>
33 #include <vcl/svapp.hxx>
35 #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 inline 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_uLong redShift, sal_uLong greenShift, sal_uLong 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(sal::static_int_cast<sal_uInt32>(redShift));
95 pCounts[greenPos] = bitcount(sal::static_int_cast<sal_uInt32>(greenShift));
96 pCounts[bluePos] = bitcount(sal::static_int_cast<sal_uInt32>(blueShift));
99 VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
100 m_aBmpEx( rBitmap ),
101 m_aBitmap( rBitmap.GetBitmap() ),
102 m_aAlpha(),
103 m_pBmpAcc( m_aBitmap.AcquireReadAccess() ),
104 m_pAlphaAcc( NULL ),
105 m_aComponentTags(),
106 m_aComponentBitCounts(),
107 m_aLayout(),
108 m_nBitsPerInputPixel(0),
109 m_nBitsPerOutputPixel(0),
110 m_nRedIndex(-1),
111 m_nGreenIndex(-1),
112 m_nBlueIndex(-1),
113 m_nAlphaIndex(-1),
114 m_nIndexIndex(-1),
115 m_nEndianness(0),
116 m_bPalette(false)
118 if( m_aBmpEx.IsTransparent() )
120 m_aAlpha = m_aBmpEx.IsAlpha() ? m_aBmpEx.GetAlpha().GetBitmap() : m_aBmpEx.GetMask();
121 m_pAlphaAcc = m_aAlpha.AcquireReadAccess();
124 m_aLayout.ScanLines = 0;
125 m_aLayout.ScanLineBytes = 0;
126 m_aLayout.ScanLineStride = 0;
127 m_aLayout.PlaneStride = 0;
128 m_aLayout.ColorSpace.clear();
129 m_aLayout.Palette.clear();
130 m_aLayout.IsMsbFirst = sal_False;
132 if( m_pBmpAcc )
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 BMP_FORMAT_1BIT_MSB_PAL:
142 m_bPalette = true;
143 m_nBitsPerInputPixel = 1;
144 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
145 m_aLayout.IsMsbFirst = sal_True;
146 break;
148 case BMP_FORMAT_1BIT_LSB_PAL:
149 m_bPalette = true;
150 m_nBitsPerInputPixel = 1;
151 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
152 m_aLayout.IsMsbFirst = sal_False;
153 break;
155 case BMP_FORMAT_4BIT_MSN_PAL:
156 m_bPalette = true;
157 m_nBitsPerInputPixel = 4;
158 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
159 m_aLayout.IsMsbFirst = sal_True;
160 break;
162 case BMP_FORMAT_4BIT_LSN_PAL:
163 m_bPalette = true;
164 m_nBitsPerInputPixel = 4;
165 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
166 m_aLayout.IsMsbFirst = sal_False;
167 break;
169 case BMP_FORMAT_8BIT_PAL:
170 m_bPalette = true;
171 m_nBitsPerInputPixel = 8;
172 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
173 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
174 break;
176 case BMP_FORMAT_8BIT_TC_MASK:
177 m_bPalette = false;
178 m_nBitsPerInputPixel = 8;
179 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
180 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
181 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
182 m_pBmpAcc->GetColorMask().GetGreenMask(),
183 m_pBmpAcc->GetColorMask().GetBlueMask() );
184 break;
186 case BMP_FORMAT_16BIT_TC_MSB_MASK:
187 m_bPalette = false;
188 m_nBitsPerInputPixel = 16;
189 m_nEndianness = util::Endianness::BIG;
190 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
191 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
192 m_pBmpAcc->GetColorMask().GetGreenMask(),
193 m_pBmpAcc->GetColorMask().GetBlueMask() );
194 break;
196 case BMP_FORMAT_16BIT_TC_LSB_MASK:
197 m_bPalette = false;
198 m_nBitsPerInputPixel = 16;
199 m_nEndianness = util::Endianness::LITTLE;
200 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
201 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
202 m_pBmpAcc->GetColorMask().GetGreenMask(),
203 m_pBmpAcc->GetColorMask().GetBlueMask() );
204 break;
206 case BMP_FORMAT_24BIT_TC_BGR:
207 m_bPalette = false;
208 m_nBitsPerInputPixel = 24;
209 m_nEndianness = util::Endianness::LITTLE;
210 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
211 setComponentInfo( 0xff0000LL,
212 0x00ff00LL,
213 0x0000ffLL );
214 break;
216 case BMP_FORMAT_24BIT_TC_RGB:
217 m_bPalette = false;
218 m_nBitsPerInputPixel = 24;
219 m_nEndianness = util::Endianness::LITTLE;
220 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
221 setComponentInfo( 0x0000ffLL,
222 0x00ff00LL,
223 0xff0000LL );
224 break;
226 case BMP_FORMAT_24BIT_TC_MASK:
227 m_bPalette = false;
228 m_nBitsPerInputPixel = 24;
229 m_nEndianness = util::Endianness::LITTLE;
230 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
231 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
232 m_pBmpAcc->GetColorMask().GetGreenMask(),
233 m_pBmpAcc->GetColorMask().GetBlueMask() );
234 break;
236 case BMP_FORMAT_32BIT_TC_ABGR:
238 m_bPalette = false;
239 m_nBitsPerInputPixel = 32;
240 m_nEndianness = util::Endianness::LITTLE;
241 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
243 m_aComponentTags.realloc(4);
244 sal_Int8* pTags = m_aComponentTags.getArray();
245 pTags[0] = rendering::ColorComponentTag::ALPHA;
246 pTags[1] = rendering::ColorComponentTag::RGB_BLUE;
247 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
248 pTags[3] = rendering::ColorComponentTag::RGB_RED;
250 m_aComponentBitCounts.realloc(4);
251 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
252 pCounts[0] = 8;
253 pCounts[1] = 8;
254 pCounts[2] = 8;
255 pCounts[3] = 8;
257 m_nRedIndex = 3;
258 m_nGreenIndex = 2;
259 m_nBlueIndex = 1;
260 m_nAlphaIndex = 0;
262 break;
264 case BMP_FORMAT_32BIT_TC_ARGB:
266 m_bPalette = false;
267 m_nBitsPerInputPixel = 32;
268 m_nEndianness = util::Endianness::LITTLE;
269 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
271 m_aComponentTags.realloc(4);
272 sal_Int8* pTags = m_aComponentTags.getArray();
273 pTags[0] = rendering::ColorComponentTag::ALPHA;
274 pTags[1] = rendering::ColorComponentTag::RGB_RED;
275 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
276 pTags[3] = rendering::ColorComponentTag::RGB_BLUE;
278 m_aComponentBitCounts.realloc(4);
279 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
280 pCounts[0] = 8;
281 pCounts[1] = 8;
282 pCounts[2] = 8;
283 pCounts[3] = 8;
285 m_nRedIndex = 1;
286 m_nGreenIndex = 2;
287 m_nBlueIndex = 3;
288 m_nAlphaIndex = 0;
290 break;
292 case BMP_FORMAT_32BIT_TC_BGRA:
294 m_bPalette = false;
295 m_nBitsPerInputPixel = 32;
296 m_nEndianness = util::Endianness::LITTLE;
297 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
299 m_aComponentTags.realloc(4);
300 sal_Int8* pTags = m_aComponentTags.getArray();
301 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
302 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
303 pTags[2] = rendering::ColorComponentTag::RGB_RED;
304 pTags[3] = rendering::ColorComponentTag::ALPHA;
306 m_aComponentBitCounts.realloc(4);
307 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
308 pCounts[0] = 8;
309 pCounts[1] = 8;
310 pCounts[2] = 8;
311 pCounts[3] = 8;
313 m_nRedIndex = 2;
314 m_nGreenIndex = 1;
315 m_nBlueIndex = 0;
316 m_nAlphaIndex = 3;
318 break;
320 case BMP_FORMAT_32BIT_TC_RGBA:
322 m_bPalette = false;
323 m_nBitsPerInputPixel = 32;
324 m_nEndianness = util::Endianness::LITTLE;
325 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
327 m_aComponentTags.realloc(4);
328 sal_Int8* pTags = m_aComponentTags.getArray();
329 pTags[0] = rendering::ColorComponentTag::RGB_RED;
330 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
331 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
332 pTags[3] = rendering::ColorComponentTag::ALPHA;
334 m_aComponentBitCounts.realloc(4);
335 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
336 pCounts[0] = 8;
337 pCounts[1] = 8;
338 pCounts[2] = 8;
339 pCounts[3] = 8;
341 m_nRedIndex = 0;
342 m_nGreenIndex = 1;
343 m_nBlueIndex = 2;
344 m_nAlphaIndex = 3;
346 break;
348 case BMP_FORMAT_32BIT_TC_MASK:
349 m_bPalette = false;
350 m_nBitsPerInputPixel = 32;
351 m_nEndianness = util::Endianness::LITTLE;
352 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
353 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
354 m_pBmpAcc->GetColorMask().GetGreenMask(),
355 m_pBmpAcc->GetColorMask().GetBlueMask() );
356 break;
358 default:
359 OSL_FAIL( "unsupported bitmap format" );
360 break;
363 if( m_bPalette )
365 m_aComponentTags.realloc(1);
366 m_aComponentTags[0] = rendering::ColorComponentTag::INDEX;
368 m_aComponentBitCounts.realloc(1);
369 m_aComponentBitCounts[0] = m_nBitsPerInputPixel;
371 m_nIndexIndex = 0;
374 m_nBitsPerOutputPixel = m_nBitsPerInputPixel;
375 if( m_aBmpEx.IsTransparent() )
377 // TODO(P1): need to interleave alpha with bitmap data -
378 // won't fuss with less-than-8 bit for now
379 m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
381 // check whether alpha goes in front or behind the
382 // bitcount sequence. If pixel format is little endian,
383 // put it behind all the other channels. If it's big
384 // endian, put it in front (because later, the actual data
385 // always gets written after the pixel data)
387 // TODO(Q1): slight catch - in the case of the
388 // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
389 // channels might happen!
390 m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
391 m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
393 m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
394 m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
396 if( m_nEndianness == util::Endianness::BIG )
398 // put alpha in front of all the color channels
399 sal_Int8* pTags =m_aComponentTags.getArray();
400 sal_Int32* pCounts=m_aComponentBitCounts.getArray();
401 std::rotate(pTags,
402 pTags+m_aComponentTags.getLength()-1,
403 pTags+m_aComponentTags.getLength());
404 std::rotate(pCounts,
405 pCounts+m_aComponentBitCounts.getLength()-1,
406 pCounts+m_aComponentBitCounts.getLength());
407 ++m_nRedIndex;
408 ++m_nGreenIndex;
409 ++m_nBlueIndex;
410 ++m_nIndexIndex;
411 m_nAlphaIndex=0;
414 // always add a full byte to the pixel size, otherwise
415 // pixel packing hell breaks loose.
416 m_nBitsPerOutputPixel += 8;
418 // adapt scanline parameters
419 const Size aSize = m_aBitmap.GetSizePixel();
420 m_aLayout.ScanLineBytes =
421 m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
426 VclCanvasBitmap::~VclCanvasBitmap()
428 if( m_pAlphaAcc )
429 m_aAlpha.ReleaseAccess(m_pAlphaAcc);
430 if( m_pBmpAcc )
431 m_aBitmap.ReleaseAccess(m_pBmpAcc);
434 // XBitmap
435 geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize() throw (uno::RuntimeException)
437 SolarMutexGuard aGuard;
438 return integerSize2DFromSize( m_aBitmap.GetSizePixel() );
441 ::sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha() throw (uno::RuntimeException)
443 SolarMutexGuard aGuard;
444 return m_aBmpEx.IsTransparent();
447 uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
448 sal_Bool beFast ) throw (uno::RuntimeException)
450 SolarMutexGuard aGuard;
452 BitmapEx aNewBmp( m_aBitmap );
453 aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_FAST : BMP_SCALE_DEFAULT );
454 return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
457 // XIntegerReadOnlyBitmap
458 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
459 const geometry::IntegerRectangle2D& rect ) throw( lang::IndexOutOfBoundsException,
460 rendering::VolatileContentDestroyedException,
461 uno::RuntimeException)
463 SolarMutexGuard aGuard;
465 bitmapLayout = getMemoryLayout();
467 const ::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
468 if( aRequestedArea.IsEmpty() )
469 return uno::Sequence< sal_Int8 >();
471 // Invalid/empty bitmap: no data available
472 if( !m_pBmpAcc )
473 throw lang::IndexOutOfBoundsException();
474 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
475 throw lang::IndexOutOfBoundsException();
477 if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
478 aRequestedArea.Right() > m_pBmpAcc->Width() ||
479 aRequestedArea.Bottom() > m_pBmpAcc->Height() )
481 throw lang::IndexOutOfBoundsException();
484 uno::Sequence< sal_Int8 > aRet;
485 Rectangle aRequestedBytes( aRequestedArea );
487 // adapt to byte boundaries
488 aRequestedBytes.Left() = aRequestedArea.Left()*m_nBitsPerOutputPixel/8;
489 aRequestedBytes.Right() = (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8;
491 // copy stuff to output sequence
492 aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight());
493 sal_Int8* pOutBuf = aRet.getArray();
495 bitmapLayout.ScanLines = aRequestedBytes.getHeight();
496 bitmapLayout.ScanLineBytes =
497 bitmapLayout.ScanLineStride= aRequestedBytes.getWidth();
499 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
500 if( !(m_pBmpAcc->GetScanlineFormat() & BMP_FORMAT_TOP_DOWN) )
502 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1);
503 nScanlineStride *= -1;
506 if( !m_aBmpEx.IsTransparent() )
508 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
510 // can return bitmap data as-is
511 for( long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
513 Scanline pScan = m_pBmpAcc->GetScanline(y);
514 memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
515 pOutBuf += nScanlineStride;
518 else
520 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
521 OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
523 // interleave alpha with bitmap data - note, bitcount is
524 // always integer multiple of 8
525 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
526 "Transparent bitmap bitcount not integer multiple of 8" );
528 for( long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
530 sal_Int8* pOutScan = pOutBuf;
532 if( m_nBitsPerInputPixel < 8 )
534 // input less than a byte - copy via GetPixel()
535 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
537 *pOutScan++ = m_pBmpAcc->GetPixel(y,x);
538 *pOutScan++ = m_pAlphaAcc->GetPixel(y,x);
541 else
543 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
544 const long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
545 Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
547 // input integer multiple of byte - copy directly
548 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
550 for( long i=0; i<nNonAlphaBytes; ++i )
551 *pOutScan++ = *pScan++;
552 *pOutScan++ = m_pAlphaAcc->GetPixel(y,x);
556 pOutBuf += nScanlineStride;
560 return aRet;
563 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
564 const geometry::IntegerPoint2D& pos ) throw (lang::IndexOutOfBoundsException,
565 rendering::VolatileContentDestroyedException,
566 uno::RuntimeException)
568 SolarMutexGuard aGuard;
570 bitmapLayout = getMemoryLayout();
572 // Invalid/empty bitmap: no data available
573 if( !m_pBmpAcc )
574 throw lang::IndexOutOfBoundsException();
575 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
576 throw lang::IndexOutOfBoundsException();
578 if( pos.X < 0 || pos.Y < 0 ||
579 pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
581 throw lang::IndexOutOfBoundsException();
584 uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
585 sal_Int8* pOutBuf = aRet.getArray();
587 // copy stuff to output sequence
588 bitmapLayout.ScanLines = 1;
589 bitmapLayout.ScanLineBytes =
590 bitmapLayout.ScanLineStride= aRet.getLength();
592 const long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
593 if( !m_aBmpEx.IsTransparent() )
595 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
597 // can return bitmap data as-is
598 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
599 memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
601 else
603 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
604 OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
606 // interleave alpha with bitmap data - note, bitcount is
607 // always integer multiple of 8
608 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
609 "Transparent bitmap bitcount not integer multiple of 8" );
611 if( m_nBitsPerInputPixel < 8 )
613 // input less than a byte - copy via GetPixel()
614 *pOutBuf++ = m_pBmpAcc->GetPixel(pos.Y,pos.X);
615 *pOutBuf = m_pAlphaAcc->GetPixel(pos.Y,pos.X);
617 else
619 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
620 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
622 // input integer multiple of byte - copy directly
623 memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
624 pOutBuf += nNonAlphaBytes;
625 *pOutBuf++ = m_pAlphaAcc->GetPixel(pos.Y,pos.X);
629 return aRet;
632 uno::Reference< rendering::XBitmapPalette > SAL_CALL VclCanvasBitmap::getPalette() throw (uno::RuntimeException)
634 SolarMutexGuard aGuard;
636 uno::Reference< XBitmapPalette > aRet;
637 if( m_bPalette )
638 aRet.set(this);
640 return aRet;
643 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout() throw (uno::RuntimeException)
645 SolarMutexGuard aGuard;
647 rendering::IntegerBitmapLayout aLayout( m_aLayout );
649 // only set references to self on separate copy of
650 // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
651 // a circular reference!
652 if( m_bPalette )
653 aLayout.Palette.set( this );
655 aLayout.ColorSpace.set( this );
657 return aLayout;
660 sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries() throw (uno::RuntimeException)
662 SolarMutexGuard aGuard;
664 if( !m_pBmpAcc )
665 return 0;
667 return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ;
670 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
672 SolarMutexGuard aGuard;
674 const sal_uInt16 nCount( m_pBmpAcc ?
675 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
676 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
677 if( nIndex < 0 || nIndex >= nCount )
678 throw lang::IndexOutOfBoundsException(::rtl::OUString("Palette index out of range"),
679 static_cast<rendering::XBitmapPalette*>(this));
681 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
682 o_entry.realloc(3);
683 double* pColor=o_entry.getArray();
684 pColor[0] = aCol.GetRed();
685 pColor[1] = aCol.GetGreen();
686 pColor[2] = aCol.GetBlue();
688 return sal_True; // no palette transparency here.
691 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
693 SolarMutexGuard aGuard;
695 const sal_uInt16 nCount( m_pBmpAcc ?
696 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
698 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
699 if( nIndex < 0 || nIndex >= nCount )
700 throw lang::IndexOutOfBoundsException(::rtl::OUString("Palette index out of range"),
701 static_cast<rendering::XBitmapPalette*>(this));
703 return sal_False; // read-only implementation
706 namespace
708 struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
709 PaletteColorSpaceHolder>
711 uno::Reference<rendering::XColorSpace> operator()()
713 return vcl::unotools::createStandardColorSpace();
718 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( ) throw (uno::RuntimeException)
720 // this is the method from XBitmapPalette. Return palette color
721 // space here
722 return PaletteColorSpaceHolder::get();
725 sal_Int8 SAL_CALL VclCanvasBitmap::getType( ) throw (uno::RuntimeException)
727 return rendering::ColorSpaceType::RGB;
730 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( ) throw (uno::RuntimeException)
732 SolarMutexGuard aGuard;
733 return m_aComponentTags;
736 sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent( ) throw (uno::RuntimeException)
738 return rendering::RenderingIntent::PERCEPTUAL;
741 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( ) throw (uno::RuntimeException)
743 return uno::Sequence< ::beans::PropertyValue >();
746 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
747 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (uno::RuntimeException)
749 // TODO(P3): if we know anything about target
750 // colorspace, this can be greatly sped up
751 uno::Sequence<rendering::ARGBColor> aIntermediate(
752 convertToARGB(deviceColor));
753 return targetColorSpace->convertFromARGB(aIntermediate);
756 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
758 SolarMutexGuard aGuard;
760 const sal_Size nLen( deviceColor.getLength() );
761 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
762 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
763 "number of channels no multiple of pixel element count",
764 static_cast<rendering::XBitmapPalette*>(this), 01);
766 uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
767 rendering::RGBColor* pOut( aRes.getArray() );
769 if( m_bPalette )
771 OSL_ENSURE(m_nIndexIndex != -1,
772 "Invalid color channel indices");
773 ENSURE_OR_THROW(m_pBmpAcc,
774 "Unable to get BitmapAccess");
776 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
778 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
779 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
781 // TODO(F3): Convert result to sRGB color space
782 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
783 toDoubleColor(aCol.GetGreen()),
784 toDoubleColor(aCol.GetBlue()));
787 else
789 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
790 "Invalid color channel indices");
792 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
794 // TODO(F3): Convert result to sRGB color space
795 *pOut++ = rendering::RGBColor(
796 deviceColor[i+m_nRedIndex],
797 deviceColor[i+m_nGreenIndex],
798 deviceColor[i+m_nBlueIndex]);
802 return aRes;
805 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
807 SolarMutexGuard aGuard;
809 const sal_Size nLen( deviceColor.getLength() );
810 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
811 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
812 "number of channels no multiple of pixel element count",
813 static_cast<rendering::XBitmapPalette*>(this), 01);
815 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
816 rendering::ARGBColor* pOut( aRes.getArray() );
818 if( m_bPalette )
820 OSL_ENSURE(m_nIndexIndex != -1,
821 "Invalid color channel indices");
822 ENSURE_OR_THROW(m_pBmpAcc,
823 "Unable to get BitmapAccess");
825 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
827 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
828 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
830 // TODO(F3): Convert result to sRGB color space
831 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
832 *pOut++ = rendering::ARGBColor(nAlpha,
833 toDoubleColor(aCol.GetRed()),
834 toDoubleColor(aCol.GetGreen()),
835 toDoubleColor(aCol.GetBlue()));
838 else
840 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
841 "Invalid color channel indices");
843 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
845 // TODO(F3): Convert result to sRGB color space
846 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
847 *pOut++ = rendering::ARGBColor(
848 nAlpha,
849 deviceColor[i+m_nRedIndex],
850 deviceColor[i+m_nGreenIndex],
851 deviceColor[i+m_nBlueIndex]);
855 return aRes;
858 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
860 SolarMutexGuard aGuard;
862 const sal_Size nLen( deviceColor.getLength() );
863 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
864 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
865 "number of channels no multiple of pixel element count",
866 static_cast<rendering::XBitmapPalette*>(this), 01);
868 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
869 rendering::ARGBColor* pOut( aRes.getArray() );
871 if( m_bPalette )
873 OSL_ENSURE(m_nIndexIndex != -1,
874 "Invalid color channel indices");
875 ENSURE_OR_THROW(m_pBmpAcc,
876 "Unable to get BitmapAccess");
878 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
880 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
881 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
883 // TODO(F3): Convert result to sRGB color space
884 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
885 *pOut++ = rendering::ARGBColor(nAlpha,
886 nAlpha*toDoubleColor(aCol.GetRed()),
887 nAlpha*toDoubleColor(aCol.GetGreen()),
888 nAlpha*toDoubleColor(aCol.GetBlue()));
891 else
893 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
894 "Invalid color channel indices");
896 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
898 // TODO(F3): Convert result to sRGB color space
899 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
900 *pOut++ = rendering::ARGBColor(
901 nAlpha,
902 nAlpha*deviceColor[i+m_nRedIndex],
903 nAlpha*deviceColor[i+m_nGreenIndex],
904 nAlpha*deviceColor[i+m_nBlueIndex]);
908 return aRes;
911 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
913 SolarMutexGuard aGuard;
915 const sal_Size nLen( rgbColor.getLength() );
916 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
918 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
919 double* pColors=aRes.getArray();
921 if( m_bPalette )
923 for( sal_Size i=0; i<nLen; ++i )
925 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
926 BitmapColor(toByteColor(rgbColor[i].Red),
927 toByteColor(rgbColor[i].Green),
928 toByteColor(rgbColor[i].Blue)));
929 if( m_nAlphaIndex != -1 )
930 pColors[m_nAlphaIndex] = 1.0;
932 pColors += nComponentsPerPixel;
935 else
937 for( sal_Size i=0; i<nLen; ++i )
939 pColors[m_nRedIndex] = rgbColor[i].Red;
940 pColors[m_nGreenIndex] = rgbColor[i].Green;
941 pColors[m_nBlueIndex] = rgbColor[i].Blue;
942 if( m_nAlphaIndex != -1 )
943 pColors[m_nAlphaIndex] = 1.0;
945 pColors += nComponentsPerPixel;
948 return aRes;
951 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
953 SolarMutexGuard aGuard;
955 const sal_Size nLen( rgbColor.getLength() );
956 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
958 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
959 double* pColors=aRes.getArray();
961 if( m_bPalette )
963 for( sal_Size i=0; i<nLen; ++i )
965 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
966 BitmapColor(toByteColor(rgbColor[i].Red),
967 toByteColor(rgbColor[i].Green),
968 toByteColor(rgbColor[i].Blue)));
969 if( m_nAlphaIndex != -1 )
970 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
972 pColors += nComponentsPerPixel;
975 else
977 for( sal_Size i=0; i<nLen; ++i )
979 pColors[m_nRedIndex] = rgbColor[i].Red;
980 pColors[m_nGreenIndex] = rgbColor[i].Green;
981 pColors[m_nBlueIndex] = rgbColor[i].Blue;
982 if( m_nAlphaIndex != -1 )
983 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
985 pColors += nComponentsPerPixel;
988 return aRes;
991 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
993 SolarMutexGuard aGuard;
995 const sal_Size nLen( rgbColor.getLength() );
996 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
998 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
999 double* pColors=aRes.getArray();
1001 if( m_bPalette )
1003 for( sal_Size i=0; i<nLen; ++i )
1005 const double nAlpha( rgbColor[i].Alpha );
1006 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
1007 BitmapColor(toByteColor(rgbColor[i].Red / nAlpha),
1008 toByteColor(rgbColor[i].Green / nAlpha),
1009 toByteColor(rgbColor[i].Blue / nAlpha)));
1010 if( m_nAlphaIndex != -1 )
1011 pColors[m_nAlphaIndex] = nAlpha;
1013 pColors += nComponentsPerPixel;
1016 else
1018 for( sal_Size i=0; i<nLen; ++i )
1020 const double nAlpha( rgbColor[i].Alpha );
1021 pColors[m_nRedIndex] = rgbColor[i].Red / nAlpha;
1022 pColors[m_nGreenIndex] = rgbColor[i].Green / nAlpha;
1023 pColors[m_nBlueIndex] = rgbColor[i].Blue / nAlpha;
1024 if( m_nAlphaIndex != -1 )
1025 pColors[m_nAlphaIndex] = nAlpha;
1027 pColors += nComponentsPerPixel;
1030 return aRes;
1033 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( ) throw (uno::RuntimeException)
1035 SolarMutexGuard aGuard;
1036 return m_nBitsPerOutputPixel;
1039 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( ) throw (uno::RuntimeException)
1041 SolarMutexGuard aGuard;
1042 return m_aComponentBitCounts;
1045 sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness( ) throw (uno::RuntimeException)
1047 SolarMutexGuard aGuard;
1048 return m_nEndianness;
1051 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1052 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1054 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1056 SolarMutexGuard aGuard;
1058 const sal_Size nLen( deviceColor.getLength() );
1059 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1060 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1061 "number of channels no multiple of pixel element count",
1062 static_cast<rendering::XBitmapPalette*>(this), 01);
1064 uno::Sequence<double> aRes(nLen);
1065 double* pOut( aRes.getArray() );
1067 if( m_bPalette )
1069 OSL_ENSURE(m_nIndexIndex != -1,
1070 "Invalid color channel indices");
1071 ENSURE_OR_THROW(m_pBmpAcc,
1072 "Unable to get BitmapAccess");
1074 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1076 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1077 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
1079 // TODO(F3): Convert result to sRGB color space
1080 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1081 *pOut++ = toDoubleColor(aCol.GetRed());
1082 *pOut++ = toDoubleColor(aCol.GetGreen());
1083 *pOut++ = toDoubleColor(aCol.GetBlue());
1084 *pOut++ = nAlpha;
1087 else
1089 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1090 "Invalid color channel indices");
1092 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1094 // TODO(F3): Convert result to sRGB color space
1095 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1096 *pOut++ = deviceColor[i+m_nRedIndex];
1097 *pOut++ = deviceColor[i+m_nGreenIndex];
1098 *pOut++ = deviceColor[i+m_nBlueIndex];
1099 *pOut++ = nAlpha;
1103 return aRes;
1105 else
1107 // TODO(P3): if we know anything about target
1108 // colorspace, this can be greatly sped up
1109 uno::Sequence<rendering::ARGBColor> aIntermediate(
1110 convertIntegerToARGB(deviceColor));
1111 return targetColorSpace->convertFromARGB(aIntermediate);
1115 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1116 const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1118 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1120 // it's us, so simply pass-through the data
1121 return deviceColor;
1123 else
1125 // TODO(P3): if we know anything about target
1126 // colorspace, this can be greatly sped up
1127 uno::Sequence<rendering::ARGBColor> aIntermediate(
1128 convertIntegerToARGB(deviceColor));
1129 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1133 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1135 SolarMutexGuard aGuard;
1137 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1138 const sal_Size nLen( deviceColor.getLength() );
1139 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1141 uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1142 rendering::RGBColor* pOut( aRes.getArray() );
1144 ENSURE_OR_THROW(m_pBmpAcc,
1145 "Unable to get BitmapAccess");
1147 if( m_aBmpEx.IsTransparent() )
1149 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1150 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1152 // if palette, index is guaranteed to be 8 bit
1153 const BitmapColor aCol =
1154 m_bPalette ?
1155 m_pBmpAcc->GetPaletteColor(*pIn) :
1156 m_pBmpAcc->GetPixelFromData(pIn,0);
1158 // TODO(F3): Convert result to sRGB color space
1159 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1160 toDoubleColor(aCol.GetGreen()),
1161 toDoubleColor(aCol.GetBlue()));
1162 // skips alpha
1163 pIn += nBytesPerPixel;
1166 else
1168 for( sal_Int32 i=0; i<nNumColors; ++i )
1170 const BitmapColor aCol =
1171 m_bPalette ?
1172 m_pBmpAcc->GetPaletteColor(
1173 sal::static_int_cast<sal_uInt16>(
1174 m_pBmpAcc->GetPixelFromData(
1175 pIn, i ))) :
1176 m_pBmpAcc->GetPixelFromData(pIn, i);
1178 // TODO(F3): Convert result to sRGB color space
1179 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1180 toDoubleColor(aCol.GetGreen()),
1181 toDoubleColor(aCol.GetBlue()));
1185 return aRes;
1188 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1190 SolarMutexGuard aGuard;
1192 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1193 const sal_Size nLen( deviceColor.getLength() );
1194 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1196 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1197 rendering::ARGBColor* pOut( aRes.getArray() );
1199 ENSURE_OR_THROW(m_pBmpAcc,
1200 "Unable to get BitmapAccess");
1202 if( m_aBmpEx.IsTransparent() )
1204 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1205 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1206 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1207 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1209 // if palette, index is guaranteed to be 8 bit
1210 const BitmapColor aCol =
1211 m_bPalette ?
1212 m_pBmpAcc->GetPaletteColor(*pIn) :
1213 m_pBmpAcc->GetPixelFromData(pIn,0);
1215 // TODO(F3): Convert result to sRGB color space
1216 *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1217 toDoubleColor(aCol.GetRed()),
1218 toDoubleColor(aCol.GetGreen()),
1219 toDoubleColor(aCol.GetBlue()));
1220 pIn += nBytesPerPixel;
1223 else
1225 for( sal_Int32 i=0; i<nNumColors; ++i )
1227 const BitmapColor aCol =
1228 m_bPalette ?
1229 m_pBmpAcc->GetPaletteColor(
1230 sal::static_int_cast<sal_uInt16>(
1231 m_pBmpAcc->GetPixelFromData(
1232 pIn, i ))) :
1233 m_pBmpAcc->GetPixelFromData(pIn, i);
1235 // TODO(F3): Convert result to sRGB color space
1236 *pOut++ = rendering::ARGBColor(1.0,
1237 toDoubleColor(aCol.GetRed()),
1238 toDoubleColor(aCol.GetGreen()),
1239 toDoubleColor(aCol.GetBlue()));
1243 return aRes;
1246 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1248 SolarMutexGuard aGuard;
1250 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1251 const sal_Size nLen( deviceColor.getLength() );
1252 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1254 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1255 rendering::ARGBColor* pOut( aRes.getArray() );
1257 ENSURE_OR_THROW(m_pBmpAcc,
1258 "Unable to get BitmapAccess");
1260 if( m_aBmpEx.IsTransparent() )
1262 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1263 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1264 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1265 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1267 // if palette, index is guaranteed to be 8 bit
1268 const BitmapColor aCol =
1269 m_bPalette ?
1270 m_pBmpAcc->GetPaletteColor(*pIn) :
1271 m_pBmpAcc->GetPixelFromData(pIn,0);
1273 // TODO(F3): Convert result to sRGB color space
1274 const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1275 *pOut++ = rendering::ARGBColor(nAlpha,
1276 nAlpha*toDoubleColor(aCol.GetRed()),
1277 nAlpha*toDoubleColor(aCol.GetGreen()),
1278 nAlpha*toDoubleColor(aCol.GetBlue()));
1279 pIn += nBytesPerPixel;
1282 else
1284 for( sal_Int32 i=0; i<nNumColors; ++i )
1286 const BitmapColor aCol =
1287 m_bPalette ?
1288 m_pBmpAcc->GetPaletteColor(
1289 sal::static_int_cast<sal_uInt16>(
1290 m_pBmpAcc->GetPixelFromData(
1291 pIn, i ))) :
1292 m_pBmpAcc->GetPixelFromData(pIn, i);
1294 // TODO(F3): Convert result to sRGB color space
1295 *pOut++ = rendering::ARGBColor(1.0,
1296 toDoubleColor(aCol.GetRed()),
1297 toDoubleColor(aCol.GetGreen()),
1298 toDoubleColor(aCol.GetBlue()));
1302 return aRes;
1305 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1307 SolarMutexGuard aGuard;
1309 const sal_Size nLen( rgbColor.getLength() );
1310 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1312 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1313 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1315 if( m_aBmpEx.IsTransparent() )
1317 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1318 for( sal_Size i=0; i<nLen; ++i )
1320 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1321 toByteColor(rgbColor[i].Green),
1322 toByteColor(rgbColor[i].Blue));
1323 const BitmapColor aCol2 =
1324 m_bPalette ?
1325 BitmapColor(
1326 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1327 aCol;
1329 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1330 pColors += nNonAlphaBytes;
1331 *pColors++ = sal_uInt8(255);
1334 else
1336 for( sal_Size i=0; i<nLen; ++i )
1338 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1339 toByteColor(rgbColor[i].Green),
1340 toByteColor(rgbColor[i].Blue));
1341 const BitmapColor aCol2 =
1342 m_bPalette ?
1343 BitmapColor(
1344 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1345 aCol;
1347 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1351 return aRes;
1354 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1356 SolarMutexGuard aGuard;
1358 const sal_Size nLen( rgbColor.getLength() );
1359 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1361 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1362 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1364 if( m_aBmpEx.IsTransparent() )
1366 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1367 for( sal_Size i=0; i<nLen; ++i )
1369 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1370 toByteColor(rgbColor[i].Green),
1371 toByteColor(rgbColor[i].Blue));
1372 const BitmapColor aCol2 =
1373 m_bPalette ?
1374 BitmapColor(
1375 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1376 aCol;
1378 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1379 pColors += nNonAlphaBytes;
1380 *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1383 else
1385 for( sal_Size i=0; i<nLen; ++i )
1387 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1388 toByteColor(rgbColor[i].Green),
1389 toByteColor(rgbColor[i].Blue));
1390 const BitmapColor aCol2 =
1391 m_bPalette ?
1392 BitmapColor(
1393 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1394 aCol;
1396 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1400 return aRes;
1403 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1405 SolarMutexGuard aGuard;
1407 const sal_Size nLen( rgbColor.getLength() );
1408 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1410 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1411 sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1413 if( m_aBmpEx.IsTransparent() )
1415 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1416 for( sal_Size i=0; i<nLen; ++i )
1418 const double nAlpha( rgbColor[i].Alpha );
1419 const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1420 toByteColor(rgbColor[i].Green / nAlpha),
1421 toByteColor(rgbColor[i].Blue / nAlpha));
1422 const BitmapColor aCol2 =
1423 m_bPalette ?
1424 BitmapColor(
1425 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1426 aCol;
1428 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1429 pColors += nNonAlphaBytes;
1430 *pColors++ = 255 - toByteColor(nAlpha);
1433 else
1435 for( sal_Size i=0; i<nLen; ++i )
1437 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1438 toByteColor(rgbColor[i].Green),
1439 toByteColor(rgbColor[i].Blue));
1440 const BitmapColor aCol2 =
1441 m_bPalette ?
1442 BitmapColor(
1443 sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1444 aCol;
1446 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1450 return aRes;
1453 BitmapEx VclCanvasBitmap::getBitmapEx() const
1455 return m_aBmpEx;
1458 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */