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