merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / helper / canvasbitmap.cxx
blob50f9a355f5ba0746d7b785e0b5fcaac4a1e16ce6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: canvasbitmap.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <com/sun/star/util/Endianness.hpp>
35 #include <com/sun/star/rendering/ColorComponentTag.hpp>
36 #include <com/sun/star/rendering/ColorSpaceType.hpp>
37 #include <com/sun/star/rendering/RenderingIntent.hpp>
39 #include <rtl/instance.hxx>
40 #include <vos/mutex.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <vcl/canvasbitmap.hxx>
44 #include <vcl/canvastools.hxx>
45 #include <vcl/bmpacc.hxx>
46 #include <vcl/svapp.hxx>
48 #include <algorithm>
51 using namespace ::vcl::unotools;
52 using namespace ::com::sun::star;
54 namespace
56 // TODO(Q3): move to o3tl bithacks or somesuch. A similar method is in canvas/canvastools.hxx
58 // Good ole HAKMEM tradition. Calc number of 1 bits in 32bit word,
59 // unrolled loop. See e.g. Hackers Delight, p. 66
60 inline sal_Int32 bitcount( sal_uInt32 val )
62 val = val - ((val >> 1) & 0x55555555);
63 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
64 val = (val + (val >> 4)) & 0x0F0F0F0F;
65 val = val + (val >> 8);
66 val = val + (val >> 16);
67 return sal_Int32(val & 0x0000003F);
71 void VclCanvasBitmap::setComponentInfo( ULONG redShift, ULONG greenShift, ULONG blueShift )
73 // sort channels in increasing order of appearance in the pixel
74 // (starting with the least significant bits)
75 sal_Int8 redPos(0);
76 sal_Int8 greenPos(1);
77 sal_Int8 bluePos(2);
79 if( redShift > greenShift )
81 std::swap(redPos,greenPos);
82 if( redShift > blueShift )
84 std::swap(redPos,bluePos);
85 if( greenShift > blueShift )
86 std::swap(greenPos,bluePos);
89 else
91 if( greenShift > blueShift )
93 std::swap(greenPos,bluePos);
94 if( redShift > blueShift )
95 std::swap(redPos,bluePos);
99 m_aComponentTags.realloc(3);
100 sal_Int8* pTags = m_aComponentTags.getArray();
101 pTags[redPos] = rendering::ColorComponentTag::RGB_RED;
102 pTags[greenPos] = rendering::ColorComponentTag::RGB_GREEN;
103 pTags[bluePos] = rendering::ColorComponentTag::RGB_BLUE;
105 m_aComponentBitCounts.realloc(3);
106 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
107 pCounts[redPos] = bitcount(sal::static_int_cast<sal_uInt32>(redShift));
108 pCounts[greenPos] = bitcount(sal::static_int_cast<sal_uInt32>(greenShift));
109 pCounts[bluePos] = bitcount(sal::static_int_cast<sal_uInt32>(blueShift));
112 VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) :
113 m_aBmpEx( rBitmap ),
114 m_aBitmap( rBitmap.GetBitmap() ),
115 m_aAlpha(),
116 m_pBmpAcc( m_aBitmap.AcquireReadAccess() ),
117 m_pAlphaAcc( NULL ),
118 m_aComponentTags(),
119 m_aComponentBitCounts(),
120 m_aLayout(),
121 m_nBitsPerInputPixel(0),
122 m_nBitsPerOutputPixel(0),
123 m_nRedIndex(-1),
124 m_nGreenIndex(-1),
125 m_nBlueIndex(-1),
126 m_nAlphaIndex(-1),
127 m_nIndexIndex(-1),
128 m_nEndianness(0),
129 m_bSwap(false),
130 m_bPalette(false)
132 if( m_aBmpEx.IsTransparent() )
134 m_aAlpha = m_aBmpEx.IsAlpha() ? m_aBmpEx.GetAlpha().GetBitmap() : m_aBmpEx.GetMask();
135 m_pAlphaAcc = m_aAlpha.AcquireReadAccess();
138 m_aLayout.ScanLines = 0;
139 m_aLayout.ScanLineBytes = 0;
140 m_aLayout.ScanLineStride = 0;
141 m_aLayout.PlaneStride = 0;
142 m_aLayout.ColorSpace.clear();
143 m_aLayout.Palette.clear();
144 m_aLayout.IsMsbFirst = sal_False;
146 if( m_pBmpAcc )
148 m_aLayout.ScanLines = m_pBmpAcc->Height();
149 m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
150 m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
151 m_aLayout.PlaneStride = 0;
153 switch( m_pBmpAcc->GetScanlineFormat() )
155 case BMP_FORMAT_1BIT_MSB_PAL:
156 m_bPalette = true;
157 m_nBitsPerInputPixel = 1;
158 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
159 m_aLayout.IsMsbFirst = sal_True;
160 break;
162 case BMP_FORMAT_1BIT_LSB_PAL:
163 m_bPalette = true;
164 m_nBitsPerInputPixel = 1;
165 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
166 m_aLayout.IsMsbFirst = sal_False;
167 break;
169 case BMP_FORMAT_4BIT_MSN_PAL:
170 m_bPalette = true;
171 m_nBitsPerInputPixel = 4;
172 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
173 m_aLayout.IsMsbFirst = sal_True;
174 break;
176 case BMP_FORMAT_4BIT_LSN_PAL:
177 m_bPalette = true;
178 m_nBitsPerInputPixel = 4;
179 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
180 m_aLayout.IsMsbFirst = sal_False;
181 break;
183 case BMP_FORMAT_8BIT_PAL:
184 m_bPalette = true;
185 m_nBitsPerInputPixel = 8;
186 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
187 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
188 break;
190 case BMP_FORMAT_8BIT_TC_MASK:
191 m_bPalette = false;
192 m_nBitsPerInputPixel = 8;
193 m_nEndianness = util::Endianness::LITTLE; // doesn't matter
194 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
195 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
196 m_pBmpAcc->GetColorMask().GetGreenMask(),
197 m_pBmpAcc->GetColorMask().GetBlueMask() );
198 break;
200 case BMP_FORMAT_16BIT_TC_MSB_MASK:
201 m_bPalette = false;
202 m_nBitsPerInputPixel = 16;
203 m_nEndianness = util::Endianness::BIG;
204 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
205 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
206 m_pBmpAcc->GetColorMask().GetGreenMask(),
207 m_pBmpAcc->GetColorMask().GetBlueMask() );
208 break;
210 case BMP_FORMAT_16BIT_TC_LSB_MASK:
211 m_bPalette = false;
212 m_nBitsPerInputPixel = 16;
213 m_nEndianness = util::Endianness::LITTLE;
214 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
215 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
216 m_pBmpAcc->GetColorMask().GetGreenMask(),
217 m_pBmpAcc->GetColorMask().GetBlueMask() );
218 break;
220 case BMP_FORMAT_24BIT_TC_BGR:
221 m_bPalette = false;
222 m_nBitsPerInputPixel = 24;
223 m_nEndianness = util::Endianness::LITTLE;
224 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
225 setComponentInfo( 0xff0000LL,
226 0x00ff00LL,
227 0x0000ffLL );
228 break;
230 case BMP_FORMAT_24BIT_TC_RGB:
231 m_bPalette = false;
232 m_nBitsPerInputPixel = 24;
233 m_nEndianness = util::Endianness::LITTLE;
234 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
235 setComponentInfo( 0x0000ffLL,
236 0x00ff00LL,
237 0xff0000LL );
238 break;
240 case BMP_FORMAT_24BIT_TC_MASK:
241 m_bPalette = false;
242 m_nBitsPerInputPixel = 24;
243 m_nEndianness = util::Endianness::LITTLE;
244 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
245 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
246 m_pBmpAcc->GetColorMask().GetGreenMask(),
247 m_pBmpAcc->GetColorMask().GetBlueMask() );
248 break;
250 case BMP_FORMAT_32BIT_TC_ABGR:
252 m_bPalette = false;
253 m_nBitsPerInputPixel = 32;
254 m_nEndianness = util::Endianness::LITTLE;
255 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
257 m_aComponentTags.realloc(4);
258 sal_Int8* pTags = m_aComponentTags.getArray();
259 pTags[0] = rendering::ColorComponentTag::ALPHA;
260 pTags[1] = rendering::ColorComponentTag::RGB_BLUE;
261 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
262 pTags[3] = rendering::ColorComponentTag::RGB_RED;
264 m_aComponentBitCounts.realloc(4);
265 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
266 pCounts[0] = 8;
267 pCounts[1] = 8;
268 pCounts[2] = 8;
269 pCounts[3] = 8;
271 m_nRedIndex = 3;
272 m_nGreenIndex = 2;
273 m_nBlueIndex = 1;
274 m_nAlphaIndex = 0;
276 break;
278 case BMP_FORMAT_32BIT_TC_ARGB:
280 m_bPalette = false;
281 m_nBitsPerInputPixel = 32;
282 m_nEndianness = util::Endianness::LITTLE;
283 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
285 m_aComponentTags.realloc(4);
286 sal_Int8* pTags = m_aComponentTags.getArray();
287 pTags[0] = rendering::ColorComponentTag::ALPHA;
288 pTags[1] = rendering::ColorComponentTag::RGB_RED;
289 pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
290 pTags[3] = rendering::ColorComponentTag::RGB_BLUE;
292 m_aComponentBitCounts.realloc(4);
293 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
294 pCounts[0] = 8;
295 pCounts[1] = 8;
296 pCounts[2] = 8;
297 pCounts[3] = 8;
299 m_nRedIndex = 1;
300 m_nGreenIndex = 2;
301 m_nBlueIndex = 3;
302 m_nAlphaIndex = 0;
304 break;
306 case BMP_FORMAT_32BIT_TC_BGRA:
308 m_bPalette = false;
309 m_nBitsPerInputPixel = 32;
310 m_nEndianness = util::Endianness::LITTLE;
311 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
313 m_aComponentTags.realloc(4);
314 sal_Int8* pTags = m_aComponentTags.getArray();
315 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
316 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
317 pTags[2] = rendering::ColorComponentTag::RGB_RED;
318 pTags[3] = rendering::ColorComponentTag::ALPHA;
320 m_aComponentBitCounts.realloc(4);
321 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
322 pCounts[0] = 8;
323 pCounts[1] = 8;
324 pCounts[2] = 8;
325 pCounts[3] = 8;
327 m_nRedIndex = 2;
328 m_nGreenIndex = 1;
329 m_nBlueIndex = 0;
330 m_nAlphaIndex = 3;
332 break;
334 case BMP_FORMAT_32BIT_TC_RGBA:
336 m_bPalette = false;
337 m_nBitsPerInputPixel = 32;
338 m_nEndianness = util::Endianness::LITTLE;
339 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
341 m_aComponentTags.realloc(4);
342 sal_Int8* pTags = m_aComponentTags.getArray();
343 pTags[0] = rendering::ColorComponentTag::RGB_RED;
344 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
345 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
346 pTags[3] = rendering::ColorComponentTag::ALPHA;
348 m_aComponentBitCounts.realloc(4);
349 sal_Int32* pCounts = m_aComponentBitCounts.getArray();
350 pCounts[0] = 8;
351 pCounts[1] = 8;
352 pCounts[2] = 8;
353 pCounts[3] = 8;
355 m_nRedIndex = 0;
356 m_nGreenIndex = 1;
357 m_nBlueIndex = 2;
358 m_nAlphaIndex = 3;
360 break;
362 case BMP_FORMAT_32BIT_TC_MASK:
363 m_bPalette = false;
364 m_nBitsPerInputPixel = 32;
365 m_nEndianness = util::Endianness::LITTLE;
366 m_aLayout.IsMsbFirst = sal_False; // doesn't matter
367 setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(),
368 m_pBmpAcc->GetColorMask().GetGreenMask(),
369 m_pBmpAcc->GetColorMask().GetBlueMask() );
370 break;
372 default:
373 DBG_ERROR( "unsupported bitmap format" );
374 break;
377 if( m_bPalette )
379 m_aComponentTags.realloc(1);
380 m_aComponentTags[0] = rendering::ColorComponentTag::INDEX;
382 m_aComponentBitCounts.realloc(1);
383 m_aComponentBitCounts[0] = m_nBitsPerInputPixel;
385 m_nIndexIndex = 0;
388 m_nBitsPerOutputPixel = m_nBitsPerInputPixel;
389 if( m_aBmpEx.IsTransparent() )
391 // TODO(P1): need to interleave alpha with bitmap data -
392 // won't fuss with less-than-8 bit for now
393 m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
395 // check whether alpha goes in front or behind the
396 // bitcount sequence. If pixel format is little endian,
397 // put it behind all the other channels. If it's big
398 // endian, put it in front (because later, the actual data
399 // always gets written after the pixel data)
401 // TODO(Q1): slight catch - in the case of the
402 // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
403 // channels might happen!
404 m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
405 m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
407 m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
408 m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
410 if( m_nEndianness == util::Endianness::BIG )
412 // put alpha in front of all the color channels
413 sal_Int8* pTags =m_aComponentTags.getArray();
414 sal_Int32* pCounts=m_aComponentBitCounts.getArray();
415 std::rotate(pTags,
416 pTags+m_aComponentTags.getLength()-1,
417 pTags+m_aComponentTags.getLength());
418 std::rotate(pCounts,
419 pCounts+m_aComponentBitCounts.getLength()-1,
420 pCounts+m_aComponentBitCounts.getLength());
421 ++m_nRedIndex;
422 ++m_nGreenIndex;
423 ++m_nBlueIndex;
424 ++m_nIndexIndex;
425 m_nAlphaIndex=0;
428 // always add a full byte to the pixel size, otherwise
429 // pixel packing hell breaks loose.
430 m_nBitsPerOutputPixel += 8;
432 // adapt scanline parameters
433 const Size aSize = m_aBitmap.GetSizePixel();
434 m_aLayout.ScanLineBytes =
435 m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
440 VclCanvasBitmap::~VclCanvasBitmap()
442 if( m_pAlphaAcc )
443 m_aAlpha.ReleaseAccess(m_pAlphaAcc);
444 if( m_pBmpAcc )
445 m_aBitmap.ReleaseAccess(m_pBmpAcc);
448 // XBitmap
449 geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize() throw (uno::RuntimeException)
451 vos::OGuard aGuard( Application::GetSolarMutex() );
452 return integerSize2DFromSize( m_aBitmap.GetSizePixel() );
455 ::sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha() throw (uno::RuntimeException)
457 vos::OGuard aGuard( Application::GetSolarMutex() );
458 return m_aBmpEx.IsTransparent();
461 uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
462 sal_Bool beFast ) throw (uno::RuntimeException)
464 vos::OGuard aGuard( Application::GetSolarMutex() );
466 BitmapEx aNewBmp( m_aBitmap );
467 aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_FAST : BMP_SCALE_INTERPOLATE );
468 return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
471 // XIntegerReadOnlyBitmap
472 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
473 const geometry::IntegerRectangle2D& rect ) throw( lang::IndexOutOfBoundsException,
474 rendering::VolatileContentDestroyedException,
475 uno::RuntimeException)
477 vos::OGuard aGuard( Application::GetSolarMutex() );
479 bitmapLayout = getMemoryLayout();
481 const ::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
482 if( aRequestedArea.IsEmpty() )
483 return uno::Sequence< sal_Int8 >();
485 // Invalid/empty bitmap: no data available
486 if( !m_pBmpAcc )
487 throw lang::IndexOutOfBoundsException();
488 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
489 throw lang::IndexOutOfBoundsException();
491 if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
492 aRequestedArea.Right() > m_pBmpAcc->Width() ||
493 aRequestedArea.Bottom() > m_pBmpAcc->Height() )
495 throw lang::IndexOutOfBoundsException();
498 uno::Sequence< sal_Int8 > aRet;
499 Rectangle aRequestedBytes( aRequestedArea );
501 // adapt to byte boundaries
502 aRequestedBytes.Left() = aRequestedArea.Left()*m_nBitsPerOutputPixel/8;
503 aRequestedBytes.Right() = (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8;
505 // copy stuff to output sequence
506 aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight());
507 sal_Int8* pOutBuf = aRet.getArray();
509 bitmapLayout.ScanLines = aRequestedBytes.getHeight();
510 bitmapLayout.ScanLineBytes =
511 bitmapLayout.ScanLineStride= aRequestedBytes.getWidth();
513 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
514 if( !(m_pBmpAcc->GetScanlineFormat() & BMP_FORMAT_TOP_DOWN) )
516 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1);
517 nScanlineStride *= -1;
520 if( !m_aBmpEx.IsTransparent() )
522 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
524 // can return bitmap data as-is
525 for( long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
527 Scanline pScan = m_pBmpAcc->GetScanline(y);
528 rtl_copyMemory(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
529 pOutBuf += nScanlineStride;
532 else
534 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
535 OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
537 // interleave alpha with bitmap data - note, bitcount is
538 // always integer multiple of 8
539 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
540 "Transparent bitmap bitcount not integer multiple of 8" );
542 for( long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
544 sal_Int8* pOutScan = pOutBuf;
546 if( m_nBitsPerInputPixel < 8 )
548 // input less than a byte - copy via GetPixel()
549 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
551 *pOutScan++ = m_pBmpAcc->GetPixel(y,x);
552 *pOutScan++ = m_pAlphaAcc->GetPixel(y,x);
555 else
557 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
558 const long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
559 Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
561 // input integer multiple of byte - copy directly
562 for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
564 for( long i=0; i<nNonAlphaBytes; ++i )
565 *pOutScan++ = *pScan++;
566 *pOutScan++ = m_pAlphaAcc->GetPixel(y,x);
570 pOutBuf += nScanlineStride;
574 return aRet;
577 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
578 const geometry::IntegerPoint2D& pos ) throw (lang::IndexOutOfBoundsException,
579 rendering::VolatileContentDestroyedException,
580 uno::RuntimeException)
582 vos::OGuard aGuard( Application::GetSolarMutex() );
584 bitmapLayout = getMemoryLayout();
586 // Invalid/empty bitmap: no data available
587 if( !m_pBmpAcc )
588 throw lang::IndexOutOfBoundsException();
589 if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc )
590 throw lang::IndexOutOfBoundsException();
592 if( pos.X < 0 || pos.Y < 0 ||
593 pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
595 throw lang::IndexOutOfBoundsException();
598 uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
599 sal_Int8* pOutBuf = aRet.getArray();
601 // copy stuff to output sequence
602 bitmapLayout.ScanLines = 1;
603 bitmapLayout.ScanLineBytes =
604 bitmapLayout.ScanLineStride= aRet.getLength();
606 const long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
607 if( !m_aBmpEx.IsTransparent() )
609 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
611 // can return bitmap data as-is
612 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
613 rtl_copyMemory(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
615 else
617 OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
618 OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
620 // interleave alpha with bitmap data - note, bitcount is
621 // always integer multiple of 8
622 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
623 "Transparent bitmap bitcount not integer multiple of 8" );
625 if( m_nBitsPerInputPixel < 8 )
627 // input less than a byte - copy via GetPixel()
628 *pOutBuf++ = m_pBmpAcc->GetPixel(pos.Y,pos.X);
629 *pOutBuf = m_pAlphaAcc->GetPixel(pos.Y,pos.X);
631 else
633 const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
634 Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
636 // input integer multiple of byte - copy directly
637 rtl_copyMemory(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
638 pOutBuf += nNonAlphaBytes;
639 *pOutBuf++ = m_pAlphaAcc->GetPixel(pos.Y,pos.X);
643 return aRet;
646 uno::Reference< rendering::XBitmapPalette > SAL_CALL VclCanvasBitmap::getPalette() throw (uno::RuntimeException)
648 vos::OGuard aGuard( Application::GetSolarMutex() );
650 uno::Reference< XBitmapPalette > aRet;
651 if( m_bPalette )
652 aRet.set(this);
654 return aRet;
657 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout() throw (uno::RuntimeException)
659 vos::OGuard aGuard( Application::GetSolarMutex() );
661 rendering::IntegerBitmapLayout aLayout( m_aLayout );
663 // only set references to self on separate copy of
664 // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
665 // a circular reference!
666 if( m_bPalette )
667 aLayout.Palette.set( this );
669 aLayout.ColorSpace.set( this );
671 return aLayout;
674 sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries() throw (uno::RuntimeException)
676 vos::OGuard aGuard( Application::GetSolarMutex() );
678 if( !m_pBmpAcc )
679 return 0;
681 return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ;
684 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
686 vos::OGuard aGuard( Application::GetSolarMutex() );
688 const USHORT nCount( m_pBmpAcc ?
689 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
690 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
691 if( nIndex < 0 || nIndex >= nCount )
692 throw lang::IndexOutOfBoundsException(::rtl::OUString::createFromAscii("Palette index out of range"),
693 static_cast<rendering::XBitmapPalette*>(this));
695 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<USHORT>(nIndex));
696 o_entry.realloc(3);
697 double* pColor=o_entry.getArray();
698 pColor[0] = aCol.GetRed();
699 pColor[1] = aCol.GetGreen();
700 pColor[2] = aCol.GetBlue();
702 return sal_True; // no palette transparency here.
705 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
707 vos::OGuard aGuard( Application::GetSolarMutex() );
709 const USHORT nCount( m_pBmpAcc ?
710 (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
712 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
713 if( nIndex < 0 || nIndex >= nCount )
714 throw lang::IndexOutOfBoundsException(::rtl::OUString::createFromAscii("Palette index out of range"),
715 static_cast<rendering::XBitmapPalette*>(this));
717 return sal_False; // read-only implementation
720 namespace
722 struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
723 PaletteColorSpaceHolder>
725 uno::Reference<rendering::XColorSpace> operator()()
727 return vcl::unotools::createStandardColorSpace();
732 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( ) throw (uno::RuntimeException)
734 // this is the method from XBitmapPalette. Return palette color
735 // space here
736 return PaletteColorSpaceHolder::get();
739 sal_Int8 SAL_CALL VclCanvasBitmap::getType( ) throw (uno::RuntimeException)
741 return rendering::ColorSpaceType::RGB;
744 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( ) throw (uno::RuntimeException)
746 vos::OGuard aGuard( Application::GetSolarMutex() );
747 return m_aComponentTags;
750 sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent( ) throw (uno::RuntimeException)
752 return rendering::RenderingIntent::PERCEPTUAL;
755 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( ) throw (uno::RuntimeException)
757 return uno::Sequence< ::beans::PropertyValue >();
760 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
761 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (uno::RuntimeException)
763 // TODO(P3): if we know anything about target
764 // colorspace, this can be greatly sped up
765 uno::Sequence<rendering::ARGBColor> aIntermediate(
766 convertToARGB(deviceColor));
767 return targetColorSpace->convertFromARGB(aIntermediate);
770 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
772 vos::OGuard aGuard( Application::GetSolarMutex() );
774 const sal_Size nLen( deviceColor.getLength() );
775 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
776 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
777 "number of channels no multiple of pixel element count",
778 static_cast<rendering::XBitmapPalette*>(this), 01);
780 uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
781 rendering::RGBColor* pOut( aRes.getArray() );
783 if( m_bPalette )
785 OSL_ENSURE(m_nIndexIndex != -1,
786 "Invalid color channel indices");
787 ENSURE_OR_THROW(m_pBmpAcc,
788 "Unable to get BitmapAccess");
790 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
792 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
793 sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex]));
795 // TODO(F3): Convert result to sRGB color space
796 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
797 toDoubleColor(aCol.GetGreen()),
798 toDoubleColor(aCol.GetBlue()));
801 else
803 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
804 "Invalid color channel indices");
806 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
808 // TODO(F3): Convert result to sRGB color space
809 *pOut++ = rendering::RGBColor(
810 deviceColor[i+m_nRedIndex],
811 deviceColor[i+m_nGreenIndex],
812 deviceColor[i+m_nBlueIndex]);
816 return aRes;
819 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
821 vos::OGuard aGuard( Application::GetSolarMutex() );
823 const sal_Size nLen( deviceColor.getLength() );
824 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
825 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
826 "number of channels no multiple of pixel element count",
827 static_cast<rendering::XBitmapPalette*>(this), 01);
829 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
830 rendering::ARGBColor* pOut( aRes.getArray() );
832 if( m_bPalette )
834 OSL_ENSURE(m_nIndexIndex != -1,
835 "Invalid color channel indices");
836 ENSURE_OR_THROW(m_pBmpAcc,
837 "Unable to get BitmapAccess");
839 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
841 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
842 sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex]));
844 // TODO(F3): Convert result to sRGB color space
845 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
846 *pOut++ = rendering::ARGBColor(nAlpha,
847 toDoubleColor(aCol.GetRed()),
848 toDoubleColor(aCol.GetGreen()),
849 toDoubleColor(aCol.GetBlue()));
852 else
854 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
855 "Invalid color channel indices");
857 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
859 // TODO(F3): Convert result to sRGB color space
860 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
861 *pOut++ = rendering::ARGBColor(
862 nAlpha,
863 deviceColor[i+m_nRedIndex],
864 deviceColor[i+m_nGreenIndex],
865 deviceColor[i+m_nBlueIndex]);
869 return aRes;
872 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
874 vos::OGuard aGuard( Application::GetSolarMutex() );
876 const sal_Size nLen( deviceColor.getLength() );
877 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
878 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
879 "number of channels no multiple of pixel element count",
880 static_cast<rendering::XBitmapPalette*>(this), 01);
882 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
883 rendering::ARGBColor* pOut( aRes.getArray() );
885 if( m_bPalette )
887 OSL_ENSURE(m_nIndexIndex != -1,
888 "Invalid color channel indices");
889 ENSURE_OR_THROW(m_pBmpAcc,
890 "Unable to get BitmapAccess");
892 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
894 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
895 sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex]));
897 // TODO(F3): Convert result to sRGB color space
898 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
899 *pOut++ = rendering::ARGBColor(nAlpha,
900 nAlpha*toDoubleColor(aCol.GetRed()),
901 nAlpha*toDoubleColor(aCol.GetGreen()),
902 nAlpha*toDoubleColor(aCol.GetBlue()));
905 else
907 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
908 "Invalid color channel indices");
910 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
912 // TODO(F3): Convert result to sRGB color space
913 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
914 *pOut++ = rendering::ARGBColor(
915 nAlpha,
916 nAlpha*deviceColor[i+m_nRedIndex],
917 nAlpha*deviceColor[i+m_nGreenIndex],
918 nAlpha*deviceColor[i+m_nBlueIndex]);
922 return aRes;
925 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
927 vos::OGuard aGuard( Application::GetSolarMutex() );
929 const sal_Size nLen( rgbColor.getLength() );
930 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
932 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
933 double* pColors=aRes.getArray();
935 if( m_bPalette )
937 for( sal_Size i=0; i<nLen; ++i )
939 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
940 BitmapColor(toByteColor(rgbColor[i].Red),
941 toByteColor(rgbColor[i].Green),
942 toByteColor(rgbColor[i].Blue)));
943 if( m_nAlphaIndex != -1 )
944 pColors[m_nAlphaIndex] = 1.0;
946 pColors += nComponentsPerPixel;
949 else
951 for( sal_Size i=0; i<nLen; ++i )
953 pColors[m_nRedIndex] = rgbColor[i].Red;
954 pColors[m_nGreenIndex] = rgbColor[i].Green;
955 pColors[m_nBlueIndex] = rgbColor[i].Blue;
956 if( m_nAlphaIndex != -1 )
957 pColors[m_nAlphaIndex] = 1.0;
959 pColors += nComponentsPerPixel;
962 return aRes;
965 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
967 vos::OGuard aGuard( Application::GetSolarMutex() );
969 const sal_Size nLen( rgbColor.getLength() );
970 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
972 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
973 double* pColors=aRes.getArray();
975 if( m_bPalette )
977 for( sal_Size i=0; i<nLen; ++i )
979 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
980 BitmapColor(toByteColor(rgbColor[i].Red),
981 toByteColor(rgbColor[i].Green),
982 toByteColor(rgbColor[i].Blue)));
983 if( m_nAlphaIndex != -1 )
984 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
986 pColors += nComponentsPerPixel;
989 else
991 for( sal_Size i=0; i<nLen; ++i )
993 pColors[m_nRedIndex] = rgbColor[i].Red;
994 pColors[m_nGreenIndex] = rgbColor[i].Green;
995 pColors[m_nBlueIndex] = rgbColor[i].Blue;
996 if( m_nAlphaIndex != -1 )
997 pColors[m_nAlphaIndex] = rgbColor[i].Alpha;
999 pColors += nComponentsPerPixel;
1002 return aRes;
1005 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1007 vos::OGuard aGuard( Application::GetSolarMutex() );
1009 const sal_Size nLen( rgbColor.getLength() );
1010 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1012 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
1013 double* pColors=aRes.getArray();
1015 if( m_bPalette )
1017 for( sal_Size i=0; i<nLen; ++i )
1019 const double nAlpha( rgbColor[i].Alpha );
1020 pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex(
1021 BitmapColor(toByteColor(rgbColor[i].Red / nAlpha),
1022 toByteColor(rgbColor[i].Green / nAlpha),
1023 toByteColor(rgbColor[i].Blue / nAlpha)));
1024 if( m_nAlphaIndex != -1 )
1025 pColors[m_nAlphaIndex] = nAlpha;
1027 pColors += nComponentsPerPixel;
1030 else
1032 for( sal_Size i=0; i<nLen; ++i )
1034 const double nAlpha( rgbColor[i].Alpha );
1035 pColors[m_nRedIndex] = rgbColor[i].Red / nAlpha;
1036 pColors[m_nGreenIndex] = rgbColor[i].Green / nAlpha;
1037 pColors[m_nBlueIndex] = rgbColor[i].Blue / nAlpha;
1038 if( m_nAlphaIndex != -1 )
1039 pColors[m_nAlphaIndex] = nAlpha;
1041 pColors += nComponentsPerPixel;
1044 return aRes;
1047 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( ) throw (uno::RuntimeException)
1049 vos::OGuard aGuard( Application::GetSolarMutex() );
1050 return m_nBitsPerOutputPixel;
1053 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( ) throw (uno::RuntimeException)
1055 vos::OGuard aGuard( Application::GetSolarMutex() );
1056 return m_aComponentBitCounts;
1059 sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness( ) throw (uno::RuntimeException)
1061 vos::OGuard aGuard( Application::GetSolarMutex() );
1062 return m_nEndianness;
1065 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1066 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1068 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1070 vos::OGuard aGuard( Application::GetSolarMutex() );
1072 const sal_Size nLen( deviceColor.getLength() );
1073 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1074 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1075 "number of channels no multiple of pixel element count",
1076 static_cast<rendering::XBitmapPalette*>(this), 01);
1078 uno::Sequence<double> aRes(nLen);
1079 double* pOut( aRes.getArray() );
1081 if( m_bPalette )
1083 OSL_ENSURE(m_nIndexIndex != -1,
1084 "Invalid color channel indices");
1085 ENSURE_OR_THROW(m_pBmpAcc,
1086 "Unable to get BitmapAccess");
1088 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1090 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1091 sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex]));
1093 // TODO(F3): Convert result to sRGB color space
1094 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1095 *pOut++ = toDoubleColor(aCol.GetRed());
1096 *pOut++ = toDoubleColor(aCol.GetGreen());
1097 *pOut++ = toDoubleColor(aCol.GetBlue());
1098 *pOut++ = nAlpha;
1101 else
1103 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1104 "Invalid color channel indices");
1106 for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel )
1108 // TODO(F3): Convert result to sRGB color space
1109 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1110 *pOut++ = deviceColor[i+m_nRedIndex];
1111 *pOut++ = deviceColor[i+m_nGreenIndex];
1112 *pOut++ = deviceColor[i+m_nBlueIndex];
1113 *pOut++ = nAlpha;
1117 return aRes;
1119 else
1121 // TODO(P3): if we know anything about target
1122 // colorspace, this can be greatly sped up
1123 uno::Sequence<rendering::ARGBColor> aIntermediate(
1124 convertIntegerToARGB(deviceColor));
1125 return targetColorSpace->convertFromARGB(aIntermediate);
1129 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1130 const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1132 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1134 // it's us, so simply pass-through the data
1135 return deviceColor;
1137 else
1139 // TODO(P3): if we know anything about target
1140 // colorspace, this can be greatly sped up
1141 uno::Sequence<rendering::ARGBColor> aIntermediate(
1142 convertIntegerToARGB(deviceColor));
1143 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1147 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1149 vos::OGuard aGuard( Application::GetSolarMutex() );
1151 const BYTE* pIn( reinterpret_cast<const BYTE*>(deviceColor.getConstArray()) );
1152 const sal_Size nLen( deviceColor.getLength() );
1153 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1155 uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1156 rendering::RGBColor* pOut( aRes.getArray() );
1158 ENSURE_OR_THROW(m_pBmpAcc,
1159 "Unable to get BitmapAccess");
1161 if( m_aBmpEx.IsTransparent() )
1163 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1164 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1166 // if palette, index is guaranteed to be 8 bit
1167 const BitmapColor aCol =
1168 m_bPalette ?
1169 m_pBmpAcc->GetPaletteColor(*pIn) :
1170 m_pBmpAcc->GetPixelFromData(pIn,0);
1172 // TODO(F3): Convert result to sRGB color space
1173 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1174 toDoubleColor(aCol.GetGreen()),
1175 toDoubleColor(aCol.GetBlue()));
1176 // skips alpha
1177 pIn += nBytesPerPixel;
1180 else
1182 for( sal_Int32 i=0; i<nNumColors; ++i )
1184 const BitmapColor aCol =
1185 m_bPalette ?
1186 m_pBmpAcc->GetPaletteColor(
1187 sal::static_int_cast<USHORT>(
1188 m_pBmpAcc->GetPixelFromData(
1189 pIn, i ))) :
1190 m_pBmpAcc->GetPixelFromData(pIn, i);
1192 // TODO(F3): Convert result to sRGB color space
1193 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1194 toDoubleColor(aCol.GetGreen()),
1195 toDoubleColor(aCol.GetBlue()));
1199 return aRes;
1202 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1204 vos::OGuard aGuard( Application::GetSolarMutex() );
1206 const BYTE* pIn( reinterpret_cast<const BYTE*>(deviceColor.getConstArray()) );
1207 const sal_Size nLen( deviceColor.getLength() );
1208 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1210 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1211 rendering::ARGBColor* pOut( aRes.getArray() );
1213 ENSURE_OR_THROW(m_pBmpAcc,
1214 "Unable to get BitmapAccess");
1216 if( m_aBmpEx.IsTransparent() )
1218 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1219 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1220 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1221 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1223 // if palette, index is guaranteed to be 8 bit
1224 const BitmapColor aCol =
1225 m_bPalette ?
1226 m_pBmpAcc->GetPaletteColor(*pIn) :
1227 m_pBmpAcc->GetPixelFromData(pIn,0);
1229 // TODO(F3): Convert result to sRGB color space
1230 *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1231 toDoubleColor(aCol.GetRed()),
1232 toDoubleColor(aCol.GetGreen()),
1233 toDoubleColor(aCol.GetBlue()));
1234 pIn += nBytesPerPixel;
1237 else
1239 for( sal_Int32 i=0; i<nNumColors; ++i )
1241 const BitmapColor aCol =
1242 m_bPalette ?
1243 m_pBmpAcc->GetPaletteColor(
1244 sal::static_int_cast<USHORT>(
1245 m_pBmpAcc->GetPixelFromData(
1246 pIn, i ))) :
1247 m_pBmpAcc->GetPixelFromData(pIn, i);
1249 // TODO(F3): Convert result to sRGB color space
1250 *pOut++ = rendering::ARGBColor(1.0,
1251 toDoubleColor(aCol.GetRed()),
1252 toDoubleColor(aCol.GetGreen()),
1253 toDoubleColor(aCol.GetBlue()));
1257 return aRes;
1260 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1262 vos::OGuard aGuard( Application::GetSolarMutex() );
1264 const BYTE* pIn( reinterpret_cast<const BYTE*>(deviceColor.getConstArray()) );
1265 const sal_Size nLen( deviceColor.getLength() );
1266 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1268 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1269 rendering::ARGBColor* pOut( aRes.getArray() );
1271 ENSURE_OR_THROW(m_pBmpAcc,
1272 "Unable to get BitmapAccess");
1274 if( m_aBmpEx.IsTransparent() )
1276 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1277 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1278 const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1279 for( sal_Size i=0; i<nLen; i+=nBytesPerPixel )
1281 // if palette, index is guaranteed to be 8 bit
1282 const BitmapColor aCol =
1283 m_bPalette ?
1284 m_pBmpAcc->GetPaletteColor(*pIn) :
1285 m_pBmpAcc->GetPixelFromData(pIn,0);
1287 // TODO(F3): Convert result to sRGB color space
1288 const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1289 *pOut++ = rendering::ARGBColor(nAlpha,
1290 nAlpha*toDoubleColor(aCol.GetRed()),
1291 nAlpha*toDoubleColor(aCol.GetGreen()),
1292 nAlpha*toDoubleColor(aCol.GetBlue()));
1293 pIn += nBytesPerPixel;
1296 else
1298 for( sal_Int32 i=0; i<nNumColors; ++i )
1300 const BitmapColor aCol =
1301 m_bPalette ?
1302 m_pBmpAcc->GetPaletteColor(
1303 sal::static_int_cast<USHORT>(
1304 m_pBmpAcc->GetPixelFromData(
1305 pIn, i ))) :
1306 m_pBmpAcc->GetPixelFromData(pIn, i);
1308 // TODO(F3): Convert result to sRGB color space
1309 *pOut++ = rendering::ARGBColor(1.0,
1310 toDoubleColor(aCol.GetRed()),
1311 toDoubleColor(aCol.GetGreen()),
1312 toDoubleColor(aCol.GetBlue()));
1316 return aRes;
1319 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1321 vos::OGuard aGuard( Application::GetSolarMutex() );
1323 const sal_Size nLen( rgbColor.getLength() );
1324 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1326 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1327 BYTE* pColors=reinterpret_cast<BYTE*>(aRes.getArray());
1329 if( m_aBmpEx.IsTransparent() )
1331 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1332 for( sal_Size i=0; i<nLen; ++i )
1334 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1335 toByteColor(rgbColor[i].Green),
1336 toByteColor(rgbColor[i].Blue));
1337 const BitmapColor aCol2 =
1338 m_bPalette ?
1339 BitmapColor(
1340 sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1341 aCol;
1343 m_pBmpAcc->SetPixelOnData(pColors,0,aCol2);
1344 pColors += nNonAlphaBytes;
1345 *pColors++ = BYTE(255);
1348 else
1350 for( sal_Size i=0; i<nLen; ++i )
1352 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1353 toByteColor(rgbColor[i].Green),
1354 toByteColor(rgbColor[i].Blue));
1355 const BitmapColor aCol2 =
1356 m_bPalette ?
1357 BitmapColor(
1358 sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1359 aCol;
1361 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1365 return aRes;
1368 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1370 vos::OGuard aGuard( Application::GetSolarMutex() );
1372 const sal_Size nLen( rgbColor.getLength() );
1373 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1375 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1376 BYTE* pColors=reinterpret_cast<BYTE*>(aRes.getArray());
1378 if( m_aBmpEx.IsTransparent() )
1380 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1381 for( sal_Size i=0; i<nLen; ++i )
1383 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1384 toByteColor(rgbColor[i].Green),
1385 toByteColor(rgbColor[i].Blue));
1386 const BitmapColor aCol2 =
1387 m_bPalette ?
1388 BitmapColor(
1389 sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1390 aCol;
1392 m_pBmpAcc->SetPixelOnData(pColors,0,aCol2);
1393 pColors += nNonAlphaBytes;
1394 *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1397 else
1399 for( sal_Size i=0; i<nLen; ++i )
1401 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1402 toByteColor(rgbColor[i].Green),
1403 toByteColor(rgbColor[i].Blue));
1404 const BitmapColor aCol2 =
1405 m_bPalette ?
1406 BitmapColor(
1407 sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1408 aCol;
1410 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1414 return aRes;
1417 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException)
1419 vos::OGuard aGuard( Application::GetSolarMutex() );
1421 const sal_Size nLen( rgbColor.getLength() );
1422 const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1424 uno::Sequence< sal_Int8 > aRes(nNumBytes);
1425 BYTE* pColors=reinterpret_cast<BYTE*>(aRes.getArray());
1427 if( m_aBmpEx.IsTransparent() )
1429 const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1430 for( sal_Size i=0; i<nLen; ++i )
1432 const double nAlpha( rgbColor[i].Alpha );
1433 const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1434 toByteColor(rgbColor[i].Green / nAlpha),
1435 toByteColor(rgbColor[i].Blue / nAlpha));
1436 const BitmapColor aCol2 =
1437 m_bPalette ?
1438 BitmapColor(
1439 sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1440 aCol;
1442 m_pBmpAcc->SetPixelOnData(pColors,0,aCol2);
1443 pColors += nNonAlphaBytes;
1444 *pColors++ = 255 - toByteColor(nAlpha);
1447 else
1449 for( sal_Size i=0; i<nLen; ++i )
1451 const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1452 toByteColor(rgbColor[i].Green),
1453 toByteColor(rgbColor[i].Blue));
1454 const BitmapColor aCol2 =
1455 m_bPalette ?
1456 BitmapColor(
1457 sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1458 aCol;
1460 m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1464 return aRes;
1467 BitmapEx VclCanvasBitmap::getBitmapEx() const
1469 return m_aBmpEx;