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/BitmapReadAccess.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  // convert alpha to transparency to preserve UNO compat
568  *pOutBuf = 255 - m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
569  }
570  else
571  {
572  const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
573  Scanline pScan = m_pBmpAcc->GetScanline(pos.Y);
574 
575  // input integer multiple of byte - copy directly
576  memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
577  pOutBuf += nNonAlphaBytes;
578  // convert alpha to transparency to preserve UNO compat
579  *pOutBuf++ = 255 - m_pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
580  }
581  }
582 
583  return aRet;
584 }
585 
586 uno::Reference< rendering::XBitmapPalette > VclCanvasBitmap::getPalette()
587 {
588  SolarMutexGuard aGuard;
589 
590  uno::Reference< XBitmapPalette > aRet;
591  if( m_bPalette )
592  aRet.set(this);
593 
594  return aRet;
595 }
596 
597 rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout()
598 {
599  SolarMutexGuard aGuard;
600 
601  rendering::IntegerBitmapLayout aLayout( m_aLayout );
602 
603  // only set references to self on separate copy of
604  // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
605  // a circular reference!
606  if( m_bPalette )
607  aLayout.Palette.set( this );
608 
609  aLayout.ColorSpace.set( this );
610 
611  return aLayout;
612 }
613 
615 {
616  SolarMutexGuard aGuard;
617 
618  if( !m_pBmpAcc )
619  return 0;
620 
622 }
623 
624 sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex )
625 {
626  SolarMutexGuard aGuard;
627 
628  const sal_uInt16 nCount( m_pBmpAcc ?
629  (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
630  OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
631  if( nIndex < 0 || nIndex >= nCount )
632  throw lang::IndexOutOfBoundsException("Palette index out of range",
633  static_cast<rendering::XBitmapPalette*>(this));
634 
635  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
636  o_entry.realloc(3);
637  double* pColor=o_entry.getArray();
638  pColor[0] = aCol.GetRed();
639  pColor[1] = aCol.GetGreen();
640  pColor[2] = aCol.GetBlue();
641 
642  return true; // no palette transparency here.
643 }
644 
645 sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex )
646 {
647  SolarMutexGuard aGuard;
648 
649  const sal_uInt16 nCount( m_pBmpAcc ?
650  (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 );
651 
652  OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
653  if( nIndex < 0 || nIndex >= nCount )
654  throw lang::IndexOutOfBoundsException("Palette index out of range",
655  static_cast<rendering::XBitmapPalette*>(this));
656 
657  return false; // read-only implementation
658 }
659 
660 namespace
661 {
662  struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
663  PaletteColorSpaceHolder>
664  {
665  uno::Reference<rendering::XColorSpace> operator()()
666  {
668  }
669  };
670 }
671 
672 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( )
673 {
674  // this is the method from XBitmapPalette. Return palette color
675  // space here
676  return PaletteColorSpaceHolder::get();
677 }
678 
680 {
681  return rendering::ColorSpaceType::RGB;
682 }
683 
684 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( )
685 {
686  SolarMutexGuard aGuard;
687  return m_aComponentTags;
688 }
689 
691 {
692  return rendering::RenderingIntent::PERCEPTUAL;
693 }
694 
695 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( )
696 {
697  return uno::Sequence< ::beans::PropertyValue >();
698 }
699 
700 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
701  const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
702 {
703  // TODO(P3): if we know anything about target
704  // colorspace, this can be greatly sped up
705  uno::Sequence<rendering::ARGBColor> aIntermediate(
706  convertToARGB(deviceColor));
707  return targetColorSpace->convertFromARGB(aIntermediate);
708 }
709 
710 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor )
711 {
712  SolarMutexGuard aGuard;
713 
714  const std::size_t nLen( deviceColor.getLength() );
715  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
716  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
717  "number of channels no multiple of pixel element count",
718  static_cast<rendering::XBitmapPalette*>(this), 01);
719 
720  uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
721  rendering::RGBColor* pOut( aRes.getArray() );
722 
723  if( m_bPalette )
724  {
725  OSL_ENSURE(m_nIndexIndex != -1,
726  "Invalid color channel indices");
728  "Unable to get BitmapAccess");
729 
730  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
731  {
732  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
733  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
734 
735  // TODO(F3): Convert result to sRGB color space
736  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
737  toDoubleColor(aCol.GetGreen()),
738  toDoubleColor(aCol.GetBlue()));
739  }
740  }
741  else
742  {
743  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
744  "Invalid color channel indices");
745 
746  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
747  {
748  // TODO(F3): Convert result to sRGB color space
749  *pOut++ = rendering::RGBColor(
750  deviceColor[i+m_nRedIndex],
751  deviceColor[i+m_nGreenIndex],
752  deviceColor[i+m_nBlueIndex]);
753  }
754  }
755 
756  return aRes;
757 }
758 
759 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor )
760 {
761  SolarMutexGuard aGuard;
762 
763  const std::size_t nLen( deviceColor.getLength() );
764  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
765  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
766  "number of channels no multiple of pixel element count",
767  static_cast<rendering::XBitmapPalette*>(this), 01);
768 
769  uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
770  rendering::ARGBColor* pOut( aRes.getArray() );
771 
772  if( m_bPalette )
773  {
774  OSL_ENSURE(m_nIndexIndex != -1,
775  "Invalid color channel indices");
777  "Unable to get BitmapAccess");
778 
779  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
780  {
781  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
782  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
783 
784  // TODO(F3): Convert result to sRGB color space
785  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
786  *pOut++ = rendering::ARGBColor(nAlpha,
787  toDoubleColor(aCol.GetRed()),
788  toDoubleColor(aCol.GetGreen()),
789  toDoubleColor(aCol.GetBlue()));
790  }
791  }
792  else
793  {
794  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
795  "Invalid color channel indices");
796 
797  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
798  {
799  // TODO(F3): Convert result to sRGB color space
800  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
801  *pOut++ = rendering::ARGBColor(
802  nAlpha,
803  deviceColor[i+m_nRedIndex],
804  deviceColor[i+m_nGreenIndex],
805  deviceColor[i+m_nBlueIndex]);
806  }
807  }
808 
809  return aRes;
810 }
811 
812 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor )
813 {
814  SolarMutexGuard aGuard;
815 
816  const std::size_t nLen( deviceColor.getLength() );
817  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
818  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
819  "number of channels no multiple of pixel element count",
820  static_cast<rendering::XBitmapPalette*>(this), 01);
821 
822  uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
823  rendering::ARGBColor* pOut( aRes.getArray() );
824 
825  if( m_bPalette )
826  {
827  OSL_ENSURE(m_nIndexIndex != -1,
828  "Invalid color channel indices");
830  "Unable to get BitmapAccess");
831 
832  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
833  {
834  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
835  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
836 
837  // TODO(F3): Convert result to sRGB color space
838  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
839  *pOut++ = rendering::ARGBColor(nAlpha,
840  nAlpha*toDoubleColor(aCol.GetRed()),
841  nAlpha*toDoubleColor(aCol.GetGreen()),
842  nAlpha*toDoubleColor(aCol.GetBlue()));
843  }
844  }
845  else
846  {
847  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
848  "Invalid color channel indices");
849 
850  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
851  {
852  // TODO(F3): Convert result to sRGB color space
853  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
854  *pOut++ = rendering::ARGBColor(
855  nAlpha,
856  nAlpha*deviceColor[i+m_nRedIndex],
857  nAlpha*deviceColor[i+m_nGreenIndex],
858  nAlpha*deviceColor[i+m_nBlueIndex]);
859  }
860  }
861 
862  return aRes;
863 }
864 
865 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
866 {
867  SolarMutexGuard aGuard;
868 
869  const std::size_t nLen( rgbColor.getLength() );
870  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
871 
872  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
873  double* pColors=aRes.getArray();
874 
875  if( m_bPalette )
876  {
877  for( const auto& rIn : rgbColor )
878  {
880  BitmapColor(toByteColor(rIn.Red),
881  toByteColor(rIn.Green),
882  toByteColor(rIn.Blue)));
883  if( m_nAlphaIndex != -1 )
884  pColors[m_nAlphaIndex] = 1.0;
885 
886  pColors += nComponentsPerPixel;
887  }
888  }
889  else
890  {
891  for( const auto& rIn : rgbColor )
892  {
893  pColors[m_nRedIndex] = rIn.Red;
894  pColors[m_nGreenIndex] = rIn.Green;
895  pColors[m_nBlueIndex] = rIn.Blue;
896  if( m_nAlphaIndex != -1 )
897  pColors[m_nAlphaIndex] = 1.0;
898 
899  pColors += nComponentsPerPixel;
900  }
901  }
902  return aRes;
903 }
904 
905 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
906 {
907  SolarMutexGuard aGuard;
908 
909  const std::size_t nLen( rgbColor.getLength() );
910  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
911 
912  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
913  double* pColors=aRes.getArray();
914 
915  if( m_bPalette )
916  {
917  for( const auto& rIn : rgbColor )
918  {
920  BitmapColor(toByteColor(rIn.Red),
921  toByteColor(rIn.Green),
922  toByteColor(rIn.Blue)));
923  if( m_nAlphaIndex != -1 )
924  pColors[m_nAlphaIndex] = rIn.Alpha;
925 
926  pColors += nComponentsPerPixel;
927  }
928  }
929  else
930  {
931  for( const auto& rIn : rgbColor )
932  {
933  pColors[m_nRedIndex] = rIn.Red;
934  pColors[m_nGreenIndex] = rIn.Green;
935  pColors[m_nBlueIndex] = rIn.Blue;
936  if( m_nAlphaIndex != -1 )
937  pColors[m_nAlphaIndex] = rIn.Alpha;
938 
939  pColors += nComponentsPerPixel;
940  }
941  }
942  return aRes;
943 }
944 
945 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
946 {
947  SolarMutexGuard aGuard;
948 
949  const std::size_t nLen( rgbColor.getLength() );
950  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
951 
952  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
953  double* pColors=aRes.getArray();
954 
955  if( m_bPalette )
956  {
957  for( const auto& rIn : rgbColor )
958  {
959  const double nAlpha( rIn.Alpha );
961  BitmapColor(toByteColor(rIn.Red / nAlpha),
962  toByteColor(rIn.Green / nAlpha),
963  toByteColor(rIn.Blue / nAlpha)));
964  if( m_nAlphaIndex != -1 )
965  pColors[m_nAlphaIndex] = nAlpha;
966 
967  pColors += nComponentsPerPixel;
968  }
969  }
970  else
971  {
972  for( const auto& rIn : rgbColor )
973  {
974  const double nAlpha( rIn.Alpha );
975  pColors[m_nRedIndex] = rIn.Red / nAlpha;
976  pColors[m_nGreenIndex] = rIn.Green / nAlpha;
977  pColors[m_nBlueIndex] = rIn.Blue / nAlpha;
978  if( m_nAlphaIndex != -1 )
979  pColors[m_nAlphaIndex] = nAlpha;
980 
981  pColors += nComponentsPerPixel;
982  }
983  }
984  return aRes;
985 }
986 
987 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( )
988 {
989  SolarMutexGuard aGuard;
990  return m_nBitsPerOutputPixel;
991 }
992 
993 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( )
994 {
995  SolarMutexGuard aGuard;
996  return m_aComponentBitCounts;
997 }
998 
1000 {
1001  SolarMutexGuard aGuard;
1002  return m_nEndianness;
1003 }
1004 
1005 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1006  const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
1007 {
1008  if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1009  {
1010  SolarMutexGuard aGuard;
1011 
1012  const std::size_t nLen( deviceColor.getLength() );
1013  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
1014  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
1015  "number of channels no multiple of pixel element count",
1016  static_cast<rendering::XBitmapPalette*>(this), 01);
1017 
1018  uno::Sequence<double> aRes(nLen);
1019  double* pOut( aRes.getArray() );
1020 
1021  if( m_bPalette )
1022  {
1023  OSL_ENSURE(m_nIndexIndex != -1,
1024  "Invalid color channel indices");
1026  "Unable to get BitmapAccess");
1027 
1028  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1029  {
1030  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
1031  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
1032 
1033  // TODO(F3): Convert result to sRGB color space
1034  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1035  *pOut++ = toDoubleColor(aCol.GetRed());
1036  *pOut++ = toDoubleColor(aCol.GetGreen());
1037  *pOut++ = toDoubleColor(aCol.GetBlue());
1038  *pOut++ = nAlpha;
1039  }
1040  }
1041  else
1042  {
1043  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
1044  "Invalid color channel indices");
1045 
1046  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
1047  {
1048  // TODO(F3): Convert result to sRGB color space
1049  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
1050  *pOut++ = deviceColor[i+m_nRedIndex];
1051  *pOut++ = deviceColor[i+m_nGreenIndex];
1052  *pOut++ = deviceColor[i+m_nBlueIndex];
1053  *pOut++ = nAlpha;
1054  }
1055  }
1056 
1057  return aRes;
1058  }
1059  else
1060  {
1061  // TODO(P3): if we know anything about target
1062  // colorspace, this can be greatly sped up
1063  uno::Sequence<rendering::ARGBColor> aIntermediate(
1064  convertIntegerToARGB(deviceColor));
1065  return targetColorSpace->convertFromARGB(aIntermediate);
1066  }
1067 }
1068 
1069 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1070  const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace )
1071 {
1072  if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1073  {
1074  // it's us, so simply pass-through the data
1075  return deviceColor;
1076  }
1077  else
1078  {
1079  // TODO(P3): if we know anything about target
1080  // colorspace, this can be greatly sped up
1081  uno::Sequence<rendering::ARGBColor> aIntermediate(
1082  convertIntegerToARGB(deviceColor));
1083  return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1084  }
1085 }
1086 
1087 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1088 {
1089  SolarMutexGuard aGuard;
1090 
1091  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1092  const std::size_t nLen( deviceColor.getLength() );
1093  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1094 
1095  uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1096  rendering::RGBColor* pOut( aRes.getArray() );
1097 
1099  "Unable to get BitmapAccess");
1100 
1101  if( m_aBmpEx.IsTransparent() )
1102  {
1103  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1104  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1105  {
1106  // if palette, index is guaranteed to be 8 bit
1107  const BitmapColor aCol =
1108  m_bPalette ?
1109  m_pBmpAcc->GetPaletteColor(*pIn) :
1110  m_pBmpAcc->GetPixelFromData(pIn,0);
1111 
1112  // TODO(F3): Convert result to sRGB color space
1113  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1114  toDoubleColor(aCol.GetGreen()),
1115  toDoubleColor(aCol.GetBlue()));
1116  // skips alpha
1117  pIn += nBytesPerPixel;
1118  }
1119  }
1120  else
1121  {
1122  for( sal_Int32 i=0; i<nNumColors; ++i )
1123  {
1124  const BitmapColor aCol =
1125  m_bPalette ?
1127  m_pBmpAcc->GetPixelFromData(pIn, i);
1128 
1129  // TODO(F3): Convert result to sRGB color space
1130  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1131  toDoubleColor(aCol.GetGreen()),
1132  toDoubleColor(aCol.GetBlue()));
1133  }
1134  }
1135 
1136  return aRes;
1137 }
1138 
1139 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1140 {
1141  SolarMutexGuard aGuard;
1142 
1143  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1144  const std::size_t nLen( deviceColor.getLength() );
1145  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1146 
1147  uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1148  rendering::ARGBColor* pOut( aRes.getArray() );
1149 
1151  "Unable to get BitmapAccess");
1152 
1153  if( m_aBmpEx.IsTransparent() )
1154  {
1155  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1156  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1157  const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1158  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1159  {
1160  // if palette, index is guaranteed to be 8 bit
1161  const BitmapColor aCol =
1162  m_bPalette ?
1163  m_pBmpAcc->GetPaletteColor(*pIn) :
1164  m_pBmpAcc->GetPixelFromData(pIn,0);
1165 
1166  // TODO(F3): Convert result to sRGB color space
1167  *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1168  toDoubleColor(aCol.GetRed()),
1169  toDoubleColor(aCol.GetGreen()),
1170  toDoubleColor(aCol.GetBlue()));
1171  pIn += nBytesPerPixel;
1172  }
1173  }
1174  else
1175  {
1176  for( sal_Int32 i=0; i<nNumColors; ++i )
1177  {
1178  const BitmapColor aCol =
1179  m_bPalette ?
1181  m_pBmpAcc->GetPixelFromData(pIn, i);
1182 
1183  // TODO(F3): Convert result to sRGB color space
1184  *pOut++ = rendering::ARGBColor(1.0,
1185  toDoubleColor(aCol.GetRed()),
1186  toDoubleColor(aCol.GetGreen()),
1187  toDoubleColor(aCol.GetBlue()));
1188  }
1189  }
1190 
1191  return aRes;
1192 }
1193 
1194 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1195 {
1196  SolarMutexGuard aGuard;
1197 
1198  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1199  const std::size_t nLen( deviceColor.getLength() );
1200  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1201 
1202  uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1203  rendering::ARGBColor* pOut( aRes.getArray() );
1204 
1206  "Unable to get BitmapAccess");
1207 
1208  if( m_aBmpEx.IsTransparent() )
1209  {
1210  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1211  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1212  const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1213  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1214  {
1215  // if palette, index is guaranteed to be 8 bit
1216  const BitmapColor aCol =
1217  m_bPalette ?
1218  m_pBmpAcc->GetPaletteColor(*pIn) :
1219  m_pBmpAcc->GetPixelFromData(pIn,0);
1220 
1221  // TODO(F3): Convert result to sRGB color space
1222  const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1223  *pOut++ = rendering::ARGBColor(nAlpha,
1224  nAlpha*toDoubleColor(aCol.GetRed()),
1225  nAlpha*toDoubleColor(aCol.GetGreen()),
1226  nAlpha*toDoubleColor(aCol.GetBlue()));
1227  pIn += nBytesPerPixel;
1228  }
1229  }
1230  else
1231  {
1232  for( sal_Int32 i=0; i<nNumColors; ++i )
1233  {
1234  const BitmapColor aCol =
1235  m_bPalette ?
1237  m_pBmpAcc->GetPixelFromData(pIn, i);
1238 
1239  // TODO(F3): Convert result to sRGB color space
1240  *pOut++ = rendering::ARGBColor(1.0,
1241  toDoubleColor(aCol.GetRed()),
1242  toDoubleColor(aCol.GetGreen()),
1243  toDoubleColor(aCol.GetBlue()));
1244  }
1245  }
1246 
1247  return aRes;
1248 }
1249 
1250 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
1251 {
1252  SolarMutexGuard aGuard;
1253 
1254  const std::size_t nLen( rgbColor.getLength() );
1255  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1256 
1257  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1258  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1259 
1260  if( m_aBmpEx.IsTransparent() )
1261  {
1262  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1263  for( std::size_t i=0; i<nLen; ++i )
1264  {
1265  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1266  toByteColor(rgbColor[i].Green),
1267  toByteColor(rgbColor[i].Blue));
1268  const BitmapColor aCol2 =
1269  m_bPalette ?
1270  BitmapColor(
1271  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1272  aCol;
1273 
1274  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1275  pColors += nNonAlphaBytes;
1276  *pColors++ = sal_uInt8(255);
1277  }
1278  }
1279  else
1280  {
1281  for( std::size_t i=0; i<nLen; ++i )
1282  {
1283  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1284  toByteColor(rgbColor[i].Green),
1285  toByteColor(rgbColor[i].Blue));
1286  const BitmapColor aCol2 =
1287  m_bPalette ?
1288  BitmapColor(
1289  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1290  aCol;
1291 
1292  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1293  }
1294  }
1295 
1296  return aRes;
1297 }
1298 
1299 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1300 {
1301  SolarMutexGuard aGuard;
1302 
1303  const std::size_t nLen( rgbColor.getLength() );
1304  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1305 
1306  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1307  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1308 
1309  if( m_aBmpEx.IsTransparent() )
1310  {
1311  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1312  for( std::size_t i=0; i<nLen; ++i )
1313  {
1314  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1315  toByteColor(rgbColor[i].Green),
1316  toByteColor(rgbColor[i].Blue));
1317  const BitmapColor aCol2 =
1318  m_bPalette ?
1319  BitmapColor(
1320  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1321  aCol;
1322 
1323  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1324  pColors += nNonAlphaBytes;
1325  *pColors++ = toByteColor(rgbColor[i].Alpha);
1326  }
1327  }
1328  else
1329  {
1330  for( std::size_t i=0; i<nLen; ++i )
1331  {
1332  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1333  toByteColor(rgbColor[i].Green),
1334  toByteColor(rgbColor[i].Blue));
1335  const BitmapColor aCol2 =
1336  m_bPalette ?
1337  BitmapColor(
1338  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1339  aCol;
1340 
1341  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1342  }
1343  }
1344 
1345  return aRes;
1346 }
1347 
1348 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1349 {
1350  SolarMutexGuard aGuard;
1351 
1352  const std::size_t nLen( rgbColor.getLength() );
1353  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1354 
1355  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1356  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1357 
1358  if( m_aBmpEx.IsTransparent() )
1359  {
1360  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1361  for( std::size_t i=0; i<nLen; ++i )
1362  {
1363  const double nAlpha( rgbColor[i].Alpha );
1364  const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1365  toByteColor(rgbColor[i].Green / nAlpha),
1366  toByteColor(rgbColor[i].Blue / nAlpha));
1367  const BitmapColor aCol2 =
1368  m_bPalette ?
1369  BitmapColor(
1370  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1371  aCol;
1372 
1373  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1374  pColors += nNonAlphaBytes;
1375  *pColors++ = toByteColor(nAlpha);
1376  }
1377  }
1378  else
1379  {
1380  for( std::size_t i=0; i<nLen; ++i )
1381  {
1382  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1383  toByteColor(rgbColor[i].Green),
1384  toByteColor(rgbColor[i].Blue));
1385  const BitmapColor aCol2 =
1386  m_bPalette ?
1387  BitmapColor(
1388  sal::static_int_cast<sal_uInt8>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) :
1389  aCol;
1390 
1391  m_pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1392  }
1393  }
1394 
1395  return aRes;
1396 }
1397 
1398 
1399 /* 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:253
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
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:365
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
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:221
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:537
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:216
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:263
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