summaryrefslogtreecommitdiff
path: root/vcl/opengl
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2016-06-21 14:34:45 +0800
committerTomaž Vajngerl <quikee@gmail.com>2016-06-21 06:53:33 +0000
commitc2fc93cae194a1aad94721edc51078b168a34f5f (patch)
tree9a487f94b0e9bbff1494bc00c1624a0e8751a963 /vcl/opengl
parentfafb309d2ec6b7a7125409dabffd13613ad65a0d (diff)
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@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl/opengl')
-rw-r--r--vcl/opengl/salbmp.cxx92
1 files changed, 66 insertions, 26 deletions
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index fbfcf6fd1ea5..ef081ee9fd4d 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -415,7 +415,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
{
@@ -567,43 +608,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;
}
@@ -612,7 +653,6 @@ bool OpenGLSalBitmap::ReadTexture()
<< mnWidth << "x" << mnHeight << "- unimplemented bit depth: "
<< mnBits);
return false;
-
}
sal_uInt16 OpenGLSalBitmap::GetBitCount() const