20 #include <com/sun/star/geometry/RealSize2D.hpp>
21 #include <com/sun/star/geometry/IntegerSize2D.hpp>
22 #include <com/sun/star/geometry/IntegerPoint2D.hpp>
23 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
25 #include <com/sun/star/rendering/ColorSpaceType.hpp>
26 #include <com/sun/star/rendering/RenderingIntent.hpp>
27 #include <com/sun/star/rendering/VolatileContentDestroyedException.hpp>
28 #include <com/sun/star/rendering/XBitmap.hpp>
29 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
30 #include <com/sun/star/rendering/ColorComponentTag.hpp>
43 #include <canvasbitmap.hxx>
53 SAL_INFO(
"vcl.helper",
"vcl::unotools::xBitmapFromBitmapEx()" );
60 bool equalsLayout(
const rendering::IntegerBitmapLayout& rLHS,
61 const rendering::IntegerBitmapLayout& rRHS )
64 rLHS.ScanLineBytes == rRHS.ScanLineBytes &&
65 rLHS.ScanLineStride == rRHS.ScanLineStride &&
66 rLHS.PlaneStride == rRHS.PlaneStride &&
67 rLHS.ColorSpace == rRHS.ColorSpace &&
68 rLHS.Palette == rRHS.Palette &&
69 rLHS.IsMsbFirst == rRHS.IsMsbFirst;
71 bool readBmp( sal_Int32 nWidth,
73 const rendering::IntegerBitmapLayout& rLayout,
74 const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap,
78 rendering::IntegerBitmapLayout aCurrLayout;
79 geometry::IntegerRectangle2D aRect;
80 uno::Sequence<sal_Int8> aPixelData;
81 uno::Sequence<rendering::RGBColor> aRGBColors;
82 uno::Sequence<rendering::ARGBColor> aARGBColors;
84 for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 )
86 aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1;
89 aPixelData = xInputBitmap->getData(aCurrLayout,aRect);
91 catch( rendering::VolatileContentDestroyedException& )
96 if( !equalsLayout(aCurrLayout, rLayout) )
99 Scanline pScanline = rWriteAcc->GetScanline( aRect.Y1 );
100 if( rAlphaAcc.
get() )
102 Scanline pScanlineAlpha = rAlphaAcc->GetScanline( aRect.Y1 );
104 aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData);
106 if( rWriteAcc->HasPalette() )
108 for( sal_Int32 x=0;
x<nWidth; ++
x )
110 const rendering::ARGBColor& rColor=aARGBColors[
x];
111 rWriteAcc->SetPixelOnData( pScanline, x,
112 BitmapColor(static_cast<sal_uInt8>(rWriteAcc->GetBestPaletteIndex(
116 rAlphaAcc->SetPixelOnData( pScanlineAlpha, x,
122 for( sal_Int32 x=0;
x<nWidth; ++
x )
124 const rendering::ARGBColor& rColor=aARGBColors[
x];
125 rWriteAcc->SetPixelOnData( pScanline, x,
129 rAlphaAcc->SetPixelOnData( pScanlineAlpha, x,
137 aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData);
138 if( rWriteAcc->HasPalette() )
140 for( sal_Int32 x=0;
x<nWidth; ++
x )
142 const rendering::RGBColor& rColor=aRGBColors[
x];
143 rWriteAcc->SetPixelOnData( pScanline, x,
144 BitmapColor(static_cast<sal_uInt8>(rWriteAcc->GetBestPaletteIndex(
152 for( sal_Int32 x=0;
x<nWidth; ++
x )
154 const rendering::RGBColor& rColor=aRGBColors[
x];
155 rWriteAcc->SetPixelOnData( pScanline, x,
170 SAL_INFO(
"vcl.helper",
"vcl::unotools::bitmapExFromXBitmap()" );
172 if( !xInputBitmap.is() )
186 for(
int i=0;
i<10; ++
i )
189 sal_Int32 nAlphaDepth=0;
190 const rendering::IntegerBitmapLayout aLayout(
191 xInputBitmap->getMemoryLayout());
193 OSL_ENSURE(aLayout.ColorSpace.is(),
194 "Cannot convert image without color space!");
195 if( !aLayout.ColorSpace.is() )
198 nDepth = aLayout.ColorSpace->getBitsPerPixel();
200 if( xInputBitmap->hasAlpha() )
203 const uno::Sequence<sal_Int8> aTags(
204 aLayout.ColorSpace->getComponentTags() );
205 const sal_Int8* pStart(aTags.getConstArray());
206 const std::size_t nLen(aTags.getLength());
209 const std::ptrdiff_t nAlphaIndex =
210 std::find(pStart,pEnd,
211 rendering::ColorComponentTag::ALPHA) - pStart;
213 if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) )
215 nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1;
216 nDepth -= nAlphaDepth;
221 if( aLayout.Palette.is() )
223 uno::Reference< rendering::XColorSpace > xPaletteColorSpace(
224 aLayout.Palette->getColorSpace());
226 "Palette without color space");
228 const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() );
229 if( nEntryCount <= 256 )
231 if( nEntryCount <= 2 )
236 const sal_uInt16 nPaletteEntries(
237 sal::static_int_cast<sal_uInt16>(
238 std::min(sal_Int32(255), nEntryCount)));
242 uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette );
243 uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() );
245 uno::Sequence<double> aPaletteEntry;
246 for( sal_uInt16 j=0; j<nPaletteEntries; ++j )
248 if( !xPalette->getIndex(aPaletteEntry,j) &&
253 uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry);
255 "Palette returned more or less than one entry");
256 const rendering::RGBColor& rColor=aColors[0];
264 const ::Size aPixelSize(
272 auto eAlphaPixelFormat =
278 aLayout.Palette.is() ? &aPalette : nullptr );
281 aAlpha =
Bitmap(aPixelSize,
284 sal::static_int_cast<sal_uInt16>(1 << nAlphaDepth)) );
292 "Cannot get write access to bitmap");
294 const sal_Int32 nWidth(aPixelSize.Width());
295 const sal_Int32 nHeight(aPixelSize.Height());
297 if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap,
298 pWriteAccess,pAlphaWriteAccess) )
303 return ::BitmapEx( aBitmap,
306 return ::BitmapEx( aBitmap );
315 return geometry::RealSize2D( rSize.
Width(),
321 return Size( static_cast<tools::Long>(rSize.Width + .5),
322 static_cast<tools::Long>(rSize.Height + .5) );
343 return ::Point( rPoint.
getX(),
354 return ::tools::Rectangle( rRect.
getMinX(),
388 if (rRect.IsWidthEmpty() && rRect.IsHeightEmpty())
392 rRect.IsWidthEmpty() ? rRect.Left() : rRect.Right(),
393 rRect.IsHeightEmpty() ? rRect.Top() : rRect.Bottom() );
398 return geometry::IntegerSize2D( rSize.
Width(),
404 return Size( rSize.Width,
410 return Point( rPoint.X,
417 rRectangle.X2, rRectangle.Y2 );
422 class StandardColorSpace :
public cppu::WeakImplHelper< css::rendering::XColorSpace >
427 virtual ::sal_Int8 SAL_CALL
getType( )
override
429 return rendering::ColorSpaceType::RGB;
431 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( )
override
435 virtual ::sal_Int8 SAL_CALL getRenderingIntent( )
override
437 return rendering::RenderingIntent::PERCEPTUAL;
439 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( )
override
441 return uno::Sequence< beans::PropertyValue >();
443 virtual uno::Sequence< double > SAL_CALL convertColorSpace(
const uno::Sequence< double >& deviceColor,
444 const uno::Reference< rendering::XColorSpace >& targetColorSpace )
override
448 uno::Sequence<rendering::ARGBColor> aIntermediate(
449 convertToARGB(deviceColor));
450 return targetColorSpace->convertFromARGB(aIntermediate);
452 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB(
const uno::Sequence< double >& deviceColor )
override
454 const double* pIn( deviceColor.getConstArray() );
455 const std::size_t nLen( deviceColor.getLength() );
457 "number of channels no multiple of 4",
458 static_cast<rendering::XColorSpace*>(
this), 0);
460 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
461 rendering::RGBColor*
pOut( aRes.getArray() );
462 for( std::size_t i=0;
i<nLen;
i+=4 )
464 *
pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
469 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB(
const uno::Sequence< double >& deviceColor )
override
471 const double* pIn( deviceColor.getConstArray() );
472 const std::size_t nLen( deviceColor.getLength() );
474 "number of channels no multiple of 4",
475 static_cast<rendering::XColorSpace*>(
this), 0);
477 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
478 rendering::ARGBColor*
pOut( aRes.getArray() );
479 for( std::size_t i=0;
i<nLen;
i+=4 )
481 *
pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
486 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB(
const uno::Sequence< double >& deviceColor )
override
488 const double* pIn( deviceColor.getConstArray() );
489 const std::size_t nLen( deviceColor.getLength() );
491 "number of channels no multiple of 4",
492 static_cast<rendering::XColorSpace*>(
this), 0);
494 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
495 rendering::ARGBColor*
pOut( aRes.getArray() );
496 for( std::size_t i=0;
i<nLen;
i+=4 )
498 *
pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
503 virtual uno::Sequence< double > SAL_CALL convertFromRGB(
const uno::Sequence< rendering::RGBColor >& rgbColor )
override
505 const std::size_t nLen( rgbColor.getLength() );
507 uno::Sequence< double > aRes(nLen*4);
508 double* pColors=aRes.getArray();
509 for(
const auto& rIn : rgbColor )
511 *pColors++ = rIn.Red;
512 *pColors++ = rIn.Green;
513 *pColors++ = rIn.Blue;
518 virtual uno::Sequence< double > SAL_CALL convertFromARGB(
const uno::Sequence< rendering::ARGBColor >& rgbColor )
override
520 const std::size_t nLen( rgbColor.getLength() );
522 uno::Sequence< double > aRes(nLen*4);
523 double* pColors=aRes.getArray();
524 for(
const auto& rIn : rgbColor )
526 *pColors++ = rIn.Red;
527 *pColors++ = rIn.Green;
528 *pColors++ = rIn.Blue;
529 *pColors++ = rIn.Alpha;
533 virtual uno::Sequence< double > SAL_CALL convertFromPARGB(
const uno::Sequence< rendering::ARGBColor >& rgbColor )
override
535 const std::size_t nLen( rgbColor.getLength() );
537 uno::Sequence< double > aRes(nLen*4);
538 double* pColors=aRes.getArray();
539 for(
const auto& rIn : rgbColor )
541 *pColors++ = rIn.Red/rIn.Alpha;
542 *pColors++ = rIn.Green/rIn.Alpha;
543 *pColors++ = rIn.Blue/rIn.Alpha;
544 *pColors++ = rIn.Alpha;
550 StandardColorSpace() : m_aComponentTags(4)
552 sal_Int8* pTags = m_aComponentTags.getArray();
553 pTags[0] = rendering::ColorComponentTag::RGB_RED;
554 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
555 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
556 pTags[3] = rendering::ColorComponentTag::ALPHA;
563 return new StandardColorSpace();
568 uno::Sequence< double > aRet(4);
569 double* pRet = aRet.getArray();
582 "color must have 4 channels" );
596 const uno::Reference< rendering::XColorSpace >& xColorSpace )
598 uno::Sequence<rendering::ARGBColor>
aSeq(1);
599 aSeq[0] = rendering::ARGBColor(
605 return xColorSpace->convertFromARGB(aSeq);
609 const uno::Sequence< double >& rColor,
610 const uno::Reference< rendering::XColorSpace >& xColorSpace )
612 const rendering::ARGBColor aARGBColor(
613 xColorSpace->convertToARGB(rColor)[0]);
sal_uInt8 GetAlpha() const
void SetEntryCount(sal_uInt16 nCount)
bool getType(BSTR name, Type &type)
sal_Int32 getMinY() const
This template handles BitmapAccess the RAII way.
sal_Int32 getMaxX() const
sal_uInt8 GetBlue() const
B2IRange fround(const B2DRange &rRange)
tools::Long FRound(double fVal)
tools::Long Width() const
#define ENSURE_ARG_OR_THROW2(c, m, ifc, arg)
void SetRed(sal_uInt8 nRed)
sal_Int32 getMinX() const
#define ENSURE_ARG_OR_THROW(c, m)
sal_uInt8 GetGreen() const
#define ENSURE_OR_THROW(c, m)
#define SAL_INFO(area, stream)
tools::Long Height() const
Sequence< sal_Int8 > aSeq
sal_Int32 getMaxY() const
static const BitmapPalette & GetGreyPalette(int nEntries)