[Libreoffice-commits] core.git: filter/source vcl/source
Noel Grandin
noel.grandin at collabora.co.uk
Wed Feb 14 06:29:24 UTC 2018
filter/source/graphicfilter/itiff/itiff.cxx | 199 ++++++++++++++--------------
vcl/source/bitmap/BitmapTools.cxx | 38 ++++-
2 files changed, 135 insertions(+), 102 deletions(-)
New commits:
commit 6b4d3815a612b688cc5714f8b828a9cc9b109429
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date: Tue Feb 13 13:41:55 2018 +0200
use BitmapTools in TIFFReader
part of making Bitmap an internal detail of vcl.
This one is a little trickier because it constructs the palette after it
reads the pixel data, so I couldn't use RawBitmap
Change-Id: I2f501260beebb541ee451e78d551e13f182a01b1
Reviewed-on: https://gerrit.libreoffice.org/49665
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
diff --git a/filter/source/graphicfilter/itiff/itiff.cxx b/filter/source/graphicfilter/itiff/itiff.cxx
index 0449cdff7e2b..d86d2912804d 100644
--- a/filter/source/graphicfilter/itiff/itiff.cxx
+++ b/filter/source/graphicfilter/itiff/itiff.cxx
@@ -22,7 +22,7 @@
#include <vcl/FilterConfigItem.hxx>
#include <vcl/graph.hxx>
-#include <vcl/bitmapaccess.hxx>
+#include <vcl/BitmapTools.hxx>
#include <vcl/animate.hxx>
#include <tools/fract.hxx>
#include "lzwdecom.hxx"
@@ -50,13 +50,13 @@ private:
Animation aAnimation;
SvStream* pTIFF; // the TIFF file that should be read
- Bitmap aBitmap;
- Bitmap::ScopedWriteAccess xAcc;
+ std::unique_ptr<sal_uInt8[]> mpBitmap;
+ Size maBitmapPixelSize;
+ std::vector<Color> mvPalette;
+ MapMode maBitmapPrefMapMode;
+ Size maBitmapPrefSize;
sal_uInt16 nDstBitsPerPixel;
int nLargestPixelIndex;
- std::unique_ptr<AlphaMask>
- pAlphaMask;
- AlphaMask::ScopedWriteAccess xMaskAcc;
sal_uInt64 nOrigPos; // start position in pTIFF
sal_uInt64 nEndOfFile; // end of file position in pTIFF
@@ -124,7 +124,9 @@ private:
bool HasAlphaChannel() const;
- void SetPixelOnData(BitmapWriteAccess *pWriteAcc, sal_uInt8* pData, long nX, sal_uInt8 cIndex);
+ void SetPixel(long nY, long nX, sal_uInt8 cIndex);
+ void SetPixel(long nY, long nX, Color c);
+ void SetPixelAlpha(long nY, long nX, sal_uInt8 nAlpha);
public:
@@ -133,7 +135,6 @@ public:
, pTIFF(nullptr)
, nDstBitsPerPixel(0)
, nLargestPixelIndex(-1)
- , pAlphaMask(nullptr)
, nOrigPos(0)
, nEndOfFile(0)
, nDataType(0)
@@ -616,9 +617,9 @@ bool TIFFReader::ReadMap()
//if the buffer for this line didn't change, then just copy the
//previous scanline instead of painfully decoding and setting
//each pixel one by one again
- Scanline pScanline = xAcc->GetScanline(ny);
- Scanline pPrevline = xAcc->GetScanline(ny-1);
- memcpy(pScanline, pPrevline, xAcc->GetScanlineSize());
+ memcpy( mpBitmap.get() + (ny * maBitmapPixelSize.Width()) * 4,
+ mpBitmap.get() + ((ny-1) * maBitmapPixelSize.Width()) * 4,
+ maBitmapPixelSize.Width() * 4);
}
else
{
@@ -780,20 +781,38 @@ sal_uInt32 TIFFReader::GetBits( const sal_uInt8 * pSrc, sal_uInt32 nBitsPos, sal
return nRes;
}
-void TIFFReader::SetPixelOnData(BitmapWriteAccess *pWriteAcc, sal_uInt8* pData, long nX, sal_uInt8 cIndex)
+void TIFFReader::SetPixel(long nY, long nX, sal_uInt8 cIndex)
{
- pWriteAcc->SetPixelOnData(pData, nX, BitmapColor(cIndex));
+ mpBitmap[(maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3)] = cIndex;
nLargestPixelIndex = std::max<int>(nLargestPixelIndex, cIndex);
}
+void TIFFReader::SetPixel(long nY, long nX, Color c)
+{
+ auto p = mpBitmap.get() + ((maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3));
+ *p = c.GetRed();
+ p++;
+ *p = c.GetGreen();
+ p++;
+ *p = c.GetBlue();
+ if (HasAlphaChannel())
+ {
+ p++;
+ *p = 0xff; // alpha
+ }
+}
+
+void TIFFReader::SetPixelAlpha(long nY, long nX, sal_uInt8 nAlpha)
+{
+ assert(HasAlphaChannel());
+ mpBitmap[((maBitmapPixelSize.Width() * nY + nX) * 4) + 3] = nAlpha;
+}
+
bool TIFFReader::ConvertScanline(sal_Int32 nY)
{
sal_uInt32 nRed, nGreen, nBlue, ns, nVal;
sal_uInt8 nByteVal;
- BitmapWriteAccess* pAcc = xAcc.get();
- Scanline pScanLine = pAcc->GetScanline(nY);
-
if ( nDstBitsPerPixel == 24 )
{
if ( nBitsPerSample == 8 && nSamplesPerPixel >= 3 &&
@@ -801,10 +820,6 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
{
sal_uInt8* pt = getMapData(0);
- Scanline pMaskScanLine = nullptr;
- if (nSamplesPerPixel >= 4 && xMaskAcc)
- pMaskScanLine = xMaskAcc->GetScanline(nY);
-
// are the values being saved as difference?
if ( 2 == nPredictor )
{
@@ -817,11 +832,11 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
nLRed = nLRed + pt[ 0 ];
nLGreen = nLGreen + pt[ 1 ];
nLBlue = nLBlue + pt[ 2 ];
- pAcc->SetPixelOnData(pScanLine, nx, Color(nLRed, nLGreen, nLBlue));
- if (pMaskScanLine)
+ SetPixel(nY, nx, Color(nLRed, nLGreen, nLBlue));
+ if (HasAlphaChannel())
{
nLAlpha = nLAlpha + pt[ 3 ];
- xMaskAcc->SetPixelOnData(pMaskScanLine, nx, BitmapColor(~nLAlpha));
+ SetPixelAlpha(nY, nx, ~nLAlpha);
}
}
}
@@ -829,11 +844,11 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
{
for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel)
{
- pAcc->SetPixelOnData(pScanLine, nx, Color(pt[0], pt[1], pt[2]));
- if (pMaskScanLine)
+ SetPixel(nY, nx, Color(pt[0], pt[1], pt[2]));
+ if (HasAlphaChannel())
{
sal_uInt8 nAlpha = pt[3];
- xMaskAcc->SetPixelOnData(pMaskScanLine, nx, BitmapColor(~nAlpha));
+ SetPixelAlpha(nY, nx, ~nAlpha);
}
}
}
@@ -857,7 +872,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
nGreen = GetBits( getMapData(1), nx * nBitsPerSample, nBitsPerSample );
nBlue = GetBits( getMapData(2), nx * nBitsPerSample, nBitsPerSample );
}
- pAcc->SetPixelOnData(pScanLine, nx, Color(static_cast<sal_uInt8>(nRed - nMinMax), static_cast<sal_uInt8>(nGreen - nMinMax), static_cast<sal_uInt8>(nBlue - nMinMax)));
+ SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed - nMinMax), static_cast<sal_uInt8>(nGreen - nMinMax), static_cast<sal_uInt8>(nBlue - nMinMax)));
}
}
}
@@ -883,7 +898,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
nRed = 255 - static_cast<sal_uInt8>( nRed - nMinMax );
nGreen = 255 - static_cast<sal_uInt8>( nGreen - nMinMax );
nBlue = 255 - static_cast<sal_uInt8>( nBlue - nMinMax );
- pAcc->SetPixelOnData(pScanLine, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue)));
+ SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue)));
}
}
}
@@ -925,7 +940,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
nBlue = static_cast<sal_uInt8>(std::max( 0L, 255L - ( ( static_cast<sal_Int32>(nSamp[ 2 ]) + nBlack - ( static_cast<sal_Int32>(nMinSampleValue) << 1 ) ) *
255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
- pAcc->SetPixelOnData(pScanLine, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue)));
+ SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue)));
}
}
}
@@ -954,7 +969,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
{
nLast += nx == 0 ? BYTESWAP( *pt++ ) : *pt++;
- SetPixelOnData(pAcc, pScanLine, nx, nLast);
+ SetPixel(nY, nx, nLast);
}
}
else
@@ -962,7 +977,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
{
sal_uInt8 nLast = *pt++;
- SetPixelOnData(pAcc, pScanLine, nx, static_cast<sal_uInt8>( (BYTESWAP(static_cast<sal_uInt32>(nLast)) - nMinSampleValue) * nMinMax ));
+ SetPixel(nY, nx, static_cast<sal_uInt8>( (BYTESWAP(static_cast<sal_uInt32>(nLast)) - nMinSampleValue) * nMinMax ));
}
}
}
@@ -974,14 +989,14 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
{
nLast += *pt++;
- SetPixelOnData(pAcc, pScanLine, nx, nLast);
+ SetPixel(nY, nx, nLast);
}
}
else
{
for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
{
- SetPixelOnData(pAcc, pScanLine, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt++) - nMinSampleValue) * nMinMax ));
+ SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt++) - nMinSampleValue) * nMinMax ));
}
}
}
@@ -998,7 +1013,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
{
nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax;
- SetPixelOnData(pAcc, pScanLine, nx, static_cast<sal_uInt8>(nVal));
+ SetPixel(nY, nx, static_cast<sal_uInt8>(nVal));
}
}
break;
@@ -1019,28 +1034,28 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
while (nByteCount--)
{
nByteVal = *pt++;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal);
+ SetPixel(nY, nx++, nByteVal);
}
if ( nImageWidth & 7 )
{
nByteVal = *pt++;
while ( nx < nImageWidth )
{
- SetPixelOnData(pAcc, pScanLine, nx++, nByteVal & 1);
+ SetPixel(nY, nx++, nByteVal & 1);
nByteVal >>= 1;
}
}
@@ -1051,21 +1066,21 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
while (nByteCount--)
{
nByteVal = *pt++;
- SetPixelOnData(pAcc, pScanLine, nx, nByteVal & 1);
+ SetPixel(nY, nx, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, --nx, nByteVal & 1);
+ SetPixel(nY, --nx, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, --nx, nByteVal & 1);
+ SetPixel(nY, --nx, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, --nx, nByteVal & 1);
+ SetPixel(nY, --nx, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, --nx, nByteVal & 1);
+ SetPixel(nY, --nx, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, --nx, nByteVal & 1);
+ SetPixel(nY, --nx, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, --nx, nByteVal & 1);
+ SetPixel(nY, --nx, nByteVal & 1);
nByteVal >>= 1;
- SetPixelOnData(pAcc, pScanLine, --nx, nByteVal);
+ SetPixel(nY, --nx, nByteVal);
nx += 15;
}
if ( nImageWidth & 7 )
@@ -1075,7 +1090,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
nShift = 7;
while ( nx < nImageWidth )
{
- SetPixelOnData(pAcc, pScanLine, nx++, ( nByteVal >> nShift ) & 1);
+ SetPixel(nY, nx++, ( nByteVal >> nShift ) & 1);
}
}
}
@@ -1096,7 +1111,7 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY)
sal_uInt8* pt = getMapData(0);
for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += 2 )
{
- SetPixelOnData(pAcc, pScanLine, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt) - nMinSampleValue) * nMinMax));
+ SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt) - nMinSampleValue) * nMinMax));
}
}
}
@@ -1133,11 +1148,11 @@ void TIFFReader::MakePalCol()
aColorMap[nNumColors - i - 1] = n0RGB;
}
}
- xAcc->SetPaletteEntryCount(std::max<sal_uInt16>(nNumColors, xAcc->GetPaletteEntryCount()));
+ mvPalette.resize(std::max<sal_uInt16>(nNumColors, mvPalette.size()));
for (sal_uInt32 i = 0; i < nNumColors; ++i)
{
- xAcc->SetPaletteColor(i, BitmapColor( static_cast<sal_uInt8>( aColorMap[ i ] >> 16 ),
- static_cast<sal_uInt8>( aColorMap[ i ] >> 8 ), static_cast<sal_uInt8>(aColorMap[ i ]) ) );
+ mvPalette[i] = Color( static_cast<sal_uInt8>( aColorMap[ i ] >> 16 ),
+ static_cast<sal_uInt8>( aColorMap[ i ] >> 8 ), static_cast<sal_uInt8>(aColorMap[ i ]) );
}
}
@@ -1155,8 +1170,8 @@ void TIFFReader::MakePalCol()
nRY=static_cast<sal_uInt32>(fYResolution*2.54+0.5);
}
MapMode aMapMode(MapUnit::MapInch,Point(0,0),Fraction(1,nRX),Fraction(1,nRY));
- aBitmap.SetPrefMapMode(aMapMode);
- aBitmap.SetPrefSize(Size(nImageWidth,nImageLength));
+ maBitmapPrefMapMode = aMapMode;
+ maBitmapPrefSize = Size(nImageWidth,nImageLength);
}
}
@@ -1302,7 +1317,6 @@ bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
nPredictor = 1;
nNumColors = 0;
- xAcc.reset();
aStripOffsets.clear();
aStripByteCounts.clear();
for (auto& j : aMap)
@@ -1506,44 +1520,43 @@ bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
if ( bStatus )
{
- pAlphaMask.reset();
- Size aTargetSize(nImageWidth, nImageLength);
- aBitmap = Bitmap(aTargetSize, nDstBitsPerPixel);
- xAcc = Bitmap::ScopedWriteAccess(aBitmap);
- if (xAcc && xAcc->Width() == nImageWidth && xAcc->Height() == nImageLength)
- {
- if (bStatus && HasAlphaChannel())
- {
- pAlphaMask.reset( new AlphaMask( aTargetSize ) );
- xMaskAcc = AlphaMask::ScopedWriteAccess(*pAlphaMask);
- }
+ maBitmapPixelSize = Size(nImageWidth, nImageLength);
+ mpBitmap.reset(new sal_uInt8[nImageWidth * nImageLength * (HasAlphaChannel() ? 4 : 3)]);
- if (bStatus && ReadMap())
- {
- nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
- MakePalCol();
- nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
- }
- else
- bStatus = false;
-
- xAcc.reset();
- xMaskAcc.reset();
-
- if ( bStatus )
- {
- BitmapEx aImage;
+ if (bStatus && ReadMap())
+ {
+ nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
+ MakePalCol();
+ nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
+ // convert palette-ized images to 24-bit color
+ if (!mvPalette.empty())
+ for (long nY = 0; nY < nImageLength; ++nY)
+ for (long nX = 0; nX < nImageWidth; ++nX)
+ {
+ auto p = mpBitmap.get() + ((maBitmapPixelSize.Width() * nY + nX) * 3);
+ auto c = mvPalette[*p];
+ *p = c.GetRed();
+ p++;
+ *p = c.GetGreen();
+ p++;
+ *p = c.GetBlue();
+ }
+ }
+ else
+ bStatus = false;
- if (pAlphaMask)
- aImage = BitmapEx( aBitmap, *pAlphaMask );
- else
- aImage = aBitmap;
+ if ( bStatus )
+ {
+ BitmapEx aImage = vcl::bitmap::CreateFromData(mpBitmap.get(), nImageWidth, nImageLength,
+ nImageWidth * (HasAlphaChannel() ? 4 : 3), // scanline bytes
+ HasAlphaChannel() ? 32 : 24);
+ aImage.SetPrefMapMode(maBitmapPrefMapMode);
+ aImage.SetPrefSize(maBitmapPrefSize);
- AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), aBitmap.GetSizePixel(),
- ANIMATION_TIMEOUT_ON_CLICK, Disposal::Back );
+ AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), maBitmapPixelSize,
+ ANIMATION_TIMEOUT_ON_CLICK, Disposal::Back );
- aAnimation.Insert( aAnimationBitmap );
- }
+ aAnimation.Insert( aAnimationBitmap );
}
}
diff --git a/vcl/source/bitmap/BitmapTools.cxx b/vcl/source/bitmap/BitmapTools.cxx
index 5f3d1062275e..4570be72e436 100644
--- a/vcl/source/bitmap/BitmapTools.cxx
+++ b/vcl/source/bitmap/BitmapTools.cxx
@@ -114,25 +114,45 @@ void loadFromSvg(SvStream& rStream, const OUString& sPath, BitmapEx& rBitmapEx,
BitmapEx CreateFromData( sal_uInt8 const *pData, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int32 nStride, sal_uInt16 nBitCount )
{
assert(nStride >= nWidth);
+ assert( nBitCount == 24 || nBitCount == 32);
Bitmap aBmp( Size( nWidth, nHeight ), nBitCount );
Bitmap::ScopedWriteAccess pWrite(aBmp);
assert(pWrite.get());
- if( pWrite.get() )
+ if( !pWrite )
+ return BitmapEx();
+ std::unique_ptr<AlphaMask> pAlphaMask;
+ AlphaMask::ScopedWriteAccess xMaskAcc;
+ if (nBitCount == 32)
{
- for( long y = 0; y < nHeight; ++y )
+ pAlphaMask.reset( new AlphaMask( Size(nWidth, nHeight) ) );
+ xMaskAcc = AlphaMask::ScopedWriteAccess(*pAlphaMask);
+ }
+ for( long y = 0; y < nHeight; ++y )
+ {
+ sal_uInt8 const *p = pData + y * nStride;
+ Scanline pScanline = pWrite->GetScanline(y);
+ for (long x = 0; x < nWidth; ++x)
{
- sal_uInt8 const *p = pData + y * nStride;
- Scanline pScanline = pWrite->GetScanline(y);
+ BitmapColor col(p[0], p[1], p[2]);
+ pWrite->SetPixelOnData(pScanline, x, col);
+ p += nBitCount/8;
+ }
+ if (nBitCount == 32)
+ {
+ p = pData + y * nStride + 3;
+ Scanline pMaskScanLine = xMaskAcc->GetScanline(y);
for (long x = 0; x < nWidth; ++x)
{
- BitmapColor col(p[0], p[1], p[2]);
- pWrite->SetPixelOnData(pScanline, x, col);
- p += 3;
+ xMaskAcc->SetPixelOnData(pMaskScanLine, x, BitmapColor(*p));
+ p += 4;
}
- }
+ }
}
- return aBmp;
+ if (nBitCount == 32)
+ return BitmapEx(aBmp, *pAlphaMask);
+ else
+ return aBmp;
}
/** Copy block of image data into the bitmap.
More information about the Libreoffice-commits
mailing list