[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