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