LibreOffice Module vcl (master)  1
canvasbitmap.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23 #include <com/sun/star/util/Endianness.hpp>
24 #include <com/sun/star/rendering/ColorComponentTag.hpp>
25 #include <com/sun/star/rendering/ColorSpaceType.hpp>
26 #include <com/sun/star/rendering/RenderingIntent.hpp>
27 
28 #include <rtl/instance.hxx>
29 
30 #include <tools/diagnose_ex.h>
31 #include <canvasbitmap.hxx>
32 #include <vcl/canvastools.hxx>
33 #include <vcl/bitmapaccess.hxx>
34 #include <vcl/svapp.hxx>
35 
36 #include <algorithm>
37 
38 using namespace vcl::unotools;
39 using namespace ::com::sun::star;
40 
41 namespace
42 {
43  // TODO(Q3): move to o3tl bithacks or somesuch. A similar method is in canvas/canvastools.hxx
44 
45  // Good ole HAKMEM tradition. Calc number of 1 bits in 32bit word,
46  // unrolled loop. See e.g. Hackers Delight, p. 66
47  sal_Int32 bitcount( sal_uInt32 val )
48  {
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);
55  }
56 }
57 
58 void VclCanvasBitmap::setComponentInfo( sal_uInt32 redShift, sal_uInt32 greenShift, sal_uInt32 blueShift )
59 {
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);
65 
66  if( redShift > greenShift )
67  {
68  std::swap(redPos,greenPos);
69  if( redShift > blueShift )
70  {
71  std::swap(redPos,bluePos);
72  if( greenShift > blueShift )
73  std::swap(greenPos,bluePos);
74  }
75  }
76  else
77  {
78  if( greenShift > blueShift )
79  {
80  std::swap(greenPos,bluePos);
81  if( redShift > blueShift )
82  std::swap(redPos,bluePos);
83  }
84  }
85 
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;
91 
92  m_aComponentBitCounts.realloc(3);
93  sal_Int32* pCounts = m_aComponentBitCounts.getArray();
94  pCounts[redPos] = bitcount(redShift);
95  pCounts[greenPos] = bitcount(greenShift);
96  pCounts[bluePos] = bitcount(blueShift);
97 }
98 
100  m_aBmpEx( rBitmap ),
101  m_aBitmap( rBitmap.GetBitmap() ),
102  m_aAlpha(),
103  m_pBmpAcc( m_aBitmap ),
105  m_aComponentBitCounts(),
106  m_aLayout(),
107  m_nBitsPerInputPixel(0),
108  m_nBitsPerOutputPixel(0),
109  m_nRedIndex(-1),
110  m_nGreenIndex(-1),
111  m_nBlueIndex(-1),
112  m_nAlphaIndex(-1),
113  m_nIndexIndex(-1),
114  m_nEndianness(0),
115  m_bPalette(false)
116 {
117  if( m_aBmpEx.IsTransparent() )
118  {
121  }
122 
123  m_aLayout.ScanLines = 0;
124  m_aLayout.ScanLineBytes = 0;
125  m_aLayout.ScanLineStride = 0;
126  m_aLayout.PlaneStride = 0;
127  m_aLayout.ColorSpace.clear();
128  m_aLayout.Palette.clear();
129  m_aLayout.IsMsbFirst = false;
130 
131  if( m_pBmpAcc )
132  {
133  m_aLayout.ScanLines = m_pBmpAcc->Height();
134  m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
135  m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
136  m_aLayout.PlaneStride = 0;
137 
138  switch( m_pBmpAcc->GetScanlineFormat() )
139  {
141  m_bPalette = true;
143  m_nEndianness = util::Endianness::LITTLE; // doesn't matter
144  m_aLayout.IsMsbFirst = true;
145  break;
146 
148  m_bPalette = true;
150  m_nEndianness = util::Endianness::LITTLE; // doesn't matter
151  m_aLayout.IsMsbFirst = false;
152  break;
153 
155  m_bPalette = true;
157  m_nEndianness = util::Endianness::LITTLE; // doesn't matter
158  m_aLayout.IsMsbFirst = true;
159  break;
160 
162  m_bPalette = true;
164  m_nEndianness = util::Endianness::LITTLE; // doesn't matter
165  m_aLayout.IsMsbFirst = false;
166  break;
167 
169  m_bPalette = true;
171  m_nEndianness = util::Endianness::LITTLE; // doesn't matter
172  m_aLayout.IsMsbFirst = false; // doesn't matter
173  break;
174 
176  m_bPalette = false;
178  m_nEndianness = util::Endianness::LITTLE; // doesn't matter
179  m_aLayout.IsMsbFirst = false; // doesn't matter
183  break;
184 
186  m_bPalette = false;
188  m_nEndianness = util::Endianness::BIG;
189  m_aLayout.IsMsbFirst = false; // doesn't matter
193  break;
194 
196  m_bPalette = false;
198  m_nEndianness = util::Endianness::LITTLE;
199  m_aLayout.IsMsbFirst = false; // doesn't matter
203  break;
204 
206  m_bPalette = false;
208  m_nEndianness = util::Endianness::LITTLE;
209  m_aLayout.IsMsbFirst = false; // doesn't matter
210  setComponentInfo( static_cast<sal_uInt32>(0xff0000UL),
211  static_cast<sal_uInt32>(0x00ff00UL),
212  static_cast<sal_uInt32>(0x0000ffUL) );
213  break;
214 
216  m_bPalette = false;
218  m_nEndianness = util::Endianness::LITTLE;
219  m_aLayout.IsMsbFirst = false; // doesn't matter
220  setComponentInfo( static_cast<sal_uInt32>(0x0000ffUL),
221  static_cast<sal_uInt32>(0x00ff00UL),
222  static_cast<sal_uInt32>(0xff0000UL) );
223  break;
224 
226  {
227  m_bPalette = false;
229  m_nEndianness = util::Endianness::LITTLE;
230  m_aLayout.IsMsbFirst = false; // doesn't matter
231 
232  m_aComponentTags.realloc(4);
233  sal_Int8* pTags = m_aComponentTags.getArray();
234  pTags[0] = rendering::ColorComponentTag::ALPHA;
235  pTags[1] = rendering::ColorComponentTag::RGB_BLUE;
236  pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
237  pTags[3] = rendering::ColorComponentTag::RGB_RED;
238 
239  m_aComponentBitCounts.realloc(4);
240  sal_Int32* pCounts = m_aComponentBitCounts.getArray();
241  pCounts[0] = 8;
242  pCounts[1] = 8;
243  pCounts[2] = 8;
244  pCounts[3] = 8;
245 
246  m_nRedIndex = 3;
247  m_nGreenIndex = 2;
248  m_nBlueIndex = 1;
249  m_nAlphaIndex = 0;
250  }
251  break;
252 
254  {
255  m_bPalette = false;
257  m_nEndianness = util::Endianness::LITTLE;
258  m_aLayout.IsMsbFirst = false; // doesn't matter
259 
260  m_aComponentTags.realloc(4);
261  sal_Int8* pTags = m_aComponentTags.getArray();
262  pTags[0] = rendering::ColorComponentTag::ALPHA;
263  pTags[1] = rendering::ColorComponentTag::RGB_RED;
264  pTags[2] = rendering::ColorComponentTag::RGB_GREEN;
265  pTags[3] = rendering::ColorComponentTag::RGB_BLUE;
266 
267  m_aComponentBitCounts.realloc(4);
268  sal_Int32* pCounts = m_aComponentBitCounts.getArray();
269  pCounts[0] = 8;
270  pCounts[1] = 8;
271  pCounts[2] = 8;
272  pCounts[3] = 8;
273 
274  m_nRedIndex = 1;
275  m_nGreenIndex = 2;
276  m_nBlueIndex = 3;
277  m_nAlphaIndex = 0;
278  }
279  break;
280 
282  {
283  m_bPalette = false;
285  m_nEndianness = util::Endianness::LITTLE;
286  m_aLayout.IsMsbFirst = false; // doesn't matter
287 
288  m_aComponentTags.realloc(4);
289  sal_Int8* pTags = m_aComponentTags.getArray();
290  pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
291  pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
292  pTags[2] = rendering::ColorComponentTag::RGB_RED;
293  pTags[3] = rendering::ColorComponentTag::ALPHA;
294 
295  m_aComponentBitCounts.realloc(4);
296  sal_Int32* pCounts = m_aComponentBitCounts.getArray();
297  pCounts[0] = 8;
298  pCounts[1] = 8;
299  pCounts[2] = 8;
300  pCounts[3] = 8;
301 
302  m_nRedIndex = 2;
303  m_nGreenIndex = 1;
304  m_nBlueIndex = 0;
305  m_nAlphaIndex = 3;
306  }
307  break;
308 
310  {
311  m_bPalette = false;
313  m_nEndianness = util::Endianness::LITTLE;
314  m_aLayout.IsMsbFirst = false; // doesn't matter
315 
316  m_aComponentTags.realloc(4);
317  sal_Int8* pTags = m_aComponentTags.getArray();
318  pTags[0] = rendering::ColorComponentTag::RGB_RED;
319  pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
320  pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
321  pTags[3] = rendering::ColorComponentTag::ALPHA;
322 
323  m_aComponentBitCounts.realloc(4);
324  sal_Int32* pCounts = m_aComponentBitCounts.getArray();
325  pCounts[0] = 8;
326  pCounts[1] = 8;
327  pCounts[2] = 8;
328  pCounts[3] = 8;
329 
330  m_nRedIndex = 0;
331  m_nGreenIndex = 1;
332  m_nBlueIndex = 2;
333  m_nAlphaIndex = 3;
334  }
335  break;
336 
338  m_bPalette = false;
340  m_nEndianness = util::Endianness::LITTLE;
341  m_aLayout.IsMsbFirst = false; // doesn't matter
345  break;
346 
347  default:
348  OSL_FAIL( "unsupported bitmap format" );
349  break;
350  }
351 
352  if( m_bPalette )
353  {
354  m_aComponentTags.realloc(1);
355  m_aComponentTags[0] = rendering::ColorComponentTag::INDEX;
356 
357  m_aComponentBitCounts.realloc(1);
359 
360  m_nIndexIndex = 0;
361  }
362 
364  if( m_aBmpEx.IsTransparent() )
365  {
366  // TODO(P1): need to interleave alpha with bitmap data -
367  // won't fuss with less-than-8 bit for now
368  m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
369 
370  // check whether alpha goes in front or behind the
371  // bitcount sequence. If pixel format is little endian,
372  // put it behind all the other channels. If it's big
373  // endian, put it in front (because later, the actual data
374  // always gets written after the pixel data)
375 
376  // TODO(Q1): slight catch - in the case of the
377  // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
378  // channels might happen!
379  m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
380  m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
381 
382  m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
383  m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
384 
385  if( m_nEndianness == util::Endianness::BIG )
386  {
387  // put alpha in front of all the color channels
388  sal_Int8* pTags =m_aComponentTags.getArray();
389  sal_Int32* pCounts=m_aComponentBitCounts.getArray();
390  std::rotate(pTags,
391  pTags+m_aComponentTags.getLength()-1,
392  pTags+m_aComponentTags.getLength());
393  std::rotate(pCounts,
394  pCounts+m_aComponentBitCounts.getLength()-1,
395  pCounts+m_aComponentBitCounts.getLength());
396  ++m_nRedIndex;
397  ++m_nGreenIndex;
398  ++m_nBlueIndex;
399  ++m_nIndexIndex;
400  m_nAlphaIndex=0;
401  }
402 
403  // always add a full byte to the pixel size, otherwise
404  // pixel packing hell breaks loose.
406 
407  // adapt scanline parameters
408  const Size aSize = m_aBitmap.GetSizePixel();
409  m_aLayout.ScanLineBytes =
410  m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
411  }
412  }
413 }
414 
416 {
417 }
418 
419 // XBitmap
420 geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize()
421 {
422  SolarMutexGuard aGuard;
424 }
425 
427 {
428  SolarMutexGuard aGuard;
429  return m_aBmpEx.IsTransparent();
430 }
431 
432 uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
433  sal_Bool beFast )
434 {
435  SolarMutexGuard aGuard;
436 
437  BitmapEx aNewBmp( m_aBitmap );
439  return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
440 }
441 
442 // XIntegerReadOnlyBitmap
443 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
444  const geometry::IntegerRectangle2D& rect )
445 {
446  SolarMutexGuard aGuard;
447 
448  bitmapLayout = getMemoryLayout();
449 
450  const ::tools::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
451  if( aRequestedArea.IsEmpty() )
452  return uno::Sequence< sal_Int8 >();
453 
454  // Invalid/empty bitmap: no data available
455  if( !m_pBmpAcc )
456  throw lang::IndexOutOfBoundsException();
458  throw lang::IndexOutOfBoundsException();
459 
460  if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
461  aRequestedArea.Right() > m_pBmpAcc->Width() ||
462  aRequestedArea.Bottom() > m_pBmpAcc->Height() )
463  {
464  throw lang::IndexOutOfBoundsException();
465  }
466 
467  uno::Sequence< sal_Int8 > aRet;
468  tools::Rectangle aRequestedBytes( aRequestedArea );
469 
470  // adapt to byte boundaries
471  aRequestedBytes.SetLeft( aRequestedArea.Left()*m_nBitsPerOutputPixel/8 );
472  aRequestedBytes.SetRight( (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8 );
473 
474  // copy stuff to output sequence
475  aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight());
476  sal_Int8* pOutBuf = aRet.getArray();
477 
478  bitmapLayout.ScanLines = aRequestedBytes.getHeight();
479  bitmapLayout.ScanLineBytes =
480  bitmapLayout.ScanLineStride= aRequestedBytes.getWidth();
481 
482  sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
484  {
485  pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1);
486  nScanlineStride *= -1;
487  }
488 
489  if( !m_aBmpEx.IsTransparent() )
490  {
491  OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
492 
493  // can return bitmap data as-is
494  for( long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
495  {
496  Scanline pScan = m_pBmpAcc->GetScanline(y);
497  memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
498  pOutBuf += nScanlineStride;
499  }
500  }
501  else
502  {
503  OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access");
504  OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access");
505 
506  // interleave alpha with bitmap data - note, bitcount is
507  // always integer multiple of 8
508  OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
509  "Transparent bitmap bitcount not integer multiple of 8" );
510 
511  for( long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
512  {
513  sal_Int8* pOutScan = pOutBuf;
514 
515  if( m_nBitsPerInputPixel < 8 )
516  {
517  // input less than a byte - copy via GetPixel()
518  for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
519  {
520  *pOutScan++ = m_pBmpAcc->GetPixelIndex(y,x);
521  *pOutScan++ = m_pAlphaAcc->GetPixelIndex(y,x);
522  }
523  }
524  else
525  {
526  const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
527  const long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
528  Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
529  Scanline pScanlineAlpha = m_pAlphaAcc->GetScanline( y );
530 
531  // input integer multiple of byte - copy directly
532  for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
533  {
534  for( long i=0; i<nNonAlphaBytes; ++i )
535  *pOutScan++ = *pScan++;
536  *pOutScan++ = m_pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
537  }
538  }
539 
540  pOutBuf += nScanlineStride;
541  }
542  }
543 
544  return aRet;
545 }
546 
547 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
548  const geometry::IntegerPoint2D& pos )
549 {
550  SolarMutexGuard aGuard;
551 
552  bitmapLayout = getMemoryLayout();
553 
554  // Invalid/empty bitmap: no data available
555  if( !m_pBmpAcc )
556  throw lang::IndexOutOfBoundsException();
558  throw lang::IndexOutOfBoundsException();
559 
560  if( pos.X < 0 || pos.Y < 0 ||
561  pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
562  {
563  throw lang::IndexOutOfBoundsException();
564  }
565 
566  uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
567  sal_Int8* pOutBuf = aRet.getArray();
568 
569  // copy stuff to output sequence
570  bitmapLayout.ScanLines = 1;
571  bitmapLayout.ScanLineBytes =
572  bitmapLayout.ScanLineStride= aRet.getLength();
573 
574  const long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
575  if( !m_aBmpEx.IsTransparent() )
576  {
577  assert(m_pBmpAcc && "Invalid bmp read access");
578 
579  // can return bitmap data as-is
580  Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
581  memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
582  }
583  else
584  {
585  assert(m_pBmpAcc && "Invalid bmp read access");
586  assert(m_pAlphaAcc && "Invalid alpha read access");
587 
588  // interleave alpha with bitmap data - note, bitcount is
589  // always integer multiple of 8
590  assert((m_nBitsPerOutputPixel & 0x07) == 0 &&
591  "Transparent bitmap bitcount not integer multiple of 8" );
592 
593  if( m_nBitsPerInputPixel < 8 )
594  {
595  // input less than a byte - copy via GetPixel()
596  *pOutBuf++ = m_pBmpAcc->GetPixelIndex(pos.Y,pos.X);
597  *pOutBuf = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
598  }
599  else
600  {
601  const long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
602  Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
603 
604  // input integer multiple of byte - copy directly
605  memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
606  pOutBuf += nNonAlphaBytes;
607  *pOutBuf++ = m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
608  }
609  }
610 
611  return aRet;
612 }
613 
614 uno::Reference< rendering::XBitmapPalette > VclCanvasBitmap::getPalette()
615 {
616  SolarMutexGuard aGuard;
617 
618  uno::Reference< XBitmapPalette > aRet;
619  if( m_bPalette )
620  aRet.set(this);
621 
622  return aRet;
623 }
624 
625 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout()
626 {
627  SolarMutexGuard aGuard;
628 
629  rendering::IntegerBitmapLayout aLayout( m_aLayout );
630 
631  // only set references to self on separate copy of
632  // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
633  // a circular reference!
634  if( m_bPalette )
635  aLayout.Palette.set( this );
636 
637  aLayout.ColorSpace.set( this );
638 
639  return aLayout;
640 }
641 
643 {
644  SolarMutexGuard aGuard;
645 
646  if( !m_pBmpAcc )
647  return 0;
648 
650 }
651 
652 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex )
653 {
654  SolarMutexGuard aGuard;
655 
656  const sal_uInt16 nCount( m_pBmpAcc ?
657  (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
658  OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
659  if( nIndex < 0 || nIndex >= nCount )
660  throw lang::IndexOutOfBoundsException("Palette index out of range",
661  static_cast<rendering::XBitmapPalette*>(this));
662 
663  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
664  o_entry.realloc(3);
665  double* pColor=o_entry.getArray();
666  pColor[0] = aCol.GetRed();
667  pColor[1] = aCol.GetGreen();
668  pColor[2] = aCol.GetBlue();
669 
670  return true; // no palette transparency here.
671 }
672 
673 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex )
674 {
675  SolarMutexGuard aGuard;
676 
677  const sal_uInt16 nCount( m_pBmpAcc ?
678  (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
679 
680  OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
681  if( nIndex < 0 || nIndex >= nCount )
682  throw lang::IndexOutOfBoundsException("Palette index out of range",
683  static_cast<rendering::XBitmapPalette*>(this));
684 
685  return false; // read-only implementation
686 }
687 
688 namespace
689 {
690  struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
691  PaletteColorSpaceHolder>
692  {
693  uno::Reference<rendering::XColorSpace> operator()()
694  {
696  }
697  };
698 }
699 
700 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( )
701 {
702  // this is the method from XBitmapPalette. Return palette color
703  // space here
704  return PaletteColorSpaceHolder::get();
705 }
706 
708 {
709  return rendering::ColorSpaceType::RGB;
710 }
711 
712 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( )
713 {
714  SolarMutexGuard aGuard;
715  return m_aComponentTags;
716 }
717 
719 {
720  return rendering::RenderingIntent::PERCEPTUAL;
721 }
722 
723 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( )
724 {
725  return uno::Sequence< ::beans::PropertyValue >();
726 }
727 
728 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
729  const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
730 {
731  // TODO(P3): if we know anything about target
732  // colorspace, this can be greatly sped up
733  uno::Sequence<rendering::ARGBColor> aIntermediate(
734  convertToARGB(deviceColor));
735  return targetColorSpace->convertFromARGB(aIntermediate);
736 }
737 
738 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor )
739 {
740  SolarMutexGuard aGuard;
741 
742  const std::size_t nLen( deviceColor.getLength() );
743  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
744  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
745  "number of channels no multiple of pixel element count",
746  static_cast<rendering::XBitmapPalette*>(this), 01);
747 
748  uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
749  rendering::RGBColor* pOut( aRes.getArray() );
750 
751  if( m_bPalette )
752  {
753  OSL_ENSURE(m_nIndexIndex != -1,
754  "Invalid color channel indices");
756  "Unable to get BitmapAccess");
757 
758  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
759  {
760  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
761  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
762 
763  // TODO(F3): Convert result to sRGB color space
764  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
765  toDoubleColor(aCol.GetGreen()),
766  toDoubleColor(aCol.GetBlue()));
767  }
768  }
769  else
770  {
771  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
772  "Invalid color channel indices");
773 
774  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
775  {
776  // TODO(F3): Convert result to sRGB color space
777  *pOut++ = rendering::RGBColor(
778  deviceColor[i+m_nRedIndex],
779  deviceColor[i+m_nGreenIndex],
780  deviceColor[i+m_nBlueIndex]);
781  }
782  }
783 
784  return aRes;
785 }
786 
787 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor )
788 {
789  SolarMutexGuard aGuard;
790 
791  const std::size_t nLen( deviceColor.getLength() );
792  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
793  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
794  "number of channels no multiple of pixel element count",
795  static_cast<rendering::XBitmapPalette*>(this), 01);
796 
797  uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
798  rendering::ARGBColor* pOut( aRes.getArray() );
799 
800  if( m_bPalette )
801  {
802  OSL_ENSURE(m_nIndexIndex != -1,
803  "Invalid color channel indices");
805  "Unable to get BitmapAccess");
806 
807  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
808  {
809  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
810  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
811 
812  // TODO(F3): Convert result to sRGB color space
813  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
814  *pOut++ = rendering::ARGBColor(nAlpha,
815  toDoubleColor(aCol.GetRed()),
816  toDoubleColor(aCol.GetGreen()),
817  toDoubleColor(aCol.GetBlue()));
818  }
819  }
820  else
821  {
822  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
823  "Invalid color channel indices");
824 
825  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
826  {
827  // TODO(F3): Convert result to sRGB color space
828  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
829  *pOut++ = rendering::ARGBColor(
830  nAlpha,
831  deviceColor[i+m_nRedIndex],
832  deviceColor[i+m_nGreenIndex],
833  deviceColor[i+m_nBlueIndex]);
834  }
835  }
836 
837  return aRes;
838 }
839 
840 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor )
841 {
842  SolarMutexGuard aGuard;
843 
844  const std::size_t nLen( deviceColor.getLength() );
845  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
846  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
847  "number of channels no multiple of pixel element count",
848  static_cast<rendering::XBitmapPalette*>(this), 01);
849 
850  uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
851  rendering::ARGBColor* pOut( aRes.getArray() );
852 
853  if( m_bPalette )
854  {
855  OSL_ENSURE(m_nIndexIndex != -1,
856  "Invalid color channel indices");
858  "Unable to get BitmapAccess");
859 
860  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
861  {
862  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
863  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
864 
865  // TODO(F3): Convert result to sRGB color space
866  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
867  *pOut++ = rendering::ARGBColor(nAlpha,
868  nAlpha*toDoubleColor(aCol.GetRed()),
869  nAlpha*toDoubleColor(aCol.GetGreen()),
870  nAlpha*toDoubleColor(aCol.GetBlue()));
871  }
872  }
873  else
874  {
875  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
876  "Invalid color channel indices");
877 
878  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
879  {
880  // TODO(F3): Convert result to sRGB color space
881  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
882  *pOut++ = rendering::ARGBColor(
883  nAlpha,
884  nAlpha*deviceColor[i+m_nRedIndex],
885  nAlpha*deviceColor[i+m_nGreenIndex],
886  nAlpha*deviceColor[i+m_nBlueIndex]);
887  }
888  }
889 
890  return aRes;
891 }
892 
893 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
894 {
895  SolarMutexGuard aGuard;
896 
897  const std::size_t nLen( rgbColor.getLength() );
898  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
899 
900  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
901  double* pColors=aRes.getArray();
902 
903  if( m_bPalette )
904  {
905  for( const auto& rIn : rgbColor )
906  {
908  BitmapColor(toByteColor(rIn.Red),
909  toByteColor(rIn.Green),
910  toByteColor(rIn.Blue)));
911  if( m_nAlphaIndex != -1 )
912  pColors[m_nAlphaIndex] = 1.0;
913 
914  pColors += nComponentsPerPixel;
915  }
916  }
917  else
918  {
919  for( const auto& rIn : rgbColor )
920  {
921  pColors[m_nRedIndex] = rIn.Red;
922  pColors[m_nGreenIndex] = rIn.Green;
923  pColors[m_nBlueIndex] = rIn.Blue;
924  if( m_nAlphaIndex != -1 )
925  pColors[m_nAlphaIndex] = 1.0;
926 
927  pColors += nComponentsPerPixel;
928  }
929  }
930  return aRes;
931 }
932 
933 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
934 {
935  SolarMutexGuard aGuard;
936 
937  const std::size_t nLen( rgbColor.getLength() );
938  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
939 
940  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
941  double* pColors=aRes.getArray();
942 
943  if( m_bPalette )
944  {
945  for( const auto& rIn : rgbColor )
946  {
948  BitmapColor(toByteColor(rIn.Red),
949  toByteColor(rIn.Green),
950  toByteColor(rIn.Blue)));
951  if( m_nAlphaIndex != -1 )
952  pColors[m_nAlphaIndex] = rIn.Alpha;
953 
954  pColors += nComponentsPerPixel;
955  }
956  }
957  else
958  {
959  for( const auto& rIn : rgbColor )
960  {
961  pColors[m_nRedIndex] = rIn.Red;
962  pColors[m_nGreenIndex] = rIn.Green;
963  pColors[m_nBlueIndex] = rIn.Blue;
964  if( m_nAlphaIndex != -1 )
965  pColors[m_nAlphaIndex] = rIn.Alpha;
966 
967  pColors += nComponentsPerPixel;
968  }
969  }
970  return aRes;
971 }
972 
973 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
974 {
975  SolarMutexGuard aGuard;
976 
977  const std::size_t nLen( rgbColor.getLength() );
978  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
979 
980  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
981  double* pColors=aRes.getArray();
982 
983  if( m_bPalette )
984  {
985  for( const auto& rIn : rgbColor )
986  {
987  const double nAlpha( rIn.Alpha );
989  BitmapColor(toByteColor(rIn.Red / nAlpha),
990  toByteColor(rIn.Green / nAlpha),
991  toByteColor(rIn.Blue / nAlpha)));
992  if( m_nAlphaIndex != -1 )
993  pColors[m_nAlphaIndex] = nAlpha;
994 
995  pColors += nComponentsPerPixel;
996  }
997  }
998  else
999  {
1000  for( const auto& rIn : rgbColor )
1001  {
1002  const double nAlpha( rIn.Alpha );
1003  pColors[m_nRedIndex] = rIn.Red / nAlpha;
1004  pColors[m_nGreenIndex] = rIn.Green / nAlpha;
1005  pColors[m_nBlueIndex] = rIn.Blue / nAlpha;
1006  if( m_nAlphaIndex != -1 )
1007  pColors[m_nAlphaIndex] = nAlpha;
1008 
1009  pColors += nComponentsPerPixel;
1010  }
1011  }
1012  return aRes;
1013 }
1014 
1016 {
1017  SolarMutexGuard aGuard;
1018  return m_nBitsPerOutputPixel;
1019 }
1020 
1021 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( )
1022 {
1023  SolarMutexGuard aGuard;
1024  return m_aComponentBitCounts;
1025 }
1026 
1028 {
1029  SolarMutexGuard aGuard;
1030  return m_nEndianness;
1031 }
1032 
1033 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1034  const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
1035 {
1036  if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1037  {
1038  SolarMutexGuard aGuard;
1039 
1040  const std::size_t nLen( deviceColor.getLength() );
1041  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1042  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1043  "number of channels no multiple of pixel element count",
1044  static_cast<rendering::XBitmapPalette*>(this), 01);
1045 
1046  uno::Sequence<double> aRes(nLen);
1047  double* pOut( aRes.getArray() );
1048 
1049  if( m_bPalette )
1050  {
1051  OSL_ENSURE(m_nIndexIndex != -1,
1052  "Invalid color channel indices");
1054  "Unable to get BitmapAccess");
1055 
1056  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1057  {
1058  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1059  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
1060 
1061  // TODO(F3): Convert result to sRGB color space
1062  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1063  *pOut++ = toDoubleColor(aCol.GetRed());
1064  *pOut++ = toDoubleColor(aCol.GetGreen());
1065  *pOut++ = toDoubleColor(aCol.GetBlue());
1066  *pOut++ = nAlpha;
1067  }
1068  }
1069  else
1070  {
1071  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1072  "Invalid color channel indices");
1073 
1074  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1075  {
1076  // TODO(F3): Convert result to sRGB color space
1077  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1078  *pOut++ = deviceColor[i+m_nRedIndex];
1079  *pOut++ = deviceColor[i+m_nGreenIndex];
1080  *pOut++ = deviceColor[i+m_nBlueIndex];
1081  *pOut++ = nAlpha;
1082  }
1083  }
1084 
1085  return aRes;
1086  }
1087  else
1088  {
1089  // TODO(P3): if we know anything about target
1090  // colorspace, this can be greatly sped up
1091  uno::Sequence<rendering::ARGBColor> aIntermediate(
1092  convertIntegerToARGB(deviceColor));
1093  return targetColorSpace->convertFromARGB(aIntermediate);
1094  }
1095 }
1096 
1097 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1098  const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace )
1099 {
1100  if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1101  {
1102  // it's us, so simply pass-through the data
1103  return deviceColor;
1104  }
1105  else
1106  {
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->convertIntegerFromARGB(aIntermediate);
1112  }
1113 }
1114 
1115 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1116 {
1117  SolarMutexGuard aGuard;
1118 
1119  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1120  const std::size_t nLen( deviceColor.getLength() );
1121  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1122 
1123  uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1124  rendering::RGBColor* pOut( aRes.getArray() );
1125 
1127  "Unable to get BitmapAccess");
1128 
1129  if( m_aBmpEx.IsTransparent() )
1130  {
1131  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1132  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1133  {
1134  // if palette, index is guaranteed to be 8 bit
1135  const BitmapColor aCol =
1136  m_bPalette ?
1137  m_pBmpAcc->GetPaletteColor(*pIn) :
1138  m_pBmpAcc->GetPixelFromData(pIn,0);
1139 
1140  // TODO(F3): Convert result to sRGB color space
1141  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1142  toDoubleColor(aCol.GetGreen()),
1143  toDoubleColor(aCol.GetBlue()));
1144  // skips alpha
1145  pIn += nBytesPerPixel;
1146  }
1147  }
1148  else
1149  {
1150  for( sal_Int32 i=0; i<nNumColors; ++i )
1151  {
1152  const BitmapColor aCol =
1153  m_bPalette ?
1155  m_pBmpAcc->GetPixelFromData(pIn, i);
1156 
1157  // TODO(F3): Convert result to sRGB color space
1158  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1159  toDoubleColor(aCol.GetGreen()),
1160  toDoubleColor(aCol.GetBlue()));
1161  }
1162  }
1163 
1164  return aRes;
1165 }
1166 
1167 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1168 {
1169  SolarMutexGuard aGuard;
1170 
1171  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1172  const std::size_t nLen( deviceColor.getLength() );
1173  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1174 
1175  uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1176  rendering::ARGBColor* pOut( aRes.getArray() );
1177 
1179  "Unable to get BitmapAccess");
1180 
1181  if( m_aBmpEx.IsTransparent() )
1182  {
1183  const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1184  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1185  const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1186  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1187  {
1188  // if palette, index is guaranteed to be 8 bit
1189  const BitmapColor aCol =
1190  m_bPalette ?
1191  m_pBmpAcc->GetPaletteColor(*pIn) :
1192  m_pBmpAcc->GetPixelFromData(pIn,0);
1193 
1194  // TODO(F3): Convert result to sRGB color space
1195  *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1196  toDoubleColor(aCol.GetRed()),
1197  toDoubleColor(aCol.GetGreen()),
1198  toDoubleColor(aCol.GetBlue()));
1199  pIn += nBytesPerPixel;
1200  }
1201  }
1202  else
1203  {
1204  for( sal_Int32 i=0; i<nNumColors; ++i )
1205  {
1206  const BitmapColor aCol =
1207  m_bPalette ?
1209  m_pBmpAcc->GetPixelFromData(pIn, i);
1210 
1211  // TODO(F3): Convert result to sRGB color space
1212  *pOut++ = rendering::ARGBColor(1.0,
1213  toDoubleColor(aCol.GetRed()),
1214  toDoubleColor(aCol.GetGreen()),
1215  toDoubleColor(aCol.GetBlue()));
1216  }
1217  }
1218 
1219  return aRes;
1220 }
1221 
1222 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1223 {
1224  SolarMutexGuard aGuard;
1225 
1226  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1227  const std::size_t nLen( deviceColor.getLength() );
1228  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1229 
1230  uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1231  rendering::ARGBColor* pOut( aRes.getArray() );
1232 
1234  "Unable to get BitmapAccess");
1235 
1236  if( m_aBmpEx.IsTransparent() )
1237  {
1238  const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1239  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1240  const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1241  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1242  {
1243  // if palette, index is guaranteed to be 8 bit
1244  const BitmapColor aCol =
1245  m_bPalette ?
1246  m_pBmpAcc->GetPaletteColor(*pIn) :
1247  m_pBmpAcc->GetPixelFromData(pIn,0);
1248 
1249  // TODO(F3): Convert result to sRGB color space
1250  const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1251  *pOut++ = rendering::ARGBColor(nAlpha,
1252  nAlpha*toDoubleColor(aCol.GetRed()),
1253  nAlpha*toDoubleColor(aCol.GetGreen()),
1254  nAlpha*toDoubleColor(aCol.GetBlue()));
1255  pIn += nBytesPerPixel;
1256  }
1257  }
1258  else
1259  {
1260  for( sal_Int32 i=0; i<nNumColors; ++i )
1261  {
1262  const BitmapColor aCol =
1263  m_bPalette ?
1265  m_pBmpAcc->GetPixelFromData(pIn, i);
1266 
1267  // TODO(F3): Convert result to sRGB color space
1268  *pOut++ = rendering::ARGBColor(1.0,
1269  toDoubleColor(aCol.GetRed()),
1270  toDoubleColor(aCol.GetGreen()),
1271  toDoubleColor(aCol.GetBlue()));
1272  }
1273  }
1274 
1275  return aRes;
1276 }
1277 
1278 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
1279 {
1280  SolarMutexGuard aGuard;
1281 
1282  const std::size_t nLen( rgbColor.getLength() );
1283  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1284 
1285  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1286  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1287 
1288  if( m_aBmpEx.IsTransparent() )
1289  {
1290  const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1291  for( std::size_t i=0; i<nLen; ++i )
1292  {
1293  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1294  toByteColor(rgbColor[i].Green),
1295  toByteColor(rgbColor[i].Blue));
1296  const BitmapColor aCol2 =
1297  m_bPalette ?
1298  BitmapColor(
1299  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1300  aCol;
1301 
1302  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1303  pColors += nNonAlphaBytes;
1304  *pColors++ = sal_uInt8(255);
1305  }
1306  }
1307  else
1308  {
1309  for( std::size_t i=0; i<nLen; ++i )
1310  {
1311  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1312  toByteColor(rgbColor[i].Green),
1313  toByteColor(rgbColor[i].Blue));
1314  const BitmapColor aCol2 =
1315  m_bPalette ?
1316  BitmapColor(
1317  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1318  aCol;
1319 
1320  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1321  }
1322  }
1323 
1324  return aRes;
1325 }
1326 
1327 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1328 {
1329  SolarMutexGuard aGuard;
1330 
1331  const std::size_t nLen( rgbColor.getLength() );
1332  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1333 
1334  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1335  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1336 
1337  if( m_aBmpEx.IsTransparent() )
1338  {
1339  const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1340  for( std::size_t i=0; i<nLen; ++i )
1341  {
1342  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1343  toByteColor(rgbColor[i].Green),
1344  toByteColor(rgbColor[i].Blue));
1345  const BitmapColor aCol2 =
1346  m_bPalette ?
1347  BitmapColor(
1348  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1349  aCol;
1350 
1351  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1352  pColors += nNonAlphaBytes;
1353  *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1354  }
1355  }
1356  else
1357  {
1358  for( std::size_t i=0; i<nLen; ++i )
1359  {
1360  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1361  toByteColor(rgbColor[i].Green),
1362  toByteColor(rgbColor[i].Blue));
1363  const BitmapColor aCol2 =
1364  m_bPalette ?
1365  BitmapColor(
1366  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1367  aCol;
1368 
1369  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1370  }
1371  }
1372 
1373  return aRes;
1374 }
1375 
1376 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1377 {
1378  SolarMutexGuard aGuard;
1379 
1380  const std::size_t nLen( rgbColor.getLength() );
1381  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1382 
1383  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1384  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1385 
1386  if( m_aBmpEx.IsTransparent() )
1387  {
1388  const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1389  for( std::size_t i=0; i<nLen; ++i )
1390  {
1391  const double nAlpha( rgbColor[i].Alpha );
1392  const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1393  toByteColor(rgbColor[i].Green / nAlpha),
1394  toByteColor(rgbColor[i].Blue / nAlpha));
1395  const BitmapColor aCol2 =
1396  m_bPalette ?
1397  BitmapColor(
1398  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1399  aCol;
1400 
1401  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1402  pColors += nNonAlphaBytes;
1403  *pColors++ = 255 - toByteColor(nAlpha);
1404  }
1405  }
1406  else
1407  {
1408  for( std::size_t i=0; i<nLen; ++i )
1409  {
1410  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1411  toByteColor(rgbColor[i].Green),
1412  toByteColor(rgbColor[i].Blue));
1413  const BitmapColor aCol2 =
1414  m_bPalette ?
1415  BitmapColor(
1416  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1417  aCol;
1418 
1419  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1420  }
1421  }
1422 
1423  return aRes;
1424 }
1425 
1426 
1427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long getHeight() const
long Width() const
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getProperties() override
Bitmap GetMask() const
Definition: bitmapex.cxx:258
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:61
virtual css::uno::Sequence< css::rendering::RGBColor > SAL_CALL convertToRGB(const css::uno::Sequence< double > &deviceColor) override
virtual sal_Bool SAL_CALL setIndex(const css::uno::Sequence< double > &color, sal_Bool transparency,::sal_Int32 nIndex) override
sal_uInt8 GetRed() const
Scanline GetScanline(long nY) const
virtual ::sal_Int8 SAL_CALL getType() override
sal_uInt32 GetRedMask() const
Definition: ColorMask.hxx:123
signed char sal_Int8
long getWidth() const
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: bitmapex.cxx:370
Bitmap const & GetBitmap() const
Definition: alpha.cxx:70
virtual css::uno::Reference< css::rendering::XColorSpace > SAL_CALL getColorSpace() override
sal_uInt16 GetBitCount() const
virtual css::geometry::IntegerSize2D SAL_CALL getSize() override
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rBitmapColor) const
Definition: bmpacc.cxx:81
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertIntegerToARGB(const css::uno::Sequence< ::sal_Int8 > &deviceColor) override
Size GetSizePixel() const
long Width() const
sal_uInt8 GetPixelIndex(long nY, long nX) const
float x
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace(const css::uno::Sequence< ::sal_Int8 > &deviceColor, const css::uno::Reference< css::rendering::XIntegerBitmapColorSpace > &targetColorSpace) override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
virtual sal_Bool SAL_CALL hasAlpha() override
css::rendering::IntegerBitmapLayout m_aLayout
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getData(css::rendering::IntegerBitmapLayout &bitmapLayout, const css::geometry::IntegerRectangle2D &rect) override
virtual css::uno::Sequence< double > SAL_CALL convertFromARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertToARGB(const css::uno::Sequence< double > &deviceColor) override
bool IsAlpha() const
Definition: bitmapex.cxx:226
css::uno::Reference< css::rendering::XBitmapPalette > getPalette()
virtual css::uno::Sequence< double > SAL_CALL convertFromRGB(const css::uno::Sequence< css::rendering::RGBColor > &rgbColor) override
geometry::IntegerSize2D integerSize2DFromSize(const Size &rSize)
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB(const css::uno::Sequence< css::rendering::RGBColor > &rgbColor) override
void SetPixelOnData(sal_uInt8 *pData, long nX, const BitmapColor &rBitmapColor)
long Top() const
SAL_DLLPRIVATE void setComponentInfo(sal_uInt32 redShift, sal_uInt32 greenShift, sal_uInt32 blueShift)
virtual ~VclCanvasBitmap() override
sal_uInt8 GetBlue() const
sal_Int8 toByteColor(double val)
Convert [0,1] double value to [0,255] int.
float y
virtual css::uno::Sequence< css::rendering::RGBColor > SAL_CALL convertIntegerToRGB(const css::uno::Sequence< ::sal_Int8 > &deviceColor) override
vcl::ScopedBitmapAccess< BitmapReadAccess, Bitmap,&Bitmap::AcquireReadAccess > ScopedReadAccess
Definition: bitmap.hxx:530
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
sal_uInt32 GetScanlineSize() const
bool HasPalette() const
virtual css::uno::Reference< css::rendering::XBitmap > SAL_CALL getScaledBitmap(const css::geometry::RealSize2D &newSize, sal_Bool beFast) override
ScanlineFormat GetScanlineFormat() const
VclCanvasBitmap(const BitmapEx &rBitmap)
Create API wrapper for given BitmapEx.
int i
virtual sal_Bool SAL_CALL getIndex(css::uno::Sequence< double > &entry,::sal_Int32 nIndex) override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getPixel(css::rendering::IntegerBitmapLayout &bitmapLayout, const css::geometry::IntegerPoint2D &pos) override
void SetRight(long v)
virtual sal_Int32 SAL_CALL getNumberOfEntries() override
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertIntegerToPARGB(const css::uno::Sequence< ::sal_Int8 > &deviceColor) override
#define ENSURE_ARG_OR_THROW2(c, m, ifc, arg)
unsigned char sal_Bool
uno::Sequence< sal_Int8 > m_aComponentTags
long Bottom() const
virtual ::sal_Int32 SAL_CALL getBitsPerPixel() override
virtual css::rendering::IntegerBitmapLayout SAL_CALL getMemoryLayout() override
bool IsTransparent() const
Definition: bitmapex.cxx:221
virtual css::uno::Sequence< double > SAL_CALL convertFromIntegerColorSpace(const css::uno::Sequence< ::sal_Int8 > &deviceColor, const css::uno::Reference< css::rendering::XColorSpace > &targetColorSpace) override
sal_uInt16 GetPaletteEntryCount() const
ColorMask & GetColorMask() const
sal_uInt8 GetGreen() const
#define ENSURE_OR_THROW(c, m)
Size sizeFromRealSize2D(const geometry::RealSize2D &rSize)
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertToPARGB(const css::uno::Sequence< double > &deviceColor) override
double toDoubleColor(sal_uInt8 val)
Convert [0,255] int value to [0,1] double value.
uno::Reference< rendering::XColorSpace > createStandardColorSpace()
Create a standard color space suitable for VCL RGB color.
AlphaMask GetAlpha() const
Definition: bitmapex.cxx:268
tools::Rectangle rectangleFromIntegerRectangle2D(const geometry::IntegerRectangle2D &rRectangle)
long Height() const
unsigned char sal_uInt8
virtual css::uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts() override
virtual css::uno::Sequence< double > SAL_CALL convertColorSpace(const css::uno::Sequence< double > &deviceColor, const css::uno::Reference< css::rendering::XColorSpace > &targetColorSpace) override
Bitmap::ScopedReadAccess m_pAlphaAcc
long Left() const
sal_uInt32 GetBlueMask() const
Definition: ColorMask.hxx:133
css::uno::Sequence< sal_Int32 > m_aComponentBitCounts
BitmapColor GetPixelFromData(const sal_uInt8 *pData, long nX) const
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
Bitmap::ScopedReadAccess m_pBmpAcc
void SetLeft(long v)
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getComponentTags() override
sal_uInt32 GetGreenMask() const
Definition: ColorMask.hxx:128
virtual ::sal_Int8 SAL_CALL getRenderingIntent() override
css::uno::Sequence< sal_Int8 > m_aComponentTags
virtual css::uno::Sequence< double > SAL_CALL convertFromPARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, long nX) const
virtual ::sal_Int8 SAL_CALL getEndianness() override