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