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 {
99  // BitmapReadAccess is more expensive than BitmapInfoAccess,
100  // as the latter requires also pixels, which may need converted
101  // from the system format (and even fetched). Most calls here
102  // need only info access, create read access only on demand.
103  if(!m_pBmpReadAcc)
104  m_pBmpReadAcc.emplace(m_aBitmap);
105  return *m_pBmpReadAcc;
106 }
107 
109 {
110  if(!m_pAlphaReadAcc)
111  m_pAlphaReadAcc.emplace(m_aAlpha);
112  return *m_pAlphaReadAcc;
113 }
114 
116  m_aBmpEx( rBitmap ),
117  m_aBitmap( rBitmap.GetBitmap() ),
118  m_pBmpAcc( m_aBitmap ),
119  m_nBitsPerInputPixel(0),
120  m_nBitsPerOutputPixel(0),
121  m_nRedIndex(-1),
122  m_nGreenIndex(-1),
123  m_nBlueIndex(-1),
124  m_nAlphaIndex(-1),
125  m_nIndexIndex(-1),
126  m_bPalette(false)
127 {
128  if( m_aBmpEx.IsAlpha() )
129  {
132  }
133 
134  m_aLayout.ScanLines = 0;
135  m_aLayout.ScanLineBytes = 0;
136  m_aLayout.ScanLineStride = 0;
137  m_aLayout.PlaneStride = 0;
138  m_aLayout.ColorSpace.clear();
139  m_aLayout.Palette.clear();
140  m_aLayout.IsMsbFirst = false;
141 
142  if( !m_pBmpAcc )
143  return;
144 
145  m_aLayout.ScanLines = m_pBmpAcc->Height();
146  m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8;
147  m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize();
148  m_aLayout.PlaneStride = 0;
149 
150  switch( m_pBmpAcc->GetScanlineFormat() )
151  {
153  m_bPalette = true;
155  m_aLayout.IsMsbFirst = true;
156  break;
157 
159  m_bPalette = true;
161  m_aLayout.IsMsbFirst = false;
162  break;
163 
165  m_bPalette = true;
167  m_aLayout.IsMsbFirst = false; // doesn't matter
168  break;
169 
171  m_bPalette = false;
173  m_aLayout.IsMsbFirst = false; // doesn't matter
174  setComponentInfo( static_cast<sal_uInt32>(0xff0000UL),
175  static_cast<sal_uInt32>(0x00ff00UL),
176  static_cast<sal_uInt32>(0x0000ffUL) );
177  break;
178 
180  m_bPalette = false;
182  m_aLayout.IsMsbFirst = false; // doesn't matter
183  setComponentInfo( static_cast<sal_uInt32>(0x0000ffUL),
184  static_cast<sal_uInt32>(0x00ff00UL),
185  static_cast<sal_uInt32>(0xff0000UL) );
186  break;
187 
189  {
190  m_bPalette = false;
192  m_aLayout.IsMsbFirst = false; // doesn't matter
193 
194  m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::ALPHA,
195  /* 1 */ rendering::ColorComponentTag::RGB_BLUE,
196  /* 2 */ rendering::ColorComponentTag::RGB_GREEN,
197  /* 3 */ rendering::ColorComponentTag::RGB_RED };
198 
199  m_aComponentBitCounts = { /* 0 */ 8,
200  /* 1 */ 8,
201  /* 2 */ 8,
202  /* 3 */ 8 };
203 
204  m_nRedIndex = 3;
205  m_nGreenIndex = 2;
206  m_nBlueIndex = 1;
207  m_nAlphaIndex = 0;
208  }
209  break;
210 
212  {
213  m_bPalette = false;
215  m_aLayout.IsMsbFirst = false; // doesn't matter
216 
217  m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::ALPHA,
218  /* 1 */ rendering::ColorComponentTag::RGB_RED,
219  /* 2 */ rendering::ColorComponentTag::RGB_GREEN,
220  /* 3 */ rendering::ColorComponentTag::RGB_BLUE };
221 
222  m_aComponentBitCounts = { /* 0 */ 8,
223  /* 1 */ 8,
224  /* 2 */ 8,
225  /* 3 */ 8 };
226 
227  m_nRedIndex = 1;
228  m_nGreenIndex = 2;
229  m_nBlueIndex = 3;
230  m_nAlphaIndex = 0;
231  }
232  break;
233 
235  {
236  m_bPalette = false;
238  m_aLayout.IsMsbFirst = false; // doesn't matter
239 
240  m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::RGB_BLUE,
241  /* 1 */ rendering::ColorComponentTag::RGB_GREEN,
242  /* 2 */ rendering::ColorComponentTag::RGB_RED,
243  /* 3 */ rendering::ColorComponentTag::ALPHA };
244 
245  m_aComponentBitCounts = { /* 0 */ 8,
246  /* 1 */ 8,
247  /* 2 */ 8,
248  /* 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 = { /* 0 */ rendering::ColorComponentTag::RGB_RED,
264  /* 1 */ rendering::ColorComponentTag::RGB_GREEN,
265  /* 2 */ rendering::ColorComponentTag::RGB_BLUE,
266  /* 3 */ rendering::ColorComponentTag::ALPHA };
267 
268  m_aComponentBitCounts = { /* 0 */ 8,
269  /* 1 */ 8,
270  /* 2 */ 8,
271  /* 3 */ 8 };
272 
273  m_nRedIndex = 0;
274  m_nGreenIndex = 1;
275  m_nBlueIndex = 2;
276  m_nAlphaIndex = 3;
277  }
278  break;
279 
281  m_bPalette = false;
283  m_aLayout.IsMsbFirst = false; // doesn't matter
287  break;
288 
289  default:
290  OSL_FAIL( "unsupported bitmap format" );
291  break;
292  }
293 
294  if( m_bPalette )
295  {
296  m_aComponentTags = { rendering::ColorComponentTag::INDEX };
297 
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.getArray()[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
322 
323  m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
324  m_aComponentBitCounts.getArray()[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  {
413  OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
414 
415  // can return bitmap data as-is
416  for( tools::Long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
417  {
418  Scanline pScan = pBmpAcc->GetScanline(y);
419  memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth());
420  pOutBuf += nScanlineStride;
421  }
422  }
423  else
424  {
427  OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
428  OSL_ENSURE(pAlphaAcc,"Invalid alpha read access");
429 
430  // interleave alpha with bitmap data - note, bitcount is
431  // always integer multiple of 8
432  OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
433  "Transparent bitmap bitcount not integer multiple of 8" );
434 
435  for( tools::Long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
436  {
437  sal_Int8* pOutScan = pOutBuf;
438 
439  if( m_nBitsPerInputPixel < 8 )
440  {
441  // input less than a byte - copy via GetPixel()
442  for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
443  {
444  *pOutScan++ = pBmpAcc->GetPixelIndex(y,x);
445  *pOutScan++ = pAlphaAcc->GetPixelIndex(y,x);
446  }
447  }
448  else
449  {
450  const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
451  const tools::Long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
452  Scanline pScan = pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
453  Scanline pScanlineAlpha = pAlphaAcc->GetScanline( y );
454 
455  // input integer multiple of byte - copy directly
456  for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
457  {
458  for( tools::Long i=0; i<nNonAlphaBytes; ++i )
459  *pOutScan++ = *pScan++;
460  *pOutScan++ = pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
461  }
462  }
463 
464  pOutBuf += nScanlineStride;
465  }
466  }
467 
468  return aRet;
469 }
470 
471 uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
472  const geometry::IntegerPoint2D& pos )
473 {
474  SolarMutexGuard aGuard;
475 
476  bitmapLayout = getMemoryLayout();
477 
478  // Invalid/empty bitmap: no data available
479  if( !m_pBmpAcc )
480  throw lang::IndexOutOfBoundsException();
481  if( m_aBmpEx.IsAlpha() && !m_pAlphaAcc )
482  throw lang::IndexOutOfBoundsException();
483 
484  if( pos.X < 0 || pos.Y < 0 ||
485  pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
486  {
487  throw lang::IndexOutOfBoundsException();
488  }
489 
490  uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
491  sal_Int8* pOutBuf = aRet.getArray();
492 
493  // copy stuff to output sequence
494  bitmapLayout.ScanLines = 1;
495  bitmapLayout.ScanLineBytes =
496  bitmapLayout.ScanLineStride= aRet.getLength();
497 
498  const tools::Long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
499  if( !m_aBmpEx.IsAlpha() )
500  {
502  assert(pBmpAcc && "Invalid bmp read access");
503 
504  // can return bitmap data as-is
505  Scanline pScan = pBmpAcc->GetScanline(pos.Y);
506  memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
507  }
508  else
509  {
512  assert(pBmpAcc && "Invalid bmp read access");
513  assert(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++ = pBmpAcc->GetPixelIndex(pos.Y,pos.X);
524  *pOutBuf = pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
525  }
526  else
527  {
528  const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
529  Scanline pScan = pBmpAcc->GetScanline(pos.Y);
530 
531  // input integer multiple of byte - copy directly
532  memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
533  pOutBuf += nNonAlphaBytes;
534  *pOutBuf++ = 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 uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( )
616 {
617  // this is the method from XBitmapPalette. Return palette color
618  // space here
619  static uno::Reference<rendering::XColorSpace> gColorSpace = vcl::unotools::createStandardColorSpace();
620  return gColorSpace;
621 }
622 
624 {
625  return rendering::ColorSpaceType::RGB;
626 }
627 
628 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( )
629 {
630  SolarMutexGuard aGuard;
631  return m_aComponentTags;
632 }
633 
635 {
636  return rendering::RenderingIntent::PERCEPTUAL;
637 }
638 
639 uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( )
640 {
641  return uno::Sequence< ::beans::PropertyValue >();
642 }
643 
644 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
645  const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
646 {
647  // TODO(P3): if we know anything about target
648  // colorspace, this can be greatly sped up
649  uno::Sequence<rendering::ARGBColor> aIntermediate(
650  convertToARGB(deviceColor));
651  return targetColorSpace->convertFromARGB(aIntermediate);
652 }
653 
654 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor )
655 {
656  SolarMutexGuard aGuard;
657 
658  const std::size_t nLen( deviceColor.getLength() );
659  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
660  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
661  "number of channels no multiple of pixel element count",
662  static_cast<rendering::XBitmapPalette*>(this), 01);
663 
664  uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
665  rendering::RGBColor* pOut( aRes.getArray() );
666 
667  if( m_bPalette )
668  {
669  OSL_ENSURE(m_nIndexIndex != -1,
670  "Invalid color channel indices");
672  "Unable to get BitmapAccess");
673 
674  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
675  {
676  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
677  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
678 
679  // TODO(F3): Convert result to sRGB color space
680  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
681  toDoubleColor(aCol.GetGreen()),
682  toDoubleColor(aCol.GetBlue()));
683  }
684  }
685  else
686  {
687  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
688  "Invalid color channel indices");
689 
690  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
691  {
692  // TODO(F3): Convert result to sRGB color space
693  *pOut++ = rendering::RGBColor(
694  deviceColor[i+m_nRedIndex],
695  deviceColor[i+m_nGreenIndex],
696  deviceColor[i+m_nBlueIndex]);
697  }
698  }
699 
700  return aRes;
701 }
702 
703 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor )
704 {
705  SolarMutexGuard aGuard;
706 
707  const std::size_t nLen( deviceColor.getLength() );
708  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
709  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
710  "number of channels no multiple of pixel element count",
711  static_cast<rendering::XBitmapPalette*>(this), 01);
712 
713  uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
714  rendering::ARGBColor* pOut( aRes.getArray() );
715 
716  if( m_bPalette )
717  {
718  OSL_ENSURE(m_nIndexIndex != -1,
719  "Invalid color channel indices");
721  "Unable to get BitmapAccess");
722 
723  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
724  {
725  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
726  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
727 
728  // TODO(F3): Convert result to sRGB color space
729  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
730  *pOut++ = rendering::ARGBColor(nAlpha,
731  toDoubleColor(aCol.GetRed()),
732  toDoubleColor(aCol.GetGreen()),
733  toDoubleColor(aCol.GetBlue()));
734  }
735  }
736  else
737  {
738  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
739  "Invalid color channel indices");
740 
741  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
742  {
743  // TODO(F3): Convert result to sRGB color space
744  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
745  *pOut++ = rendering::ARGBColor(
746  nAlpha,
747  deviceColor[i+m_nRedIndex],
748  deviceColor[i+m_nGreenIndex],
749  deviceColor[i+m_nBlueIndex]);
750  }
751  }
752 
753  return aRes;
754 }
755 
756 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor )
757 {
758  SolarMutexGuard aGuard;
759 
760  const std::size_t nLen( deviceColor.getLength() );
761  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
762  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
763  "number of channels no multiple of pixel element count",
764  static_cast<rendering::XBitmapPalette*>(this), 01);
765 
766  uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
767  rendering::ARGBColor* pOut( aRes.getArray() );
768 
769  if( m_bPalette )
770  {
771  OSL_ENSURE(m_nIndexIndex != -1,
772  "Invalid color channel indices");
774  "Unable to get BitmapAccess");
775 
776  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
777  {
778  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
779  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
780 
781  // TODO(F3): Convert result to sRGB color space
782  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
783  *pOut++ = rendering::ARGBColor(nAlpha,
784  nAlpha*toDoubleColor(aCol.GetRed()),
785  nAlpha*toDoubleColor(aCol.GetGreen()),
786  nAlpha*toDoubleColor(aCol.GetBlue()));
787  }
788  }
789  else
790  {
791  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
792  "Invalid color channel indices");
793 
794  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
795  {
796  // TODO(F3): Convert result to sRGB color space
797  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
798  *pOut++ = rendering::ARGBColor(
799  nAlpha,
800  nAlpha*deviceColor[i+m_nRedIndex],
801  nAlpha*deviceColor[i+m_nGreenIndex],
802  nAlpha*deviceColor[i+m_nBlueIndex]);
803  }
804  }
805 
806  return aRes;
807 }
808 
809 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
810 {
811  SolarMutexGuard aGuard;
812 
813  const std::size_t nLen( rgbColor.getLength() );
814  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
815 
816  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
817  double* pColors=aRes.getArray();
818 
819  if( m_bPalette )
820  {
821  for( const auto& rIn : rgbColor )
822  {
824  BitmapColor(toByteColor(rIn.Red),
825  toByteColor(rIn.Green),
826  toByteColor(rIn.Blue)));
827  if( m_nAlphaIndex != -1 )
828  pColors[m_nAlphaIndex] = 1.0;
829 
830  pColors += nComponentsPerPixel;
831  }
832  }
833  else
834  {
835  for( const auto& rIn : rgbColor )
836  {
837  pColors[m_nRedIndex] = rIn.Red;
838  pColors[m_nGreenIndex] = rIn.Green;
839  pColors[m_nBlueIndex] = rIn.Blue;
840  if( m_nAlphaIndex != -1 )
841  pColors[m_nAlphaIndex] = 1.0;
842 
843  pColors += nComponentsPerPixel;
844  }
845  }
846  return aRes;
847 }
848 
849 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
850 {
851  SolarMutexGuard aGuard;
852 
853  const std::size_t nLen( rgbColor.getLength() );
854  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
855 
856  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
857  double* pColors=aRes.getArray();
858 
859  if( m_bPalette )
860  {
861  for( const auto& rIn : rgbColor )
862  {
864  BitmapColor(toByteColor(rIn.Red),
865  toByteColor(rIn.Green),
866  toByteColor(rIn.Blue)));
867  if( m_nAlphaIndex != -1 )
868  pColors[m_nAlphaIndex] = rIn.Alpha;
869 
870  pColors += nComponentsPerPixel;
871  }
872  }
873  else
874  {
875  for( const auto& rIn : rgbColor )
876  {
877  pColors[m_nRedIndex] = rIn.Red;
878  pColors[m_nGreenIndex] = rIn.Green;
879  pColors[m_nBlueIndex] = rIn.Blue;
880  if( m_nAlphaIndex != -1 )
881  pColors[m_nAlphaIndex] = rIn.Alpha;
882 
883  pColors += nComponentsPerPixel;
884  }
885  }
886  return aRes;
887 }
888 
889 uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
890 {
891  SolarMutexGuard aGuard;
892 
893  const std::size_t nLen( rgbColor.getLength() );
894  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
895 
896  uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
897  double* pColors=aRes.getArray();
898 
899  if( m_bPalette )
900  {
901  for( const auto& rIn : rgbColor )
902  {
903  const double nAlpha( rIn.Alpha );
905  BitmapColor(toByteColor(rIn.Red / nAlpha),
906  toByteColor(rIn.Green / nAlpha),
907  toByteColor(rIn.Blue / nAlpha)));
908  if( m_nAlphaIndex != -1 )
909  pColors[m_nAlphaIndex] = nAlpha;
910 
911  pColors += nComponentsPerPixel;
912  }
913  }
914  else
915  {
916  for( const auto& rIn : rgbColor )
917  {
918  const double nAlpha( rIn.Alpha );
919  pColors[m_nRedIndex] = rIn.Red / nAlpha;
920  pColors[m_nGreenIndex] = rIn.Green / nAlpha;
921  pColors[m_nBlueIndex] = rIn.Blue / nAlpha;
922  if( m_nAlphaIndex != -1 )
923  pColors[m_nAlphaIndex] = nAlpha;
924 
925  pColors += nComponentsPerPixel;
926  }
927  }
928  return aRes;
929 }
930 
931 sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( )
932 {
933  SolarMutexGuard aGuard;
934  return m_nBitsPerOutputPixel;
935 }
936 
937 uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( )
938 {
939  SolarMutexGuard aGuard;
940  return m_aComponentBitCounts;
941 }
942 
944 {
945  return util::Endianness::LITTLE;
946 }
947 
948 uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
949  const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
950 {
951  if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
952  {
953  SolarMutexGuard aGuard;
954 
955  const std::size_t nLen( deviceColor.getLength() );
956  const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
957  ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
958  "number of channels no multiple of pixel element count",
959  static_cast<rendering::XBitmapPalette*>(this), 01);
960 
961  uno::Sequence<double> aRes(nLen);
962  double* pOut( aRes.getArray() );
963 
964  if( m_bPalette )
965  {
966  OSL_ENSURE(m_nIndexIndex != -1,
967  "Invalid color channel indices");
969  "Unable to get BitmapAccess");
970 
971  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
972  {
973  const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(
974  sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
975 
976  // TODO(F3): Convert result to sRGB color space
977  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
978  *pOut++ = toDoubleColor(aCol.GetRed());
979  *pOut++ = toDoubleColor(aCol.GetGreen());
980  *pOut++ = toDoubleColor(aCol.GetBlue());
981  *pOut++ = nAlpha;
982  }
983  }
984  else
985  {
986  OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
987  "Invalid color channel indices");
988 
989  for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
990  {
991  // TODO(F3): Convert result to sRGB color space
992  const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
993  *pOut++ = deviceColor[i+m_nRedIndex];
994  *pOut++ = deviceColor[i+m_nGreenIndex];
995  *pOut++ = deviceColor[i+m_nBlueIndex];
996  *pOut++ = nAlpha;
997  }
998  }
999 
1000  return aRes;
1001  }
1002  else
1003  {
1004  // TODO(P3): if we know anything about target
1005  // colorspace, this can be greatly sped up
1006  uno::Sequence<rendering::ARGBColor> aIntermediate(
1007  convertIntegerToARGB(deviceColor));
1008  return targetColorSpace->convertFromARGB(aIntermediate);
1009  }
1010 }
1011 
1012 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1013  const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace )
1014 {
1015  if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1016  {
1017  // it's us, so simply pass-through the data
1018  return deviceColor;
1019  }
1020  else
1021  {
1022  // TODO(P3): if we know anything about target
1023  // colorspace, this can be greatly sped up
1024  uno::Sequence<rendering::ARGBColor> aIntermediate(
1025  convertIntegerToARGB(deviceColor));
1026  return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1027  }
1028 }
1029 
1030 uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1031 {
1032  SolarMutexGuard aGuard;
1033 
1034  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1035  const std::size_t nLen( deviceColor.getLength() );
1036  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1037 
1038  uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1039  rendering::RGBColor* pOut( aRes.getArray() );
1040 
1042  ENSURE_OR_THROW(pBmpAcc,
1043  "Unable to get BitmapAccess");
1044 
1045  if( m_aBmpEx.IsAlpha() )
1046  {
1047  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1048  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1049  {
1050  // if palette, index is guaranteed to be 8 bit
1051  const BitmapColor aCol =
1052  m_bPalette ?
1053  pBmpAcc->GetPaletteColor(*pIn) :
1054  pBmpAcc->GetPixelFromData(pIn,0);
1055 
1056  // TODO(F3): Convert result to sRGB color space
1057  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1058  toDoubleColor(aCol.GetGreen()),
1059  toDoubleColor(aCol.GetBlue()));
1060  // skips alpha
1061  pIn += nBytesPerPixel;
1062  }
1063  }
1064  else
1065  {
1066  for( sal_Int32 i=0; i<nNumColors; ++i )
1067  {
1068  const BitmapColor aCol =
1069  m_bPalette ?
1070  pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
1071  pBmpAcc->GetPixelFromData(pIn, i);
1072 
1073  // TODO(F3): Convert result to sRGB color space
1074  *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1075  toDoubleColor(aCol.GetGreen()),
1076  toDoubleColor(aCol.GetBlue()));
1077  }
1078  }
1079 
1080  return aRes;
1081 }
1082 
1083 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1084 {
1085  SolarMutexGuard aGuard;
1086 
1087  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1088  const std::size_t nLen( deviceColor.getLength() );
1089  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1090 
1091  uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1092  rendering::ARGBColor* pOut( aRes.getArray() );
1093 
1095  ENSURE_OR_THROW(pBmpAcc,
1096  "Unable to get BitmapAccess");
1097 
1098  if( m_aBmpEx.IsAlpha() )
1099  {
1100  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1101  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1102  const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1103  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1104  {
1105  // if palette, index is guaranteed to be 8 bit
1106  const BitmapColor aCol =
1107  m_bPalette ?
1108  pBmpAcc->GetPaletteColor(*pIn) :
1109  pBmpAcc->GetPixelFromData(pIn,0);
1110 
1111  // TODO(F3): Convert result to sRGB color space
1112  *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]),
1113  toDoubleColor(aCol.GetRed()),
1114  toDoubleColor(aCol.GetGreen()),
1115  toDoubleColor(aCol.GetBlue()));
1116  pIn += nBytesPerPixel;
1117  }
1118  }
1119  else
1120  {
1121  for( sal_Int32 i=0; i<nNumColors; ++i )
1122  {
1123  const BitmapColor aCol =
1124  m_bPalette ?
1125  pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1126  pBmpAcc->GetPixelFromData(pIn, i);
1127 
1128  // TODO(F3): Convert result to sRGB color space
1129  *pOut++ = rendering::ARGBColor(1.0,
1130  toDoubleColor(aCol.GetRed()),
1131  toDoubleColor(aCol.GetGreen()),
1132  toDoubleColor(aCol.GetBlue()));
1133  }
1134  }
1135 
1136  return aRes;
1137 }
1138 
1139 uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1140 {
1141  SolarMutexGuard aGuard;
1142 
1143  const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1144  const std::size_t nLen( deviceColor.getLength() );
1145  const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1146 
1147  uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1148  rendering::ARGBColor* pOut( aRes.getArray() );
1149 
1151  ENSURE_OR_THROW(pBmpAcc,
1152  "Unable to get BitmapAccess");
1153 
1154  if( m_aBmpEx.IsAlpha() )
1155  {
1156  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1157  const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1158  const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 );
1159  for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1160  {
1161  // if palette, index is guaranteed to be 8 bit
1162  const BitmapColor aCol =
1163  m_bPalette ?
1164  pBmpAcc->GetPaletteColor(*pIn) :
1165  pBmpAcc->GetPixelFromData(pIn,0);
1166 
1167  // TODO(F3): Convert result to sRGB color space
1168  const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) );
1169  *pOut++ = rendering::ARGBColor(nAlpha,
1170  nAlpha*toDoubleColor(aCol.GetRed()),
1171  nAlpha*toDoubleColor(aCol.GetGreen()),
1172  nAlpha*toDoubleColor(aCol.GetBlue()));
1173  pIn += nBytesPerPixel;
1174  }
1175  }
1176  else
1177  {
1178  for( sal_Int32 i=0; i<nNumColors; ++i )
1179  {
1180  const BitmapColor aCol =
1181  m_bPalette ?
1182  pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1183  pBmpAcc->GetPixelFromData(pIn, i);
1184 
1185  // TODO(F3): Convert result to sRGB color space
1186  *pOut++ = rendering::ARGBColor(1.0,
1187  toDoubleColor(aCol.GetRed()),
1188  toDoubleColor(aCol.GetGreen()),
1189  toDoubleColor(aCol.GetBlue()));
1190  }
1191  }
1192 
1193  return aRes;
1194 }
1195 
1196 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
1197 {
1198  SolarMutexGuard aGuard;
1199 
1200  const std::size_t nLen( rgbColor.getLength() );
1201  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1202 
1203  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1204  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1206 
1207  if( m_aBmpEx.IsAlpha() )
1208  {
1209  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1210  for( std::size_t i=0; i<nLen; ++i )
1211  {
1212  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1213  toByteColor(rgbColor[i].Green),
1214  toByteColor(rgbColor[i].Blue));
1215  const BitmapColor aCol2 =
1216  m_bPalette ?
1217  BitmapColor(
1218  sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1219  aCol;
1220 
1221  pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1222  pColors += nNonAlphaBytes;
1223  *pColors++ = sal_uInt8(255);
1224  }
1225  }
1226  else
1227  {
1228  for( std::size_t i=0; i<nLen; ++i )
1229  {
1230  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1231  toByteColor(rgbColor[i].Green),
1232  toByteColor(rgbColor[i].Blue));
1233  const BitmapColor aCol2 =
1234  m_bPalette ?
1235  BitmapColor(
1236  sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1237  aCol;
1238 
1239  pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1240  }
1241  }
1242 
1243  return aRes;
1244 }
1245 
1246 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1247 {
1248  SolarMutexGuard aGuard;
1249 
1250  const std::size_t nLen( rgbColor.getLength() );
1251  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1252 
1253  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1254  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1256 
1257  if( m_aBmpEx.IsAlpha() )
1258  {
1259  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1260  for( std::size_t i=0; i<nLen; ++i )
1261  {
1262  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1263  toByteColor(rgbColor[i].Green),
1264  toByteColor(rgbColor[i].Blue));
1265  const BitmapColor aCol2 =
1266  m_bPalette ?
1267  BitmapColor(
1268  sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1269  aCol;
1270 
1271  pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1272  pColors += nNonAlphaBytes;
1273  *pColors++ = 255 - toByteColor(rgbColor[i].Alpha);
1274  }
1275  }
1276  else
1277  {
1278  for( std::size_t i=0; i<nLen; ++i )
1279  {
1280  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1281  toByteColor(rgbColor[i].Green),
1282  toByteColor(rgbColor[i].Blue));
1283  const BitmapColor aCol2 =
1284  m_bPalette ?
1285  BitmapColor(
1286  sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1287  aCol;
1288 
1289  pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1290  }
1291  }
1292 
1293  return aRes;
1294 }
1295 
1296 uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
1297 {
1298  SolarMutexGuard aGuard;
1299 
1300  const std::size_t nLen( rgbColor.getLength() );
1301  const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8);
1302 
1303  uno::Sequence< sal_Int8 > aRes(nNumBytes);
1304  sal_uInt8* pColors=reinterpret_cast<sal_uInt8*>(aRes.getArray());
1306 
1307  if( m_aBmpEx.IsAlpha() )
1308  {
1309  const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1310  for( std::size_t i=0; i<nLen; ++i )
1311  {
1312  const double nAlpha( rgbColor[i].Alpha );
1313  const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha),
1314  toByteColor(rgbColor[i].Green / nAlpha),
1315  toByteColor(rgbColor[i].Blue / nAlpha));
1316  const BitmapColor aCol2 =
1317  m_bPalette ?
1318  BitmapColor(
1319  sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1320  aCol;
1321 
1322  pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1323  pColors += nNonAlphaBytes;
1324  *pColors++ = 255 - toByteColor(nAlpha);
1325  }
1326  }
1327  else
1328  {
1329  for( std::size_t i=0; i<nLen; ++i )
1330  {
1331  const BitmapColor aCol(toByteColor(rgbColor[i].Red),
1332  toByteColor(rgbColor[i].Green),
1333  toByteColor(rgbColor[i].Blue));
1334  const BitmapColor aCol2 =
1335  m_bPalette ?
1336  BitmapColor(
1337  sal::static_int_cast<sal_uInt8>(pBmpAcc->GetBestPaletteIndex( aCol ))) :
1338  aCol;
1339 
1340  pBmpAcc->SetPixelOnData(pColors,i,aCol2);
1341  }
1342  }
1343 
1344  return aRes;
1345 }
1346 
1347 
1348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getProperties() override
Bitmap::ScopedReadAccess & getBitmapReadAccess()
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
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
std::optional< Bitmap::ScopedReadAccess > m_pAlphaReadAcc
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
Bitmap::ScopedInfoAccess m_pBmpAcc
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
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
std::optional< Bitmap::ScopedReadAccess > m_pBmpReadAcc
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
Bitmap::ScopedInfoAccess m_pAlphaAcc
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 & getAlphaReadAccess()
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
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
bool m_bDetectedRangeSegmentation false
virtual ::sal_Int8 SAL_CALL getEndianness() override
vcl::ScopedBitmapAccess< BitmapInfoAccess, Bitmap,&Bitmap::AcquireInfoAccess > ScopedInfoAccess