/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
namespace
{ // TODO(Q3): move to o3tl bithacks or somesuch. A similar method is in canvas/canvastools.hxx
// Good ole HAKMEM tradition. Calc number of 1 bits in 32bit word, // unrolled loop. See e.g. Hackers Delight, p. 66
sal_Int32 bitcount( sal_uInt32 val )
{
val = val - ((val >> 1) & 0x55555555);
val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
val = (val + (val >> 4)) & 0x0F0F0F0F;
val = val + (val >> 8);
val = val + (val >> 16); return sal_Int32(val & 0x0000003F);
}
}
void VclCanvasBitmap::setComponentInfo( sal_uInt32 redShift, sal_uInt32 greenShift, sal_uInt32 blueShift )
{ // sort channels in increasing order of appearance in the pixel // (starting with the least significant bits)
sal_Int8 redPos(0);
sal_Int8 greenPos(1);
sal_Int8 bluePos(2);
BitmapScopedReadAccess& VclCanvasBitmap::getBitmapReadAccess()
{ // BitmapReadAccess is more expensive than BitmapInfoAccess, // as the latter requires also pixels, which may need converted // from the system format (and even fetched). Most calls here // need only info access, create read access only on demand. if(!m_pBmpReadAcc)
m_pBmpReadAcc.emplace(m_aBitmap); return *m_pBmpReadAcc;
}
// TODO(P1): need to interleave alpha with bitmap data - // won't fuss with less-than-8 bit for now
m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel);
// check whether alpha goes in front or behind the // bitcount sequence. If pixel format is little endian, // put it behind all the other channels. If it's big // endian, put it in front (because later, the actual data // always gets written after the pixel data)
// TODO(Q1): slight catch - in the case of the // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha // channels might happen!
m_aComponentTags.realloc(m_aComponentTags.getLength()+1);
m_aComponentTags.getArray()[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA;
// interleave alpha with bitmap data - note, bitcount is // always integer multiple of 8
OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0, "Transparent bitmap bitcount not integer multiple of 8" );
if( m_nBitsPerInputPixel < 8 )
{ // input less than a byte - copy via GetPixel() for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
{
*pOutScan++ = pBmpAcc->GetPixelIndex(y,x); // vcl used to store transparency. Now it stores alpha. But we need the UNO // interface to still preserve the old interface.
*pOutScan++ = 255 - pAlphaAcc->GetPixelIndex(y,x);
}
} else
{ const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 ); const tools::Long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes);
Scanline pScan = pBmpAcc->GetScanline(y) + nScanlineOffsetLeft;
Scanline pScanlineAlpha = pAlphaAcc->GetScanline( y );
// input integer multiple of byte - copy directly for( tools::Long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x )
{ for( tools::Long i=0; i<nNonAlphaBytes; ++i )
*pOutScan++ = *pScan++; // vcl used to store transparency. Now it stores alpha. But we need the UNO // interface to still preserve the old interface.
*pOutScan++ = 255 - pAlphaAcc->GetIndexFromData( pScanlineAlpha, x );
}
}
// interleave alpha with bitmap data - note, bitcount is // always integer multiple of 8
assert((m_nBitsPerOutputPixel & 0x07) == 0 && "Transparent bitmap bitcount not integer multiple of 8" );
if( m_nBitsPerInputPixel < 8 )
{ // input less than a byte - copy via GetPixel()
*pOutBuf++ = pBmpAcc->GetPixelIndex(pos.Y,pos.X); // vcl used to store transparency. Now it stores alpha. But we need the UNO // interface to still preserve the old interface.
*pOutBuf = 255 - pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
} else
{ const tools::Long nNonAlphaBytes( m_nBitsPerInputPixel/8 );
Scanline pScan = pBmpAcc->GetScanline(pos.Y);
// input integer multiple of byte - copy directly
memcpy(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes );
pOutBuf += nNonAlphaBytes; // vcl used to store transparency. Now it stores alpha. But we need the UNO // interface to still preserve the old interface.
*pOutBuf++ = 255 - pAlphaAcc->GetPixelIndex(pos.Y,pos.X);
}
}
// only set references to self on separate copy of // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have // a circular reference! if( m_bPalette )
aLayout.Palette.set( this );
OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range"); if( nIndex < 0 || nIndex >= nCount ) throw lang::IndexOutOfBoundsException(u"Palette index out of range"_ustr, static_cast<rendering::XBitmapPalette*>(this));
returnfalse; // read-only implementation
}
uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( )
{ // this is the method from XBitmapPalette. Return palette color // space here static uno::Reference<rendering::XColorSpace> gColorSpace = vcl::unotools::createStandardColorSpace(); return gColorSpace;
}
const std::size_t nLen( deviceColor.getLength() ); const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, "number of channels no multiple of pixel element count", static_cast<rendering::XBitmapPalette*>(this), 01);
const std::size_t nLen( deviceColor.getLength() ); const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, "number of channels no multiple of pixel element count", static_cast<rendering::XBitmapPalette*>(this), 01);
const std::size_t nLen( deviceColor.getLength() ); const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, "number of channels no multiple of pixel element count", static_cast<rendering::XBitmapPalette*>(this), 01);
const std::size_t nLen( deviceColor.getLength() ); const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength());
ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, "number of channels no multiple of pixel element count", static_cast<rendering::XBitmapPalette*>(this), 01);
return aRes;
} else
{ // TODO(P3): if we know anything about target // colorspace, this can be greatly sped up
uno::Sequence<rendering::ARGBColor> aIntermediate(
convertIntegerToARGB(deviceColor)); return targetColorSpace->convertFromARGB(aIntermediate);
}
}
uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( constuno::Sequence< ::sal_Int8 >& deviceColor, const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace )
{ if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) )
{ // it's us, so simply pass-through the data return deviceColor;
} else
{ // TODO(P3): if we know anything about target // colorspace, this can be greatly sped up
uno::Sequence<rendering::ARGBColor> aIntermediate(
convertIntegerToARGB(deviceColor)); return targetColorSpace->convertIntegerFromARGB(aIntermediate);
}
}
BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
ENSURE_OR_THROW(pBmpAcc, "Unable to get BitmapAccess");
if( m_aBmpEx.IsAlpha() )
{ const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8); for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
{ // if palette, index is guaranteed to be 8 bit const BitmapColor aCol =
m_bPalette ?
pBmpAcc->GetPaletteColor(*pIn) :
pBmpAcc->GetPixelFromData(pIn,0);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
toDoubleColor(aCol.GetGreen()),
toDoubleColor(aCol.GetBlue())); // skips alpha
pIn += nBytesPerPixel;
}
} else
{ for( sal_Int32 i=0; i<nNumColors; ++i )
{ const BitmapColor aCol =
m_bPalette ?
pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex()) :
pBmpAcc->GetPixelFromData(pIn, i);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()),
toDoubleColor(aCol.GetGreen()),
toDoubleColor(aCol.GetBlue()));
}
}
BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
ENSURE_OR_THROW(pBmpAcc, "Unable to get BitmapAccess");
if( m_aBmpEx.IsAlpha() )
{ const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 ); const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8); for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
{ // if palette, index is guaranteed to be 8 bit const BitmapColor aCol =
m_bPalette ?
pBmpAcc->GetPaletteColor(*pIn) :
pBmpAcc->GetPixelFromData(pIn,0);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(pIn[nNonAlphaBytes]),
toDoubleColor(aCol.GetRed()),
toDoubleColor(aCol.GetGreen()),
toDoubleColor(aCol.GetBlue()));
pIn += nBytesPerPixel;
}
} else
{ for( sal_Int32 i=0; i<nNumColors; ++i )
{ const BitmapColor aCol =
m_bPalette ?
pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
pBmpAcc->GetPixelFromData(pIn, i);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::ARGBColor(1.0,
toDoubleColor(aCol.GetRed()),
toDoubleColor(aCol.GetGreen()),
toDoubleColor(aCol.GetBlue()));
}
}
BitmapScopedReadAccess& pBmpAcc = getBitmapReadAccess();
ENSURE_OR_THROW(pBmpAcc, "Unable to get BitmapAccess");
if( m_aBmpEx.IsAlpha() )
{ const tools::Long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 ); const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8); for( std::size_t i=0; i<nLen; i+=nBytesPerPixel )
{ // if palette, index is guaranteed to be 8 bit const BitmapColor aCol =
m_bPalette ?
pBmpAcc->GetPaletteColor(*pIn) :
pBmpAcc->GetPixelFromData(pIn,0);
// TODO(F3): Convert result to sRGB color space constdouble nAlpha( 1.0 - toDoubleColor(pIn[nNonAlphaBytes]) );
*pOut++ = rendering::ARGBColor(nAlpha,
nAlpha*toDoubleColor(aCol.GetRed()),
nAlpha*toDoubleColor(aCol.GetGreen()),
nAlpha*toDoubleColor(aCol.GetBlue()));
pIn += nBytesPerPixel;
}
} else
{ for( sal_Int32 i=0; i<nNumColors; ++i )
{ const BitmapColor aCol =
m_bPalette ?
pBmpAcc->GetPaletteColor( pBmpAcc->GetPixelFromData( pIn, i ).GetIndex() ) :
pBmpAcc->GetPixelFromData(pIn, i);
// TODO(F3): Convert result to sRGB color space
*pOut++ = rendering::ARGBColor(1.0,
toDoubleColor(aCol.GetRed()),
toDoubleColor(aCol.GetGreen()),
toDoubleColor(aCol.GetBlue()));
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.