[Libreoffice-commits] core.git: Branch 'feature/fixes25' - vcl/opengl
Tomaž Vajngerl
tomaz.vajngerl at collabora.co.uk
Tue Jun 21 15:08:04 UTC 2016
vcl/opengl/salbmp.cxx | 92 +++++++++++++++++++++++++++++++++++---------------
1 file changed, 66 insertions(+), 26 deletions(-)
New commits:
commit 7fcc432772ea2970a30ec753a91b9d88a5125020
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Tue Jun 21 14:34:45 2016 +0800
tdf#100451 convert texture buffer to 1-bit and 4-bit palette buffer
OpenGL doesn't support palettes so when the texture is created,
the bitmap buffer is converted to 24-bit RGB. This works nice for
showing the bitmaps on screen. The problem arises when we want to
read the bitmap buffer back (like in a PDF export) as we have to
convert that back to 1-bit or 4-bit palette bitmap buffer. For 4-bit
this was not implemented yet, on the other hand for 1-bit it was
implemented but it didn't take palette into account so the bitmap
was not correct (inverted).
This commit introduces a ScanlineWriter which handles writing
RGB colors to 1-bit and 4-bit palette scanlines. The class sets
up the masks and shifts needed to place the color information
at the correct place in a byte. It also automatically converts a
RGB to palette index.
Change-Id: Ie66ca8cecff40c1252072ba95196ef65ba787f4c
Reviewed-on: https://gerrit.libreoffice.org/26532
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
Tested-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 87fc542..58909b4 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -412,7 +412,48 @@ void lclInstantiateTexture(OpenGLTexture& rTexture, const int nWidth, const int
rTexture = OpenGLTexture (nWidth, nHeight, nFormat, nType, pData);
}
-}
+// Write color information for 1 and 4 bit palette bitmap scanlines.
+class ScanlineWriter
+{
+ BitmapPalette& maPalette;
+ sal_uInt8 mnColorsPerByte; // number of colors that are stored in one byte
+ sal_uInt8 mnColorBitSize; // number of bits a color takes
+ sal_uInt8 mnColorBitMask; // bit mask used to isolate the color
+ sal_uInt8* mpCurrentScanline;
+ long mnX;
+
+public:
+ ScanlineWriter(BitmapPalette& aPalette, sal_Int8 nColorsPerByte)
+ : maPalette(aPalette)
+ , mnColorsPerByte(nColorsPerByte)
+ , mnColorBitSize(8 / mnColorsPerByte) // bit size is number of bit in a byte divided by number of colors per byte (8 / 2 = 4 for 4-bit)
+ , mnColorBitMask((1 << mnColorBitSize) - 1) // calculate the bit mask from the bit size
+ , mpCurrentScanline(nullptr)
+ , mnX(0)
+ {}
+
+ inline void writeRGB(sal_uInt8 nR, sal_uInt8 nG, sal_uInt8 nB)
+ {
+ // calculate to which index we will write
+ long nScanlineIndex = mnX / mnColorsPerByte;
+
+ // calculate the number of shifts to get the color information to the right place
+ long nShift = (8 - mnColorBitSize) - ((mnX % mnColorsPerByte) * mnColorBitSize);
+
+ sal_uInt16 nColorIndex = maPalette.GetBestIndex(BitmapColor(nR, nG, nB));
+ mpCurrentScanline[nScanlineIndex] &= ~(mnColorBitMask << nShift); // clear
+ mpCurrentScanline[nScanlineIndex] |= (nColorIndex & mnColorBitMask) << nShift; // set
+ mnX++;
+ }
+
+ inline void nextLine(sal_uInt8* pScanline)
+ {
+ mnX = 0;
+ mpCurrentScanline = pScanline;
+ }
+};
+
+} // end anonymous namespace
Size OpenGLSalBitmap::GetSize() const
{
@@ -559,43 +600,43 @@ bool OpenGLSalBitmap::ReadTexture()
#endif
return true;
}
- else if (mnBits == 1)
- { // convert buffers from 24-bit RGB to 1-bit Mask
+ else if (mnBits == 1 || mnBits == 4)
+ { // convert buffers from 24-bit RGB to 1 or 4-bit buffer
std::vector<sal_uInt8> aBuffer(mnWidth * mnHeight * 3);
sal_uInt8* pBuffer = aBuffer.data();
determineTextureFormat(24, nFormat, nType);
maTexture.Read(nFormat, nType, pBuffer);
+ sal_uInt16 nSourceBytesPerRow = lclBytesPerRow(24, mnWidth);
- int nShift = 7;
- size_t nIndex = 0;
-
- sal_uInt8* pCurrent = pBuffer;
+ std::unique_ptr<ScanlineWriter> pWriter;
+ switch(mnBits)
+ {
+ case 1:
+ pWriter.reset(new ScanlineWriter(maPalette, 8));
+ break;
+ case 4:
+ default:
+ pWriter.reset(new ScanlineWriter(maPalette, 2));
+ break;
+ }
for (int y = 0; y < mnHeight; ++y)
{
+ sal_uInt8* pSource = &pBuffer[y * nSourceBytesPerRow];
+ sal_uInt8* pDestination = &pData[y * mnBytesPerRow];
+
+ pWriter->nextLine(pDestination);
+
for (int x = 0; x < mnWidth; ++x)
{
- if (nShift < 0)
- {
- nShift = 7;
- nIndex++;
- pData[nIndex] = 0;
- }
-
- sal_uInt8 nR = *pCurrent++;
- sal_uInt8 nG = *pCurrent++;
- sal_uInt8 nB = *pCurrent++;
+ // read source
+ sal_uInt8 nR = *pSource++;
+ sal_uInt8 nG = *pSource++;
+ sal_uInt8 nB = *pSource++;
- if (nR > 0 && nG > 0 && nB > 0)
- {
- pData[nIndex] |= (1 << nShift);
- }
- nShift--;
+ pWriter->writeRGB(nR, nG, nB);
}
- nShift = 7;
- nIndex++;
- pData[nIndex] = 0;
}
return true;
}
@@ -604,7 +645,6 @@ bool OpenGLSalBitmap::ReadTexture()
<< mnWidth << "x" << mnHeight << "- unimplemented bit depth: "
<< mnBits);
return false;
-
}
sal_uInt16 OpenGLSalBitmap::GetBitCount() const
More information about the Libreoffice-commits
mailing list