summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2018-07-05 17:45:14 +0200
committerJan-Marek Glogowski <glogow@fbihome.de>2018-07-06 10:47:32 +0200
commitef46981023becba0f34a235a3571028dd0ea8838 (patch)
tree862c69c767e2bf86430b2a8d2458b4dcf9459e1b
parentebd1d973eac7ef6f330634a2d2a8ca1bf3c6720e (diff)
Qt5 implement 4bit => 32bit bitmap conversion
Some of the PNG icons are 4bit palette based PNG images. This implements the conversation function for the most common 4bit case, so we don't rely on some generic handling. All other non-4bit conversions can be handled by Qt. Change-Id: I4ddd744fb7166fc3a6992b6be6c250c2adb99ca5
-rw-r--r--vcl/inc/qt5/Qt5Bitmap.hxx2
-rw-r--r--vcl/qt5/Qt5Bitmap.cxx72
-rw-r--r--vcl/qt5/Qt5Graphics_GDI.cxx22
3 files changed, 84 insertions, 12 deletions
diff --git a/vcl/inc/qt5/Qt5Bitmap.hxx b/vcl/inc/qt5/Qt5Bitmap.hxx
index 6ecdebed5ca1..c89038a28fb7 100644
--- a/vcl/inc/qt5/Qt5Bitmap.hxx
+++ b/vcl/inc/qt5/Qt5Bitmap.hxx
@@ -31,7 +31,7 @@ class VCL_DLLPUBLIC Qt5Bitmap : public SalBitmap
BitmapPalette m_aPalette;
// for 4bit support
- std::unique_ptr<sal_uInt8> m_pBuffer;
+ std::unique_ptr<sal_uInt8[]> m_pBuffer;
Size m_aSize;
sal_uInt32 m_nScanline;
diff --git a/vcl/qt5/Qt5Bitmap.cxx b/vcl/qt5/Qt5Bitmap.cxx
index ff44143a16f2..824bfc28b89a 100644
--- a/vcl/qt5/Qt5Bitmap.cxx
+++ b/vcl/qt5/Qt5Bitmap.cxx
@@ -48,8 +48,17 @@ bool Qt5Bitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPale
{
m_pImage.reset();
m_aSize = rSize;
- m_nScanline = rSize.Width() / 2 + (rSize.Width() % 2) ? 0 : 1;
- m_pBuffer.reset(new sal_uInt8[m_nScanline * rSize.Height()]);
+ bool bFail = o3tl::checked_multiply<sal_uInt32>(rSize.Width(), nBitCount, m_nScanline);
+ if (bFail)
+ {
+ SAL_WARN("vcl.gdi", "checked multiply failed");
+ return false;
+ }
+ m_nScanline = AlignedWidth4Bytes(m_nScanline);
+ sal_uInt8* pBuffer = nullptr;
+ if (0 != m_nScanline && 0 != rSize.Height())
+ pBuffer = new sal_uInt8[m_nScanline * rSize.Height()];
+ m_pBuffer.reset(pBuffer);
}
else
{
@@ -59,7 +68,7 @@ bool Qt5Bitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPale
m_aPalette = rPal;
auto count = rPal.GetEntryCount();
- if (nBitCount != 4 && count)
+ if (nBitCount != 4 && count && m_pImage.get())
{
QVector<QRgb> aColorTable(count);
for (unsigned i = 0; i < count; ++i)
@@ -81,8 +90,14 @@ bool Qt5Bitmap::Create(const SalBitmap& rSalBmp)
{
m_aSize = pBitmap->m_aSize;
m_nScanline = pBitmap->m_nScanline;
- m_pBuffer.reset(new sal_uInt8[m_nScanline * m_aSize.Height()]);
- memcpy(m_pBuffer.get(), pBitmap->m_pBuffer.get(), m_nScanline);
+ sal_uInt8* pBuffer = nullptr;
+ if (0 != m_nScanline && 0 != m_aSize.Height())
+ {
+ sal_uInt32 nSize = m_nScanline * m_aSize.Height();
+ pBuffer = new sal_uInt8[nSize];
+ memcpy(pBuffer, pBitmap->m_pBuffer.get(), nSize);
+ }
+ m_pBuffer.reset(pBuffer);
m_pImage.reset();
}
m_aPalette = pBitmap->m_aPalette;
@@ -107,9 +122,52 @@ bool Qt5Bitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount)
const Qt5Bitmap* pBitmap = static_cast<const Qt5Bitmap*>(&rSalBmp);
if (pBitmap->m_pBuffer.get())
- return false;
+ {
+ if (nNewBitCount != 32)
+ return false;
+
+ // convert 4bit indexed palette to 32bit ARGB
+ m_pImage.reset(new QImage(pBitmap->m_aSize.Width(), pBitmap->m_aSize.Height(),
+ getBitFormat(nNewBitCount)));
+ m_pImage->fill(0);
+
+ // prepare a whole palette
+ const BitmapPalette& rPal = pBitmap->m_aPalette;
+ QVector<QRgb> colorTable(16);
+ int i = 0, maxEntry = pBitmap->m_aPalette.GetEntryCount();
+ assert(maxEntry <= 16 && maxEntry >= 0);
+ for (; i < maxEntry; ++i)
+ colorTable[i] = qRgb(rPal[i].GetRed(), rPal[i].GetGreen(), rPal[i].GetBlue());
+ for (; i < 16; ++i)
+ colorTable[i] = qRgb(0, 0, 0);
- m_pImage.reset(new QImage(pBitmap->m_pImage->convertToFormat(getBitFormat(nNewBitCount))));
+ sal_uInt32* image_data = reinterpret_cast<sal_uInt32*>(m_pImage->bits());
+ sal_uInt8* buffer_data_pos = pBitmap->m_pBuffer.get();
+ sal_uInt32 nWidth = pBitmap->m_aSize.Height() / 2;
+ bool isOdd(0 != pBitmap->m_aSize.Height() % 2);
+
+ for (sal_uInt32 h = 0; h < pBitmap->m_aSize.Height(); ++h)
+ {
+ sal_uInt8* buffer_data = buffer_data_pos;
+ buffer_data_pos += pBitmap->m_nScanline;
+ for (sal_uInt32 w = 0; w < nWidth; ++w)
+ {
+ *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data >> 4));
+ ++image_data;
+ *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data & 0xF));
+ ++image_data;
+ ++buffer_data;
+ }
+ if (isOdd)
+ {
+ *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data >> 4));
+ ++image_data;
+ }
+ }
+ }
+ else
+ m_pImage.reset(new QImage(pBitmap->m_pImage->convertToFormat(getBitFormat(nNewBitCount))));
+ m_pBuffer.reset();
return true;
}
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index b58f18e4b59b..971b85f705fe 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -403,8 +403,12 @@ void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBit
assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight);
Qt5Painter aPainter(*this);
-
- const QImage* pImage = static_cast<const Qt5Bitmap*>(&rSalBitmap)->GetQImage();
+ Qt5Bitmap aRGBABitmap;
+ if (rSalBitmap.GetBitCount() == 4)
+ aRGBABitmap.Create(rSalBitmap, 32);
+ const QImage* pImage = (rSalBitmap.GetBitCount() != 4)
+ ? static_cast<const Qt5Bitmap*>(&rSalBitmap)->GetQImage()
+ : aRGBABitmap.GetQImage();
assert(pImage);
aPainter.drawImage(
@@ -475,7 +479,12 @@ static bool getAlphaImage(const SalBitmap& rSourceBitmap, const SalBitmap& rAlph
return false;
}
- const QImage* pBitmap = static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage();
+ Qt5Bitmap aRGBABitmap;
+ if (rSourceBitmap.GetBitCount() == 4)
+ aRGBABitmap.Create(rSourceBitmap, 32);
+ const QImage* pBitmap = (rSourceBitmap.GetBitCount() != 4)
+ ? static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage()
+ : aRGBABitmap.GetQImage();
const QImage* pAlpha = static_cast<const Qt5Bitmap*>(&rAlphaBitmap)->GetQImage();
rAlphaImage = pBitmap->convertToFormat(Qt5_DefaultFormat32);
@@ -532,7 +541,12 @@ bool Qt5Graphics::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const ba
return false;
else
{
- const QImage* pBitmap = static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage();
+ Qt5Bitmap aRGBABitmap;
+ if (rSourceBitmap.GetBitCount() == 4)
+ aRGBABitmap.Create(rSourceBitmap, 32);
+ const QImage* pBitmap = (rSourceBitmap.GetBitCount() != 4)
+ ? static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage()
+ : aRGBABitmap.GetQImage();
aImage = pBitmap->convertToFormat(Qt5_DefaultFormat32);
}