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
29#include <canvasbitmap.hxx>
30#include <vcl/canvastools.hxx>
32#include <vcl/svapp.hxx>
33
34#include <algorithm>
35
36using namespace vcl::unotools;
37using namespace ::com::sun::star;
38
39namespace
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
56void 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
341geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize()
342{
343 SolarMutexGuard aGuard;
345}
346
348{
349 SolarMutexGuard aGuard;
350 return m_aBmpEx.IsAlpha();
351}
352
353uno::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
364uno::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.getOpenWidth()*aRequestedBytes.getOpenHeight());
397 sal_Int8* pOutBuf = aRet.getArray();
398
399 bitmapLayout.ScanLines = aRequestedBytes.getOpenHeight();
400 bitmapLayout.ScanLineBytes =
401 bitmapLayout.ScanLineStride= aRequestedBytes.getOpenWidth();
402
403 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
405 {
406 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getOpenHeight()-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.getOpenWidth());
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
471uno::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
541uno::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
552rendering::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
579sal_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 ?
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
600sal_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 ?
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
615uno::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
628uno::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
639uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( )
640{
641 return uno::Sequence< ::beans::PropertyValue >();
642}
643
644uno::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
654uno::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 {
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
703uno::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 {
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
756uno::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 {
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
809uno::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
849uno::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
889uno::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
932{
933 SolarMutexGuard aGuard;
935}
936
937uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( )
938{
939 SolarMutexGuard aGuard;
941}
942
944{
945 return util::Endianness::LITTLE;
946}
947
948uno::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 {
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
1012uno::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
1030uno::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
1083uno::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
1139uno::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
1196uno::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 ?
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 ?
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
1246uno::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 ?
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 ?
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
1296uno::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 ?
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 ?
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: */
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
Bitmap const & GetBitmap() const
Definition: alpha.cxx:73
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:296
bool IsAlpha() const
Definition: BitmapEx.cxx:193
tools::Long Height() const
tools::Long Width() const
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rBitmapColor) const
bool HasPalette() const
ScanlineFormat GetScanlineFormat() const
sal_uInt16 GetPaletteEntryCount() const
sal_uInt16 GetBitCount() const
const ColorMask & GetColorMask() const
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
sal_uInt32 GetScanlineSize() const
sal_uInt8 GetPixelIndex(tools::Long nY, tools::Long nX) const
void SetPixelOnData(sal_uInt8 *pData, tools::Long nX, const BitmapColor &rBitmapColor)
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
Scanline GetScanline(tools::Long nY) const
Size GetSizePixel() const
vcl::ScopedBitmapAccess< BitmapInfoAccess, Bitmap, &Bitmap::AcquireInfoAccess > ScopedInfoAccess
sal_uInt32 GetRedMask() const
Definition: ColorMask.hxx:120
sal_uInt32 GetGreenMask() const
Definition: ColorMask.hxx:125
sal_uInt32 GetBlueMask() const
Definition: ColorMask.hxx:130
sal_uInt8 GetBlue() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
constexpr tools::Long Width() const
constexpr void SetLeft(tools::Long v)
constexpr tools::Long Top() const
tools::Long getOpenHeight() const
constexpr void SetRight(tools::Long v)
tools::Long getOpenWidth() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
Bitmap::ScopedInfoAccess m_pBmpAcc
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertToPARGB(const css::uno::Sequence< double > &deviceColor) override
Bitmap::ScopedReadAccess & getAlphaReadAccess()
css::uno::Sequence< sal_Int8 > m_aComponentTags
virtual ::sal_Int32 SAL_CALL getBitsPerPixel() override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
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
Bitmap::ScopedReadAccess & getBitmapReadAccess()
std::optional< Bitmap::ScopedReadAccess > m_pAlphaReadAcc
virtual ::sal_Int8 SAL_CALL getEndianness() override
virtual ~VclCanvasBitmap() override
virtual css::uno::Sequence< double > SAL_CALL convertFromPARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
virtual sal_Bool SAL_CALL setIndex(const css::uno::Sequence< double > &color, sal_Bool transparency, ::sal_Int32 nIndex) override
virtual sal_Bool SAL_CALL getIndex(css::uno::Sequence< double > &entry, ::sal_Int32 nIndex) override
virtual css::uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts() override
virtual sal_Int32 SAL_CALL getNumberOfEntries() override
virtual sal_Bool SAL_CALL hasAlpha() override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getPixel(css::rendering::IntegerBitmapLayout &bitmapLayout, const css::geometry::IntegerPoint2D &pos) override
Bitmap::ScopedInfoAccess m_pAlphaAcc
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getComponentTags() override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
css::rendering::IntegerBitmapLayout m_aLayout
virtual css::uno::Sequence< css::rendering::RGBColor > SAL_CALL convertToRGB(const css::uno::Sequence< double > &deviceColor) override
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertIntegerToPARGB(const css::uno::Sequence< ::sal_Int8 > &deviceColor) override
virtual css::uno::Sequence< double > SAL_CALL convertFromRGB(const css::uno::Sequence< css::rendering::RGBColor > &rgbColor) override
virtual css::uno::Sequence< double > SAL_CALL convertFromARGB(const css::uno::Sequence< css::rendering::ARGBColor > &rgbColor) override
virtual css::uno::Sequence< double > SAL_CALL convertFromIntegerColorSpace(const css::uno::Sequence< ::sal_Int8 > &deviceColor, const css::uno::Reference< css::rendering::XColorSpace > &targetColorSpace) override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getData(css::rendering::IntegerBitmapLayout &bitmapLayout, const css::geometry::IntegerRectangle2D &rect) override
virtual css::uno::Sequence< css::rendering::RGBColor > SAL_CALL convertIntegerToRGB(const css::uno::Sequence< ::sal_Int8 > &deviceColor) override
virtual css::geometry::IntegerSize2D SAL_CALL getSize() override
css::uno::Reference< css::rendering::XBitmapPalette > getPalette()
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getProperties() override
VclCanvasBitmap(const BitmapEx &rBitmap)
Create API wrapper for given BitmapEx.
virtual css::uno::Reference< css::rendering::XBitmap > SAL_CALL getScaledBitmap(const css::geometry::RealSize2D &newSize, sal_Bool beFast) override
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertIntegerToARGB(const css::uno::Sequence< ::sal_Int8 > &deviceColor) override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB(const css::uno::Sequence< css::rendering::RGBColor > &rgbColor) override
virtual css::uno::Sequence< double > SAL_CALL convertColorSpace(const css::uno::Sequence< double > &deviceColor, const css::uno::Reference< css::rendering::XColorSpace > &targetColorSpace) override
virtual ::sal_Int8 SAL_CALL getType() override
virtual css::rendering::IntegerBitmapLayout SAL_CALL getMemoryLayout() override
SAL_DLLPRIVATE void setComponentInfo(sal_uInt32 redShift, sal_uInt32 greenShift, sal_uInt32 blueShift)
virtual ::sal_Int8 SAL_CALL getRenderingIntent() override
virtual css::uno::Sequence< css::rendering::ARGBColor > SAL_CALL convertToARGB(const css::uno::Sequence< double > &deviceColor) override
virtual css::uno::Reference< css::rendering::XColorSpace > SAL_CALL getColorSpace() override
std::optional< Bitmap::ScopedReadAccess > m_pBmpReadAcc
css::uno::Sequence< sal_Int32 > m_aComponentBitCounts
int nCount
#define ENSURE_ARG_OR_THROW2(c, m, ifc, arg)
#define ENSURE_OR_THROW(c, m)
float y
float x
sal_Int32 nIndex
int i
long Long
Size sizeFromRealSize2D(const geometry::RealSize2D &rSize)
geometry::IntegerSize2D integerSize2DFromSize(const Size &rSize)
sal_Int8 toByteColor(double val)
Convert [0,1] double value to [0,255] int.
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.
tools::Rectangle rectangleFromIntegerRectangle2D(const geometry::IntegerRectangle2D &rRectangle)
unsigned char sal_uInt8
unsigned char sal_Bool
signed char sal_Int8
oslFileHandle & pOut
size_t pos