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