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; // doesn't matter
162 break;
163
165 m_bPalette = false;
167 m_aLayout.IsMsbFirst = false; // doesn't matter
168 setComponentInfo( static_cast<sal_uInt32>(0xff0000UL),
169 static_cast<sal_uInt32>(0x00ff00UL),
170 static_cast<sal_uInt32>(0x0000ffUL) );
171 break;
172
174 m_bPalette = false;
176 m_aLayout.IsMsbFirst = false; // doesn't matter
177 setComponentInfo( static_cast<sal_uInt32>(0x0000ffUL),
178 static_cast<sal_uInt32>(0x00ff00UL),
179 static_cast<sal_uInt32>(0xff0000UL) );
180 break;
181
183 {
184 m_bPalette = false;
186 m_aLayout.IsMsbFirst = false; // doesn't matter
187
188 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::ALPHA,
189 /* 1 */ rendering::ColorComponentTag::RGB_BLUE,
190 /* 2 */ rendering::ColorComponentTag::RGB_GREEN,
191 /* 3 */ rendering::ColorComponentTag::RGB_RED };
192
193 m_aComponentBitCounts = { /* 0 */ 8,
194 /* 1 */ 8,
195 /* 2 */ 8,
196 /* 3 */ 8 };
197
198 m_nRedIndex = 3;
199 m_nGreenIndex = 2;
200 m_nBlueIndex = 1;
201 m_nAlphaIndex = 0;
202 }
203 break;
204
206 {
207 m_bPalette = false;
209 m_aLayout.IsMsbFirst = false; // doesn't matter
210
211 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::ALPHA,
212 /* 1 */ rendering::ColorComponentTag::RGB_RED,
213 /* 2 */ rendering::ColorComponentTag::RGB_GREEN,
214 /* 3 */ rendering::ColorComponentTag::RGB_BLUE };
215
216 m_aComponentBitCounts = { /* 0 */ 8,
217 /* 1 */ 8,
218 /* 2 */ 8,
219 /* 3 */ 8 };
220
221 m_nRedIndex = 1;
222 m_nGreenIndex = 2;
223 m_nBlueIndex = 3;
224 m_nAlphaIndex = 0;
225 }
226 break;
227
229 {
230 m_bPalette = false;
232 m_aLayout.IsMsbFirst = false; // doesn't matter
233
234 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::RGB_BLUE,
235 /* 1 */ rendering::ColorComponentTag::RGB_GREEN,
236 /* 2 */ rendering::ColorComponentTag::RGB_RED,
237 /* 3 */ rendering::ColorComponentTag::ALPHA };
238
239 m_aComponentBitCounts = { /* 0 */ 8,
240 /* 1 */ 8,
241 /* 2 */ 8,
242 /* 3 */ 8 };
243
244 m_nRedIndex = 2;
245 m_nGreenIndex = 1;
246 m_nBlueIndex = 0;
247 m_nAlphaIndex = 3;
248 }
249 break;
250
252 {
253 m_bPalette = false;
255 m_aLayout.IsMsbFirst = false; // doesn't matter
256
257 m_aComponentTags = { /* 0 */ rendering::ColorComponentTag::RGB_RED,
258 /* 1 */ rendering::ColorComponentTag::RGB_GREEN,
259 /* 2 */ rendering::ColorComponentTag::RGB_BLUE,
260 /* 3 */ rendering::ColorComponentTag::ALPHA };
261
262 m_aComponentBitCounts = { /* 0 */ 8,
263 /* 1 */ 8,
264 /* 2 */ 8,
265 /* 3 */ 8 };
266
267 m_nRedIndex = 0;
268 m_nGreenIndex = 1;
269 m_nBlueIndex = 2;
270 m_nAlphaIndex = 3;
271 }
272 break;
273
275 m_bPalette = false;
277 m_aLayout.IsMsbFirst = false; // doesn't matter
281 break;
282
283 default:
284 OSL_FAIL( "unsupported bitmap format" );
285 break;
286 }
287
288 if( m_bPalette )
289 {
290 m_aComponentTags = { rendering::ColorComponentTag::INDEX };
291
293
294 m_nIndexIndex = 0;
295 }
296
298 if( !m_aBmpEx.IsAlpha() )
299 return;
300
301 // TODO(P1): need to interleave alpha with bitmap data -
302 // won't fuss with less-than-8 bit for now
303 m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
304
305 // check whether alpha goes in front or behind the
306 // bitcount sequence. If pixel format is little endian,
307 // put it behind all the other channels. If it's big
308 // endian, put it in front (because later, the actual data
309 // always gets written after the pixel data)
310
311 // TODO(Q1): slight catch - in the case of the
312 // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha
313 // channels might happen!
314 m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
315 m_aComponentTags.getArray()[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
316
317 m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1);
318 m_aComponentBitCounts.getArray()[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1;
319
320 // always add a full byte to the pixel size, otherwise
321 // pixel packing hell breaks loose.
323
324 // adapt scanline parameters
325 const Size aSize = m_aBitmap.GetSizePixel();
326 m_aLayout.ScanLineBytes =
327 m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8;
328}
329
331{
332}
333
334// XBitmap
335geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize()
336{
337 SolarMutexGuard aGuard;
339}
340
342{
343 SolarMutexGuard aGuard;
344 return m_aBmpEx.IsAlpha();
345}
346
347uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize,
348 sal_Bool beFast )
349{
350 SolarMutexGuard aGuard;
351
352 BitmapEx aNewBmp( m_aBitmap );
354 return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) );
355}
356
357// XIntegerReadOnlyBitmap
358uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout,
359 const geometry::IntegerRectangle2D& rect )
360{
361 SolarMutexGuard aGuard;
362
363 bitmapLayout = getMemoryLayout();
364
365 const ::tools::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
366 if( aRequestedArea.IsEmpty() )
367 return uno::Sequence< sal_Int8 >();
368
369 // Invalid/empty bitmap: no data available
370 if( !m_pBmpAcc )
371 throw lang::IndexOutOfBoundsException();
372 if( m_aBmpEx.IsAlpha() && !m_pAlphaAcc )
373 throw lang::IndexOutOfBoundsException();
374
375 if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 ||
376 aRequestedArea.Right() > m_pBmpAcc->Width() ||
377 aRequestedArea.Bottom() > m_pBmpAcc->Height() )
378 {
379 throw lang::IndexOutOfBoundsException();
380 }
381
382 uno::Sequence< sal_Int8 > aRet;
383 tools::Rectangle aRequestedBytes( aRequestedArea );
384
385 // adapt to byte boundaries
386 aRequestedBytes.SetLeft( aRequestedArea.Left()*m_nBitsPerOutputPixel/8 );
387 aRequestedBytes.SetRight( (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8 );
388
389 // copy stuff to output sequence
390 aRet.realloc(aRequestedBytes.getOpenWidth()*aRequestedBytes.getOpenHeight());
391 sal_Int8* pOutBuf = aRet.getArray();
392
393 bitmapLayout.ScanLines = aRequestedBytes.getOpenHeight();
394 bitmapLayout.ScanLineBytes =
395 bitmapLayout.ScanLineStride= aRequestedBytes.getOpenWidth();
396
397 sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
399 {
400 pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getOpenHeight()-1);
401 nScanlineStride *= -1;
402 }
403
404 if( !m_aBmpEx.IsAlpha() )
405 {
407 OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
408
409 // can return bitmap data as-is
410 for( tools::Long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y )
411 {
412 Scanline pScan = pBmpAcc->GetScanline(y);
413 memcpy(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getOpenWidth());
414 pOutBuf += nScanlineStride;
415 }
416 }
417 else
418 {
421 OSL_ENSURE(pBmpAcc,"Invalid bmp read access");
422 OSL_ENSURE(pAlphaAcc,"Invalid alpha read access");
423
424 // interleave alpha with bitmap data - note, bitcount is
425 // always integer multiple of 8
426 OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0,
427 "Transparent bitmap bitcount not integer multiple of 8" );
428
429 for( tools::Long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y )
430 {
431 sal_Int8* pOutScan = pOutBuf;
432
433 if( m_nBitsPerInputPixel < 8 )
434 {
435 // input less than a byte - copy via GetPixel()
436 for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
437 {
438 *pOutScan++ = pBmpAcc->GetPixelIndex(y,x);
439 // vcl used to store transparency. Now it stores alpha. But we need the UNO
440 // interface to still preserve the old interface.
441 *pOutScan++ = 255 - pAlphaAcc->GetPixelIndex(y,x);
442 }
443 }
444 else
445 {
446 const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
447 const tools::Long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
448 Scanline pScan = pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
449 Scanline pScanlineAlpha = pAlphaAcc->GetScanline( y );
450
451 // input integer multiple of byte - copy directly
452 for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
453 {
454 for( tools::Long i=0; i<nNonAlphaBytes; ++i )
455 *pOutScan++ = *pScan++;
456 // vcl used to store transparency. Now it stores alpha. But we need the UNO
457 // interface to still preserve the old interface.
458 *pOutScan++ = 255 - pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
459 }
460 }
461
462 pOutBuf += nScanlineStride;
463 }
464 }
465
466 return aRet;
467}
468
469uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
470 const geometry::IntegerPoint2D& pos )
471{
472 SolarMutexGuard aGuard;
473
474 bitmapLayout = getMemoryLayout();
475
476 // Invalid/empty bitmap: no data available
477 if( !m_pBmpAcc )
478 throw lang::IndexOutOfBoundsException();
479 if( m_aBmpEx.IsAlpha() && !m_pAlphaAcc )
480 throw lang::IndexOutOfBoundsException();
481
482 if( pos.X < 0 || pos.Y < 0 ||
483 pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() )
484 {
485 throw lang::IndexOutOfBoundsException();
486 }
487
488 uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8);
489 sal_Int8* pOutBuf = aRet.getArray();
490
491 // copy stuff to output sequence
492 bitmapLayout.ScanLines = 1;
493 bitmapLayout.ScanLineBytes =
494 bitmapLayout.ScanLineStride= aRet.getLength();
495
496 const tools::Long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 );
497 if( !m_aBmpEx.IsAlpha() )
498 {
500 assert(pBmpAcc && "Invalid bmp read access");
501
502 // can return bitmap data as-is
503 Scanline pScan = pBmpAcc->GetScanline(pos.Y);
504 memcpy(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() );
505 }
506 else
507 {
510 assert(pBmpAcc && "Invalid bmp read access");
511 assert(pAlphaAcc && "Invalid alpha read access");
512
513 // interleave alpha with bitmap data - note, bitcount is
514 // always integer multiple of 8
515 assert((m_nBitsPerOutputPixel & 0x07) == 0 &&
516 "Transparent bitmap bitcount not integer multiple of 8" );
517
518 if( m_nBitsPerInputPixel < 8 )
519 {
520 // input less than a byte - copy via GetPixel()
521 *pOutBuf++ = pBmpAcc->GetPixelIndex(pos.Y,pos.X);
522 // vcl used to store transparency. Now it stores alpha. But we need the UNO
523 // interface to still preserve the old interface.
524 *pOutBuf = 255 - 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 // vcl used to store transparency. Now it stores alpha. But we need the UNO
535 // interface to still preserve the old interface.
536 *pOutBuf++ = 255 - pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
537 }
538 }
539
540 return aRet;
541}
542
543uno::Reference< rendering::XBitmapPalette > VclCanvasBitmap::getPalette()
544{
545 SolarMutexGuard aGuard;
546
547 uno::Reference< XBitmapPalette > aRet;
548 if( m_bPalette )
549 aRet.set(this);
550
551 return aRet;
552}
553
554rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout()
555{
556 SolarMutexGuard aGuard;
557
558 rendering::IntegerBitmapLayout aLayout( m_aLayout );
559
560 // only set references to self on separate copy of
561 // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have
562 // a circular reference!
563 if( m_bPalette )
564 aLayout.Palette.set( this );
565
566 aLayout.ColorSpace.set( this );
567
568 return aLayout;
569}
570
572{
573 SolarMutexGuard aGuard;
574
575 if( !m_pBmpAcc )
576 return 0;
577
579}
580
581sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex )
582{
583 SolarMutexGuard aGuard;
584
585 const sal_uInt16 nCount( m_pBmpAcc ?
587 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
588 if( nIndex < 0 || nIndex >= nCount )
589 throw lang::IndexOutOfBoundsException("Palette index out of range",
590 static_cast<rendering::XBitmapPalette*>(this));
591
592 const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<sal_uInt16>(nIndex));
593 o_entry.realloc(3);
594 double* pColor=o_entry.getArray();
595 pColor[0] = aCol.GetRed();
596 pColor[1] = aCol.GetGreen();
597 pColor[2] = aCol.GetBlue();
598
599 return true; // no palette transparency here.
600}
601
602sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex )
603{
604 SolarMutexGuard aGuard;
605
606 const sal_uInt16 nCount( m_pBmpAcc ?
608
609 OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range");
610 if( nIndex < 0 || nIndex >= nCount )
611 throw lang::IndexOutOfBoundsException("Palette index out of range",
612 static_cast<rendering::XBitmapPalette*>(this));
613
614 return false; // read-only implementation
615}
616
617uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( )
618{
619 // this is the method from XBitmapPalette. Return palette color
620 // space here
621 static uno::Reference<rendering::XColorSpace> gColorSpace = vcl::unotools::createStandardColorSpace();
622 return gColorSpace;
623}
624
626{
627 return rendering::ColorSpaceType::RGB;
628}
629
630uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( )
631{
632 SolarMutexGuard aGuard;
633 return m_aComponentTags;
634}
635
637{
638 return rendering::RenderingIntent::PERCEPTUAL;
639}
640
641uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( )
642{
643 return uno::Sequence< ::beans::PropertyValue >();
644}
645
646uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor,
647 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
648{
649 // TODO(P3): if we know anything about target
650 // colorspace, this can be greatly sped up
651 uno::Sequence<rendering::ARGBColor> aIntermediate(
652 convertToARGB(deviceColor));
653 return targetColorSpace->convertFromARGB(aIntermediate);
654}
655
656uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor )
657{
658 SolarMutexGuard aGuard;
659
660 const std::size_t nLen( deviceColor.getLength() );
661 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
662 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
663 "number of channels no multiple of pixel element count",
664 static_cast<rendering::XBitmapPalette*>(this), 01);
665
666 uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel);
667 rendering::RGBColor* pOut( aRes.getArray() );
668
669 if( m_bPalette )
670 {
671 OSL_ENSURE(m_nIndexIndex != -1,
672 "Invalid color channel indices");
674 "Unable to get BitmapAccess");
675
676 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
677 {
679 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
680
681 // TODO(F3): Convert result to sRGB color space
682 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
683 toDoubleColor(aCol.GetGreen()),
684 toDoubleColor(aCol.GetBlue()));
685 }
686 }
687 else
688 {
689 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
690 "Invalid color channel indices");
691
692 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
693 {
694 // TODO(F3): Convert result to sRGB color space
695 *pOut++ = rendering::RGBColor(
696 deviceColor[i+m_nRedIndex],
697 deviceColor[i+m_nGreenIndex],
698 deviceColor[i+m_nBlueIndex]);
699 }
700 }
701
702 return aRes;
703}
704
705uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor )
706{
707 SolarMutexGuard aGuard;
708
709 const std::size_t nLen( deviceColor.getLength() );
710 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
711 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
712 "number of channels no multiple of pixel element count",
713 static_cast<rendering::XBitmapPalette*>(this), 01);
714
715 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
716 rendering::ARGBColor* pOut( aRes.getArray() );
717
718 if( m_bPalette )
719 {
720 OSL_ENSURE(m_nIndexIndex != -1,
721 "Invalid color channel indices");
723 "Unable to get BitmapAccess");
724
725 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
726 {
728 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
729
730 // TODO(F3): Convert result to sRGB color space
731 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
732 *pOut++ = rendering::ARGBColor(nAlpha,
733 toDoubleColor(aCol.GetRed()),
734 toDoubleColor(aCol.GetGreen()),
735 toDoubleColor(aCol.GetBlue()));
736 }
737 }
738 else
739 {
740 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
741 "Invalid color channel indices");
742
743 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
744 {
745 // TODO(F3): Convert result to sRGB color space
746 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
747 *pOut++ = rendering::ARGBColor(
748 nAlpha,
749 deviceColor[i+m_nRedIndex],
750 deviceColor[i+m_nGreenIndex],
751 deviceColor[i+m_nBlueIndex]);
752 }
753 }
754
755 return aRes;
756}
757
758uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor )
759{
760 SolarMutexGuard aGuard;
761
762 const std::size_t nLen( deviceColor.getLength() );
763 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
764 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
765 "number of channels no multiple of pixel element count",
766 static_cast<rendering::XBitmapPalette*>(this), 01);
767
768 uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel);
769 rendering::ARGBColor* pOut( aRes.getArray() );
770
771 if( m_bPalette )
772 {
773 OSL_ENSURE(m_nIndexIndex != -1,
774 "Invalid color channel indices");
776 "Unable to get BitmapAccess");
777
778 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
779 {
781 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
782
783 // TODO(F3): Convert result to sRGB color space
784 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
785 *pOut++ = rendering::ARGBColor(nAlpha,
786 nAlpha*toDoubleColor(aCol.GetRed()),
787 nAlpha*toDoubleColor(aCol.GetGreen()),
788 nAlpha*toDoubleColor(aCol.GetBlue()));
789 }
790 }
791 else
792 {
793 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
794 "Invalid color channel indices");
795
796 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
797 {
798 // TODO(F3): Convert result to sRGB color space
799 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
800 *pOut++ = rendering::ARGBColor(
801 nAlpha,
802 nAlpha*deviceColor[i+m_nRedIndex],
803 nAlpha*deviceColor[i+m_nGreenIndex],
804 nAlpha*deviceColor[i+m_nBlueIndex]);
805 }
806 }
807
808 return aRes;
809}
810
811uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor )
812{
813 SolarMutexGuard aGuard;
814
815 const std::size_t nLen( rgbColor.getLength() );
816 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
817
818 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
819 double* pColors=aRes.getArray();
820
821 if( m_bPalette )
822 {
823 for( const auto& rIn : rgbColor )
824 {
826 BitmapColor(toByteColor(rIn.Red),
827 toByteColor(rIn.Green),
828 toByteColor(rIn.Blue)));
829 if( m_nAlphaIndex != -1 )
830 pColors[m_nAlphaIndex] = 1.0;
831
832 pColors += nComponentsPerPixel;
833 }
834 }
835 else
836 {
837 for( const auto& rIn : rgbColor )
838 {
839 pColors[m_nRedIndex] = rIn.Red;
840 pColors[m_nGreenIndex] = rIn.Green;
841 pColors[m_nBlueIndex] = rIn.Blue;
842 if( m_nAlphaIndex != -1 )
843 pColors[m_nAlphaIndex] = 1.0;
844
845 pColors += nComponentsPerPixel;
846 }
847 }
848 return aRes;
849}
850
851uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
852{
853 SolarMutexGuard aGuard;
854
855 const std::size_t nLen( rgbColor.getLength() );
856 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
857
858 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
859 double* pColors=aRes.getArray();
860
861 if( m_bPalette )
862 {
863 for( const auto& rIn : rgbColor )
864 {
866 BitmapColor(toByteColor(rIn.Red),
867 toByteColor(rIn.Green),
868 toByteColor(rIn.Blue)));
869 if( m_nAlphaIndex != -1 )
870 pColors[m_nAlphaIndex] = rIn.Alpha;
871
872 pColors += nComponentsPerPixel;
873 }
874 }
875 else
876 {
877 for( const auto& rIn : rgbColor )
878 {
879 pColors[m_nRedIndex] = rIn.Red;
880 pColors[m_nGreenIndex] = rIn.Green;
881 pColors[m_nBlueIndex] = rIn.Blue;
882 if( m_nAlphaIndex != -1 )
883 pColors[m_nAlphaIndex] = rIn.Alpha;
884
885 pColors += nComponentsPerPixel;
886 }
887 }
888 return aRes;
889}
890
891uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor )
892{
893 SolarMutexGuard aGuard;
894
895 const std::size_t nLen( rgbColor.getLength() );
896 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
897
898 uno::Sequence< double > aRes(nLen*nComponentsPerPixel);
899 double* pColors=aRes.getArray();
900
901 if( m_bPalette )
902 {
903 for( const auto& rIn : rgbColor )
904 {
905 const double nAlpha( rIn.Alpha );
907 BitmapColor(toByteColor(rIn.Red / nAlpha),
908 toByteColor(rIn.Green / nAlpha),
909 toByteColor(rIn.Blue / nAlpha)));
910 if( m_nAlphaIndex != -1 )
911 pColors[m_nAlphaIndex] = nAlpha;
912
913 pColors += nComponentsPerPixel;
914 }
915 }
916 else
917 {
918 for( const auto& rIn : rgbColor )
919 {
920 const double nAlpha( rIn.Alpha );
921 pColors[m_nRedIndex] = rIn.Red / nAlpha;
922 pColors[m_nGreenIndex] = rIn.Green / nAlpha;
923 pColors[m_nBlueIndex] = rIn.Blue / nAlpha;
924 if( m_nAlphaIndex != -1 )
925 pColors[m_nAlphaIndex] = nAlpha;
926
927 pColors += nComponentsPerPixel;
928 }
929 }
930 return aRes;
931}
932
934{
935 SolarMutexGuard aGuard;
937}
938
939uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( )
940{
941 SolarMutexGuard aGuard;
943}
944
946{
947 return util::Endianness::LITTLE;
948}
949
950uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
951 const uno::Reference< ::rendering::XColorSpace >& targetColorSpace )
952{
953 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
954 {
955 SolarMutexGuard aGuard;
956
957 const std::size_t nLen( deviceColor.getLength() );
958 const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
959 ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0,
960 "number of channels no multiple of pixel element count",
961 static_cast<rendering::XBitmapPalette*>(this), 01);
962
963 uno::Sequence<double> aRes(nLen);
964 double* pOut( aRes.getArray() );
965
966 if( m_bPalette )
967 {
968 OSL_ENSURE(m_nIndexIndex != -1,
969 "Invalid color channel indices");
971 "Unable to get BitmapAccess");
972
973 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
974 {
976 sal::static_int_cast<sal_uInt16>(deviceColor[i+m_nIndexIndex]));
977
978 // TODO(F3): Convert result to sRGB color space
979 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
980 *pOut++ = toDoubleColor(aCol.GetRed());
981 *pOut++ = toDoubleColor(aCol.GetGreen());
982 *pOut++ = toDoubleColor(aCol.GetBlue());
983 *pOut++ = nAlpha;
984 }
985 }
986 else
987 {
988 OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1,
989 "Invalid color channel indices");
990
991 for( std::size_t i=0; i<nLen; i+=nComponentsPerPixel )
992 {
993 // TODO(F3): Convert result to sRGB color space
994 const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 );
995 *pOut++ = deviceColor[i+m_nRedIndex];
996 *pOut++ = deviceColor[i+m_nGreenIndex];
997 *pOut++ = deviceColor[i+m_nBlueIndex];
998 *pOut++ = nAlpha;
999 }
1000 }
1001
1002 return aRes;
1003 }
1004 else
1005 {
1006 // TODO(P3): if we know anything about target
1007 // colorspace, this can be greatly sped up
1008 uno::Sequence<rendering::ARGBColor> aIntermediate(
1009 convertIntegerToARGB(deviceColor));
1010 return targetColorSpace->convertFromARGB(aIntermediate);
1011 }
1012}
1013
1014uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1015 const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace )
1016{
1017 if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
1018 {
1019 // it's us, so simply pass-through the data
1020 return deviceColor;
1021 }
1022 else
1023 {
1024 // TODO(P3): if we know anything about target
1025 // colorspace, this can be greatly sped up
1026 uno::Sequence<rendering::ARGBColor> aIntermediate(
1027 convertIntegerToARGB(deviceColor));
1028 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1029 }
1030}
1031
1032uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1033{
1034 SolarMutexGuard aGuard;
1035
1036 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1037 const std::size_t nLen( deviceColor.getLength() );
1038 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1039
1040 uno::Sequence< rendering::RGBColor > aRes(nNumColors);
1041 rendering::RGBColor* pOut( aRes.getArray() );
1042
1044 ENSURE_OR_THROW(pBmpAcc,
1045 "Unable to get BitmapAccess");
1046
1047 if( m_aBmpEx.IsAlpha() )
1048 {
1049 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1050 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1051 {
1052 // if palette, index is guaranteed to be 8 bit
1053 const BitmapColor aCol =
1054 m_bPalette ?
1055 pBmpAcc->GetPaletteColor(*pIn) :
1056 pBmpAcc->GetPixelFromData(pIn,0);
1057
1058 // TODO(F3): Convert result to sRGB color space
1059 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1060 toDoubleColor(aCol.GetGreen()),
1061 toDoubleColor(aCol.GetBlue()));
1062 // skips alpha
1063 pIn += nBytesPerPixel;
1064 }
1065 }
1066 else
1067 {
1068 for( sal_Int32 i=0; i<nNumColors; ++i )
1069 {
1070 const BitmapColor aCol =
1071 m_bPalette ?
1072 pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
1073 pBmpAcc->GetPixelFromData(pIn, i);
1074
1075 // TODO(F3): Convert result to sRGB color space
1076 *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
1077 toDoubleColor(aCol.GetGreen()),
1078 toDoubleColor(aCol.GetBlue()));
1079 }
1080 }
1081
1082 return aRes;
1083}
1084
1085uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1086{
1087 SolarMutexGuard aGuard;
1088
1089 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1090 const std::size_t nLen( deviceColor.getLength() );
1091 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1092
1093 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1094 rendering::ARGBColor* pOut( aRes.getArray() );
1095
1097 ENSURE_OR_THROW(pBmpAcc,
1098 "Unable to get BitmapAccess");
1099
1100 if( m_aBmpEx.IsAlpha() )
1101 {
1102 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1103 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
1104 for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
1105 {
1106 // if palette, index is guaranteed to be 8 bit
1107 const BitmapColor aCol =
1108 m_bPalette ?
1109 pBmpAcc->GetPaletteColor(*pIn) :
1110 pBmpAcc->GetPixelFromData(pIn,0);
1111
1112 // TODO(F3): Convert result to sRGB color space
1113 *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(pIn[nNonAlphaBytes]),
1114 toDoubleColor(aCol.GetRed()),
1115 toDoubleColor(aCol.GetGreen()),
1116 toDoubleColor(aCol.GetBlue()));
1117 pIn += nBytesPerPixel;
1118 }
1119 }
1120 else
1121 {
1122 for( sal_Int32 i=0; i<nNumColors; ++i )
1123 {
1124 const BitmapColor aCol =
1125 m_bPalette ?
1126 pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
1127 pBmpAcc->GetPixelFromData(pIn, i);
1128
1129 // TODO(F3): Convert result to sRGB color space
1130 *pOut++ = rendering::ARGBColor(1.0,
1131 toDoubleColor(aCol.GetRed()),
1132 toDoubleColor(aCol.GetGreen()),
1133 toDoubleColor(aCol.GetBlue()));
1134 }
1135 }
1136
1137 return aRes;
1138}
1139
1140uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1141{
1142 SolarMutexGuard aGuard;
1143
1144 const sal_uInt8* pIn( reinterpret_cast<const sal_uInt8*>(deviceColor.getConstArray()) );
1145 const std::size_t nLen( deviceColor.getLength() );
1146 const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel);
1147
1148 uno::Sequence< rendering::ARGBColor > aRes(nNumColors);
1149 rendering::ARGBColor* pOut( aRes.getArray() );
1150
1152 ENSURE_OR_THROW(pBmpAcc,
1153 "Unable to get BitmapAccess");
1154
1155 if( m_aBmpEx.IsAlpha() )
1156 {
1157 const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 );
1158 const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8);
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(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:77
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
const AlphaMask & GetAlphaMask() const
Definition: bitmapex.hxx:71
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:305
bool IsAlpha() const
Definition: BitmapEx.cxx:207
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