summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2018-04-17 22:06:20 +1000
committerTomaž Vajngerl <quikee@gmail.com>2018-04-20 08:35:58 +0200
commit900b1109a94c1d72c17ab429da1b6c6c2bf79ac6 (patch)
treecd9db8e494a2ae93460c29609eff4b7dba15f583 /vcl
parentf9473a8d2ea6740d325ac35da74fec16476820f0 (diff)
vcl: move Bitmap{Ex}::ReduceColors() to BitmapColorQuantizationFilter class
Change-Id: I32b58e8d451e7303e94788a546a5b5f9a5bb4590 Reviewed-on: https://gerrit.libreoffice.org/53037 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk3
-rw-r--r--vcl/source/bitmap/BitmapColorQuantizationFilter.cxx229
-rw-r--r--vcl/source/bitmap/BitmapMedianColorQuantizationFilter.cxx300
-rw-r--r--vcl/source/bitmap/BitmapSimpleColorQuantizationFilter.cxx108
-rw-r--r--vcl/source/gdi/animate.cxx14
-rw-r--r--vcl/source/gdi/bitmap3.cxx493
-rw-r--r--vcl/source/gdi/bitmapex.cxx5
-rw-r--r--vcl/unx/generic/dtrans/bmp.cxx39
8 files changed, 676 insertions, 515 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 03c705aa5544..cfd5da379ab3 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -322,6 +322,9 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/bitmap/BitmapScaleSuperFilter \
vcl/source/bitmap/BitmapScaleConvolutionFilter \
vcl/source/bitmap/BitmapSymmetryCheck \
+ vcl/source/bitmap/BitmapColorQuantizationFilter \
+ vcl/source/bitmap/BitmapSimpleColorQuantizationFilter \
+ vcl/source/bitmap/BitmapMedianColorQuantizationFilter \
vcl/source/bitmap/BitmapTools \
vcl/source/bitmap/checksum \
vcl/source/image/Image \
diff --git a/vcl/source/bitmap/BitmapColorQuantizationFilter.cxx b/vcl/source/bitmap/BitmapColorQuantizationFilter.cxx
new file mode 100644
index 000000000000..13e88341c0d9
--- /dev/null
+++ b/vcl/source/bitmap/BitmapColorQuantizationFilter.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/BitmapColorQuantizationFilter.hxx>
+#include <vcl/bitmapaccess.hxx>
+
+#include <bitmapwriteaccess.hxx>
+
+#include <cstdlib>
+
+BitmapEx BitmapColorQuantizationFilter::execute(BitmapEx const& aBitmapEx)
+{
+ Bitmap aBitmap = aBitmapEx.GetBitmap();
+
+ bool bRet = false;
+
+ if (aBitmap.GetColorCount() <= static_cast<sal_uLong>(mnNewColorCount))
+ {
+ bRet = true;
+ }
+ else
+ {
+ Bitmap::ScopedReadAccess pRAcc(aBitmap);
+ sal_uInt16 nBitCount;
+
+ if (mnNewColorCount > 256)
+ mnNewColorCount = 256;
+
+ if (mnNewColorCount < 17)
+ nBitCount = 4;
+ else
+ nBitCount = 8;
+
+ if (pRAcc)
+ {
+ const sal_uInt32 nValidBits = 4;
+ const sal_uInt32 nRightShiftBits = 8 - nValidBits;
+ const sal_uInt32 nLeftShiftBits1 = nValidBits;
+ const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
+ const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
+ const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
+ const sal_uInt32 nTotalColors
+ = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+ std::unique_ptr<PopularColorCount[]> pCountTable(new PopularColorCount[nTotalColors]);
+
+ memset(pCountTable.get(), 0, nTotalColors * sizeof(PopularColorCount));
+
+ for (long nR = 0, nIndex = 0; nR < 256; nR += nColorOffset)
+ {
+ for (long nG = 0; nG < 256; nG += nColorOffset)
+ {
+ for (long nB = 0; nB < 256; nB += nColorOffset)
+ {
+ pCountTable[nIndex].mnIndex = nIndex;
+ nIndex++;
+ }
+ }
+ }
+
+ if (pRAcc->HasPalette())
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ const BitmapColor& rCol
+ = pRAcc->GetPaletteColor(pRAcc->GetIndexFromData(pScanlineRead, nX));
+ pCountTable[((static_cast<sal_uInt32>(rCol.GetRed()) >> nRightShiftBits)
+ << nLeftShiftBits2)
+ | ((static_cast<sal_uInt32>(rCol.GetGreen()) >> nRightShiftBits)
+ << nLeftShiftBits1)
+ | (static_cast<sal_uInt32>(rCol.GetBlue()) >> nRightShiftBits)]
+ .mnCount++;
+ }
+ }
+ }
+ else
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ const BitmapColor aCol(pRAcc->GetPixelFromData(pScanlineRead, nX));
+ pCountTable[((static_cast<sal_uInt32>(aCol.GetRed()) >> nRightShiftBits)
+ << nLeftShiftBits2)
+ | ((static_cast<sal_uInt32>(aCol.GetGreen()) >> nRightShiftBits)
+ << nLeftShiftBits1)
+ | (static_cast<sal_uInt32>(aCol.GetBlue()) >> nRightShiftBits)]
+ .mnCount++;
+ }
+ }
+ }
+
+ BitmapPalette aNewPal(mnNewColorCount);
+
+ std::qsort(pCountTable.get(), nTotalColors, sizeof(PopularColorCount),
+ [](const void* p1, const void* p2) {
+ int nRet;
+
+ if (static_cast<PopularColorCount const*>(p1)->mnCount
+ < static_cast<PopularColorCount const*>(p2)->mnCount)
+ nRet = 1;
+ else if (static_cast<PopularColorCount const*>(p1)->mnCount
+ == static_cast<PopularColorCount const*>(p2)->mnCount)
+ nRet = 0;
+ else
+ nRet = -1;
+
+ return nRet;
+ });
+
+ for (sal_uInt16 n = 0; n < mnNewColorCount; n++)
+ {
+ const PopularColorCount& rPop = pCountTable[n];
+ aNewPal[n] = BitmapColor(
+ static_cast<sal_uInt8>((rPop.mnIndex >> nLeftShiftBits2) << nRightShiftBits),
+ static_cast<sal_uInt8>(
+ ((rPop.mnIndex >> nLeftShiftBits1) & (nColorsPerComponent - 1))
+ << nRightShiftBits),
+ static_cast<sal_uInt8>((rPop.mnIndex & (nColorsPerComponent - 1))
+ << nRightShiftBits));
+ }
+
+ Bitmap aNewBmp(aBitmap.GetSizePixel(), nBitCount, &aNewPal);
+ BitmapScopedWriteAccess pWAcc(aNewBmp);
+
+ if (pWAcc)
+ {
+ BitmapColor aDstCol(sal_uInt8(0));
+ std::unique_ptr<sal_uInt8[]> pIndexMap(new sal_uInt8[nTotalColors]);
+
+ for (long nR = 0, nIndex = 0; nR < 256; nR += nColorOffset)
+ {
+ for (long nG = 0; nG < 256; nG += nColorOffset)
+ {
+ for (long nB = 0; nB < 256; nB += nColorOffset)
+ {
+ pIndexMap[nIndex++] = static_cast<sal_uInt8>(aNewPal.GetBestIndex(
+ BitmapColor(static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG),
+ static_cast<sal_uInt8>(nB))));
+ }
+ }
+ }
+
+ if (pRAcc->HasPalette())
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanline = pWAcc->GetScanline(nY);
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor(
+ pRAcc->GetIndexFromData(pScanlineRead, nX));
+ aDstCol.SetIndex(pIndexMap[((static_cast<sal_uInt32>(rCol.GetRed())
+ >> nRightShiftBits)
+ << nLeftShiftBits2)
+ | ((static_cast<sal_uInt32>(rCol.GetGreen())
+ >> nRightShiftBits)
+ << nLeftShiftBits1)
+ | (static_cast<sal_uInt32>(rCol.GetBlue())
+ >> nRightShiftBits)]);
+ pWAcc->SetPixelOnData(pScanline, nX, aDstCol);
+ }
+ }
+ }
+ else
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanline = pWAcc->GetScanline(nY);
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ const BitmapColor aCol(pRAcc->GetPixelFromData(pScanlineRead, nX));
+ aDstCol.SetIndex(pIndexMap[((static_cast<sal_uInt32>(aCol.GetRed())
+ >> nRightShiftBits)
+ << nLeftShiftBits2)
+ | ((static_cast<sal_uInt32>(aCol.GetGreen())
+ >> nRightShiftBits)
+ << nLeftShiftBits1)
+ | (static_cast<sal_uInt32>(aCol.GetBlue())
+ >> nRightShiftBits)]);
+ pWAcc->SetPixelOnData(pScanline, nX, aDstCol);
+ }
+ }
+ }
+
+ pWAcc.reset();
+ bRet = true;
+ }
+
+ pCountTable.reset();
+ pRAcc.reset();
+
+ if (bRet)
+ {
+ const MapMode aMap(aBitmap.GetPrefMapMode());
+ const Size aSize(aBitmap.GetPrefSize());
+
+ aBitmap = aNewBmp;
+
+ aBitmap.SetPrefMapMode(aMap);
+ aBitmap.SetPrefSize(aSize);
+ }
+ }
+ }
+
+ if (bRet)
+ return BitmapEx(aBitmap);
+
+ return BitmapEx();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/bitmap/BitmapMedianColorQuantizationFilter.cxx b/vcl/source/bitmap/BitmapMedianColorQuantizationFilter.cxx
new file mode 100644
index 000000000000..807e8a049a13
--- /dev/null
+++ b/vcl/source/bitmap/BitmapMedianColorQuantizationFilter.cxx
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/BitmapMedianColorQuantizationFilter.hxx>
+
+#include <bitmapwriteaccess.hxx>
+#include <impoctree.hxx>
+
+#include <cstdlib>
+
+BitmapEx BitmapMedianColorQuantizationFilter::execute(BitmapEx const& aBitmapEx)
+{
+ Bitmap aBitmap = aBitmapEx.GetBitmap();
+
+ bool bRet = false;
+
+ if (aBitmap.GetColorCount() <= static_cast<sal_uLong>(mnNewColorCount))
+ {
+ bRet = true;
+ }
+ else
+ {
+ Bitmap::ScopedReadAccess pRAcc(aBitmap);
+ sal_uInt16 nBitCount;
+
+ if (mnNewColorCount < 17)
+ {
+ nBitCount = 4;
+ }
+ else if (mnNewColorCount < 257)
+ {
+ nBitCount = 8;
+ }
+ else
+ {
+ OSL_FAIL("Bitmap::ImplReduceMedian(): invalid color count!");
+ nBitCount = 8;
+ mnNewColorCount = 256;
+ }
+
+ if (pRAcc)
+ {
+ Bitmap aNewBmp(aBitmap.GetSizePixel(), nBitCount);
+ BitmapScopedWriteAccess pWAcc(aNewBmp);
+
+ if (pWAcc)
+ {
+ const sal_uLong nSize = 32768 * sizeof(sal_uLong);
+ sal_uLong* pColBuf = static_cast<sal_uLong*>(rtl_allocateMemory(nSize));
+ const long nWidth = pWAcc->Width();
+ const long nHeight = pWAcc->Height();
+ long nIndex = 0;
+
+ memset(pColBuf, 0, nSize);
+
+ // create Buffer
+ if (pRAcc->HasPalette())
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ const BitmapColor& rCol = pRAcc->GetPaletteColor(
+ pRAcc->GetIndexFromData(pScanlineRead, nX));
+
+ pColBuf[RGB15(rCol.GetRed() >> 3, rCol.GetGreen() >> 3,
+ rCol.GetBlue() >> 3)]++;
+ }
+ }
+ }
+ else
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ const BitmapColor aCol(pRAcc->GetPixelFromData(pScanlineRead, nX));
+ pColBuf[RGB15(aCol.GetRed() >> 3, aCol.GetGreen() >> 3,
+ aCol.GetBlue() >> 3)]++;
+ }
+ }
+ }
+
+ // create palette via median cut
+ BitmapPalette aPal(pWAcc->GetPaletteEntryCount());
+ medianCut(aBitmap, pColBuf, aPal, 0, 31, 0, 31, 0, 31, mnNewColorCount,
+ nWidth * nHeight, nIndex);
+
+ // do mapping of colors to palette
+ InverseColorMap aMap(aPal);
+ pWAcc->SetPalette(aPal);
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanline = pWAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ pWAcc->SetPixelOnData(
+ pScanline, nX,
+ BitmapColor(static_cast<sal_uInt8>(
+ aMap.GetBestPaletteIndex(pRAcc->GetColor(nY, nX)))));
+ }
+ }
+
+ rtl_freeMemory(pColBuf);
+ pWAcc.reset();
+ bRet = true;
+ }
+
+ pRAcc.reset();
+ if (bRet)
+ {
+ const MapMode aMap(aBitmap.GetPrefMapMode());
+ const Size aSize(aBitmap.GetPrefSize());
+
+ aBitmap = aNewBmp;
+
+ aBitmap.SetPrefMapMode(aMap);
+ aBitmap.SetPrefSize(aSize);
+ }
+ }
+ }
+
+ if (bRet)
+ return BitmapEx(aBitmap);
+
+ return BitmapEx();
+}
+
+void BitmapMedianColorQuantizationFilter::medianCut(Bitmap& rBitmap, sal_uLong* pColBuf,
+ BitmapPalette& rPal, long nR1, long nR2,
+ long nG1, long nG2, long nB1, long nB2,
+ long nColors, long nPixels, long& rIndex)
+{
+ if (!nPixels)
+ return;
+
+ BitmapColor aCol;
+ const long nRLen = nR2 - nR1;
+ const long nGLen = nG2 - nG1;
+ const long nBLen = nB2 - nB1;
+ sal_uLong* pBuf = pColBuf;
+
+ if (!nRLen && !nGLen && !nBLen)
+ {
+ if (pBuf[RGB15(nR1, nG1, nB1)])
+ {
+ aCol.SetRed(static_cast<sal_uInt8>(nR1 << 3));
+ aCol.SetGreen(static_cast<sal_uInt8>(nG1 << 3));
+ aCol.SetBlue(static_cast<sal_uInt8>(nB1 << 3));
+ rPal[static_cast<sal_uInt16>(rIndex++)] = aCol;
+ }
+ }
+ else
+ {
+ if (nColors == 1 || nPixels == 1)
+ {
+ long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
+
+ for (long nR = nR1; nR <= nR2; nR++)
+ {
+ for (long nG = nG1; nG <= nG2; nG++)
+ {
+ for (long nB = nB1; nB <= nB2; nB++)
+ {
+ nPixSum = pBuf[RGB15(nR, nG, nB)];
+
+ if (nPixSum)
+ {
+ nRSum += nR * nPixSum;
+ nGSum += nG * nPixSum;
+ nBSum += nB * nPixSum;
+ }
+ }
+ }
+ }
+
+ aCol.SetRed(static_cast<sal_uInt8>((nRSum / nPixels) << 3));
+ aCol.SetGreen(static_cast<sal_uInt8>((nGSum / nPixels) << 3));
+ aCol.SetBlue(static_cast<sal_uInt8>((nBSum / nPixels) << 3));
+ rPal[static_cast<sal_uInt16>(rIndex++)] = aCol;
+ }
+ else
+ {
+ const long nTest = (nPixels >> 1);
+ long nPixOld = 0;
+ long nPixNew = 0;
+
+ if (nBLen > nGLen && nBLen > nRLen)
+ {
+ long nB = nB1 - 1;
+
+ while (nPixNew < nTest)
+ {
+ nB++;
+ nPixOld = nPixNew;
+ for (long nR = nR1; nR <= nR2; nR++)
+ {
+ for (long nG = nG1; nG <= nG2; nG++)
+ {
+ nPixNew += pBuf[RGB15(nR, nG, nB)];
+ }
+ }
+ }
+
+ if (nB < nB2)
+ {
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1,
+ nPixNew, rIndex);
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1,
+ nPixels - nPixNew, rIndex);
+ }
+ else
+ {
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1,
+ nPixOld, rIndex);
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1,
+ nPixels - nPixOld, rIndex);
+ }
+ }
+ else if (nGLen > nRLen)
+ {
+ long nG = nG1 - 1;
+
+ while (nPixNew < nTest)
+ {
+ nG++;
+ nPixOld = nPixNew;
+ for (long nR = nR1; nR <= nR2; nR++)
+ {
+ for (long nB = nB1; nB <= nB2; nB++)
+ {
+ nPixNew += pBuf[RGB15(nR, nG, nB)];
+ }
+ }
+ }
+
+ if (nG < nG2)
+ {
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1,
+ nPixNew, rIndex);
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1,
+ nPixels - nPixNew, rIndex);
+ }
+ else
+ {
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1,
+ nPixOld, rIndex);
+ medianCut(rBitmap, pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1,
+ nPixels - nPixOld, rIndex);
+ }
+ }
+ else
+ {
+ long nR = nR1 - 1;
+
+ while (nPixNew < nTest)
+ {
+ nR++;
+ nPixOld = nPixNew;
+ for (long nG = nG1; nG <= nG2; nG++)
+ {
+ for (long nB = nB1; nB <= nB2; nB++)
+ {
+ nPixNew += pBuf[RGB15(nR, nG, nB)];
+ }
+ }
+ }
+
+ if (nR < nR2)
+ {
+ medianCut(rBitmap, pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1,
+ nPixNew, rIndex);
+ medianCut(rBitmap, pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1,
+ nPixels - nPixNew, rIndex);
+ }
+ else
+ {
+ medianCut(rBitmap, pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1,
+ nPixOld, rIndex);
+ medianCut(rBitmap, pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1,
+ nPixels - nPixOld, rIndex);
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/bitmap/BitmapSimpleColorQuantizationFilter.cxx b/vcl/source/bitmap/BitmapSimpleColorQuantizationFilter.cxx
new file mode 100644
index 000000000000..3ffade558c41
--- /dev/null
+++ b/vcl/source/bitmap/BitmapSimpleColorQuantizationFilter.cxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/BitmapSimpleColorQuantizationFilter.hxx>
+
+#include <bitmapwriteaccess.hxx>
+#include <impoctree.hxx>
+
+#include <cstdlib>
+
+BitmapEx BitmapSimpleColorQuantizationFilter::execute(BitmapEx const& aBitmapEx)
+{
+ Bitmap aBitmap = aBitmapEx.GetBitmap();
+
+ bool bRet = false;
+
+ if (aBitmap.GetColorCount() <= static_cast<sal_uLong>(mnNewColorCount))
+ {
+ bRet = true;
+ }
+ else
+ {
+ Bitmap aNewBmp;
+ Bitmap::ScopedReadAccess pRAcc(aBitmap);
+ const sal_uInt16 nColorCount = std::min(nColorCount, sal_uInt16(256));
+ sal_uInt16 nBitCount = 0;
+
+ if (pRAcc)
+ {
+ Octree aOct(*pRAcc, nColorCount);
+ const BitmapPalette& rPal = aOct.GetPalette();
+
+ aNewBmp = Bitmap(aBitmap.GetSizePixel(), nBitCount, &rPal);
+ BitmapScopedWriteAccess pWAcc(aNewBmp);
+
+ if (pWAcc)
+ {
+ const long nWidth = pRAcc->Width();
+ const long nHeight = pRAcc->Height();
+
+ if (pRAcc->HasPalette())
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanline = pWAcc->GetScanline(nY);
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ auto c = pRAcc->GetPaletteColor(
+ pRAcc->GetIndexFromData(pScanlineRead, nX));
+ pWAcc->SetPixelOnData(
+ pScanline, nX,
+ BitmapColor(static_cast<sal_uInt8>(aOct.GetBestPaletteIndex(c))));
+ }
+ }
+ }
+ else
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ Scanline pScanline = pWAcc->GetScanline(nY);
+ Scanline pScanlineRead = pRAcc->GetScanline(nY);
+ for (long nX = 0; nX < nWidth; nX++)
+ {
+ auto c = pRAcc->GetPixelFromData(pScanlineRead, nX);
+ pWAcc->SetPixelOnData(
+ pScanline, nX,
+ BitmapColor(static_cast<sal_uInt8>(aOct.GetBestPaletteIndex(c))));
+ }
+ }
+ }
+
+ pWAcc.reset();
+ bRet = true;
+ }
+
+ pRAcc.reset();
+ }
+
+ if (bRet)
+ {
+ const MapMode aMap(aBitmap.GetPrefMapMode());
+ const Size aSize(aBitmap.GetPrefSize());
+
+ aBitmap = aNewBmp;
+
+ aBitmap.SetPrefMapMode(aMap);
+ aBitmap.SetPrefSize(aSize);
+ }
+ }
+
+ if (bRet)
+ return BitmapEx(aBitmap);
+
+ return BitmapEx();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/animate.cxx b/vcl/source/gdi/animate.cxx
index d3c5031441f7..5adfc6ca5736 100644
--- a/vcl/source/gdi/animate.cxx
+++ b/vcl/source/gdi/animate.cxx
@@ -17,12 +17,14 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include <vcl/animate.hxx>
#include <tools/stream.hxx>
#include <rtl/crc.h>
+
+#include <vcl/animate.hxx>
#include <vcl/virdev.hxx>
#include <vcl/window.hxx>
#include <vcl/dibtools.hxx>
+#include <vcl/BitmapColorQuantizationFilter.hxx>
#include <impanmvw.hxx>
@@ -527,13 +529,17 @@ bool Animation::ReduceColors( sal_uInt16 nNewColorCount )
{
bRet = true;
- for( size_t i = 0, n = maList.size(); ( i < n ) && bRet; ++i )
- bRet = maList[ i ]->aBmpEx.ReduceColors( nNewColorCount );
+ for (size_t i = 0, n = maList.size(); (i < n) && bRet; ++i)
+ {
+ bRet = BitmapFilter::Filter(maList[i]->aBmpEx, BitmapColorQuantizationFilter(nNewColorCount));
+ }
- maBitmapEx.ReduceColors( nNewColorCount );
+ BitmapFilter::Filter(maBitmapEx, BitmapColorQuantizationFilter(nNewColorCount));
}
else
+ {
bRet = false;
+ }
return bRet;
}
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index 3bf068c3444a..8503db8fc2ca 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -43,7 +43,6 @@
#include <memory>
-#define RGB15( _def_cR, _def_cG, _def_cB ) ((static_cast<sal_uLong>(_def_cR)<<10)|(static_cast<sal_uLong>(_def_cG)<<5)|static_cast<sal_uLong>(_def_cB))
#define GAMMA( _def_cVal, _def_InvGamma ) (static_cast<sal_uInt8>(MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0,255)))
#define CALC_ERRORS \
@@ -1209,498 +1208,6 @@ bool Bitmap::ImplDitherFloyd16()
return bRet;
}
-bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
-{
- bool bRet;
-
- if( GetColorCount() <= static_cast<sal_uLong>(nColorCount) )
- bRet = true;
- else if( nColorCount )
- {
- if( BMP_REDUCE_SIMPLE == eReduce )
- bRet = ImplReduceSimple( nColorCount );
- else if( BMP_REDUCE_POPULAR == eReduce )
- bRet = ImplReducePopular( nColorCount );
- else
- bRet = ImplReduceMedian( nColorCount );
- }
- else
- bRet = false;
-
- return bRet;
-}
-
-bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
-{
- Bitmap aNewBmp;
- ScopedReadAccess pRAcc(*this);
- const sal_uInt16 nColCount = std::min( nColorCount, sal_uInt16(256) );
- sal_uInt16 nBitCount;
- bool bRet = false;
-
- if( nColCount <= 2 )
- nBitCount = 1;
- else if( nColCount <= 16 )
- nBitCount = 4;
- else
- nBitCount = 8;
-
- if( pRAcc )
- {
- Octree aOct( *pRAcc, nColCount );
- const BitmapPalette& rPal = aOct.GetPalette();
-
- aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
- BitmapScopedWriteAccess pWAcc(aNewBmp);
-
- if( pWAcc )
- {
- const long nWidth = pRAcc->Width();
- const long nHeight = pRAcc->Height();
-
- if( pRAcc->HasPalette() )
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanline = pWAcc->GetScanline(nY);
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX =0; nX < nWidth; nX++ )
- {
- auto c = pRAcc->GetPaletteColor( pRAcc->GetIndexFromData( pScanlineRead, nX ) );
- pWAcc->SetPixelOnData( pScanline, nX, BitmapColor(static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( c ))) );
- }
- }
- }
- else
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanline = pWAcc->GetScanline(nY);
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX =0; nX < nWidth; nX++ )
- {
- auto c = pRAcc->GetPixelFromData( pScanlineRead, nX );
- pWAcc->SetPixelOnData( pScanline, nX, BitmapColor(static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( c ))) );
- }
- }
- }
-
- pWAcc.reset();
- bRet = true;
- }
-
- pRAcc.reset();
- }
-
- if( bRet )
- {
- const MapMode aMap( maPrefMapMode );
- const Size aSize( maPrefSize );
-
- *this = aNewBmp;
- maPrefMapMode = aMap;
- maPrefSize = aSize;
- }
-
- return bRet;
-}
-
-struct PopularColorCount
-{
- sal_uInt32 mnIndex;
- sal_uInt32 mnCount;
-};
-
-extern "C" int ImplPopularCmpFnc( const void* p1, const void* p2 )
-{
- int nRet;
-
- if( static_cast<PopularColorCount const *>(p1)->mnCount < static_cast<PopularColorCount const *>(p2)->mnCount )
- nRet = 1;
- else if( static_cast<PopularColorCount const *>(p1)->mnCount == static_cast<PopularColorCount const *>(p2)->mnCount )
- nRet = 0;
- else
- nRet = -1;
-
- return nRet;
-}
-
-bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
-{
- ScopedReadAccess pRAcc(*this);
- sal_uInt16 nBitCount;
- bool bRet = false;
-
- if( nColCount > 256 )
- nColCount = 256;
-
- if( nColCount < 17 )
- nBitCount = 4;
- else
- nBitCount = 8;
-
- if( pRAcc )
- {
- const sal_uInt32 nValidBits = 4;
- const sal_uInt32 nRightShiftBits = 8 - nValidBits;
- const sal_uInt32 nLeftShiftBits1 = nValidBits;
- const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
- const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
- const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
- const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
- const long nWidth = pRAcc->Width();
- const long nHeight = pRAcc->Height();
- std::unique_ptr<PopularColorCount[]> pCountTable(new PopularColorCount[ nTotalColors ]);
-
- memset( pCountTable.get(), 0, nTotalColors * sizeof( PopularColorCount ) );
-
- for( long nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
- {
- for( long nG = 0; nG < 256; nG += nColorOffset )
- {
- for( long nB = 0; nB < 256; nB += nColorOffset )
- {
- pCountTable[ nIndex ].mnIndex = nIndex;
- nIndex++;
- }
- }
- }
-
- if( pRAcc->HasPalette() )
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX = 0; nX < nWidth; nX++ )
- {
- const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetIndexFromData( pScanlineRead, nX ) );
- pCountTable[ ( ( static_cast<sal_uInt32>(rCol.GetRed()) >> nRightShiftBits ) << nLeftShiftBits2 ) |
- ( ( static_cast<sal_uInt32>(rCol.GetGreen()) >> nRightShiftBits ) << nLeftShiftBits1 ) |
- ( static_cast<sal_uInt32>(rCol.GetBlue()) >> nRightShiftBits ) ].mnCount++;
- }
- }
- }
- else
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX = 0; nX < nWidth; nX++ )
- {
- const BitmapColor aCol( pRAcc->GetPixelFromData( pScanlineRead, nX ) );
- pCountTable[ ( ( static_cast<sal_uInt32>(aCol.GetRed()) >> nRightShiftBits ) << nLeftShiftBits2 ) |
- ( ( static_cast<sal_uInt32>(aCol.GetGreen()) >> nRightShiftBits ) << nLeftShiftBits1 ) |
- ( static_cast<sal_uInt32>(aCol.GetBlue()) >> nRightShiftBits ) ].mnCount++;
- }
- }
- }
-
- BitmapPalette aNewPal( nColCount );
-
- qsort( pCountTable.get(), nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
-
- for( sal_uInt16 n = 0; n < nColCount; n++ )
- {
- const PopularColorCount& rPop = pCountTable[ n ];
- aNewPal[ n ] = BitmapColor( static_cast<sal_uInt8>( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
- static_cast<sal_uInt8>( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
- static_cast<sal_uInt8>( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
- }
-
- Bitmap aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
- BitmapScopedWriteAccess pWAcc(aNewBmp);
-
- if( pWAcc )
- {
- BitmapColor aDstCol( sal_uInt8(0) );
- std::unique_ptr<sal_uInt8[]> pIndexMap(new sal_uInt8[ nTotalColors ]);
-
- for( long nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
- for( long nG = 0; nG < 256; nG += nColorOffset )
- for( long nB = 0; nB < 256; nB += nColorOffset )
- pIndexMap[ nIndex++ ] = static_cast<sal_uInt8>(aNewPal.GetBestIndex( BitmapColor( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) ) ));
-
- if( pRAcc->HasPalette() )
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanline = pWAcc->GetScanline(nY);
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX = 0; nX < nWidth; nX++ )
- {
- const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetIndexFromData( pScanlineRead, nX ) );
- aDstCol.SetIndex( pIndexMap[ ( ( static_cast<sal_uInt32>(rCol.GetRed()) >> nRightShiftBits ) << nLeftShiftBits2 ) |
- ( ( static_cast<sal_uInt32>(rCol.GetGreen()) >> nRightShiftBits ) << nLeftShiftBits1 ) |
- ( static_cast<sal_uInt32>(rCol.GetBlue()) >> nRightShiftBits ) ] );
- pWAcc->SetPixelOnData( pScanline, nX, aDstCol );
- }
- }
- }
- else
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanline = pWAcc->GetScanline(nY);
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX = 0; nX < nWidth; nX++ )
- {
- const BitmapColor aCol( pRAcc->GetPixelFromData( pScanlineRead, nX ) );
- aDstCol.SetIndex( pIndexMap[ ( ( static_cast<sal_uInt32>(aCol.GetRed()) >> nRightShiftBits ) << nLeftShiftBits2 ) |
- ( ( static_cast<sal_uInt32>(aCol.GetGreen()) >> nRightShiftBits ) << nLeftShiftBits1 ) |
- ( static_cast<sal_uInt32>(aCol.GetBlue()) >> nRightShiftBits ) ] );
- pWAcc->SetPixelOnData( pScanline, nX, aDstCol );
- }
- }
- }
-
- pWAcc.reset();
- bRet = true;
- }
-
- pCountTable.reset();
- pRAcc.reset();
-
- if( bRet )
- {
- const MapMode aMap( maPrefMapMode );
- const Size aSize( maPrefSize );
-
- *this = aNewBmp;
- maPrefMapMode = aMap;
- maPrefSize = aSize;
- }
- }
-
- return bRet;
-}
-
-bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
-{
- ScopedReadAccess pRAcc(*this);
- sal_uInt16 nBitCount;
- bool bRet = false;
-
- if( nColCount < 17 )
- nBitCount = 4;
- else if( nColCount < 257 )
- nBitCount = 8;
- else
- {
- OSL_FAIL( "Bitmap::ImplReduceMedian(): invalid color count!" );
- nBitCount = 8;
- nColCount = 256;
- }
-
- if( pRAcc )
- {
- Bitmap aNewBmp( GetSizePixel(), nBitCount );
- BitmapScopedWriteAccess pWAcc(aNewBmp);
-
- if( pWAcc )
- {
- const sal_uLong nSize = 32768 * sizeof( sal_uLong );
- sal_uLong* pColBuf = static_cast<sal_uLong*>(rtl_allocateMemory( nSize ));
- const long nWidth = pWAcc->Width();
- const long nHeight = pWAcc->Height();
- long nIndex = 0;
-
- memset( pColBuf, 0, nSize );
-
- // create Buffer
- if( pRAcc->HasPalette() )
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX = 0; nX < nWidth; nX++ )
- {
- const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetIndexFromData( pScanlineRead, nX ) );
- pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
- }
- }
- }
- else
- {
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanlineRead = pRAcc->GetScanline(nY);
- for( long nX = 0; nX < nWidth; nX++ )
- {
- const BitmapColor aCol( pRAcc->GetPixelFromData( pScanlineRead, nX ) );
- pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
- }
- }
- }
-
- // create palette via median cut
- BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
- ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
- nColCount, nWidth * nHeight, nIndex );
-
- // do mapping of colors to palette
- InverseColorMap aMap( aPal );
- pWAcc->SetPalette( aPal );
- for( long nY = 0; nY < nHeight; nY++ )
- {
- Scanline pScanline = pWAcc->GetScanline(nY);
- for( long nX = 0; nX < nWidth; nX++ )
- pWAcc->SetPixelOnData( pScanline, nX, BitmapColor(static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) ))) );
- }
-
- rtl_freeMemory( pColBuf );
- pWAcc.reset();
- bRet = true;
- }
-
- pRAcc.reset();
-
- if( bRet )
- {
- const MapMode aMap( maPrefMapMode );
- const Size aSize( maPrefSize );
-
- *this = aNewBmp;
- maPrefMapMode = aMap;
- maPrefSize = aSize;
- }
- }
-
- return bRet;
-}
-
-void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
- long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
- long nColors, long nPixels, long& rIndex )
-{
- if( !nPixels )
- return;
-
- BitmapColor aCol;
- const long nRLen = nR2 - nR1;
- const long nGLen = nG2 - nG1;
- const long nBLen = nB2 - nB1;
- sal_uLong* pBuf = pColBuf;
-
- if( !nRLen && !nGLen && !nBLen )
- {
- if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
- {
- aCol.SetRed( static_cast<sal_uInt8>( nR1 << 3 ) );
- aCol.SetGreen( static_cast<sal_uInt8>( nG1 << 3 ) );
- aCol.SetBlue( static_cast<sal_uInt8>( nB1 << 3 ) );
- rPal[ static_cast<sal_uInt16>(rIndex++) ] = aCol;
- }
- }
- else
- {
- if( 1 == nColors || 1 == nPixels )
- {
- long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
-
- for( long nR = nR1; nR <= nR2; nR++ )
- {
- for( long nG = nG1; nG <= nG2; nG++ )
- {
- for( long nB = nB1; nB <= nB2; nB++ )
- {
- nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
-
- if( nPixSum )
- {
- nRSum += nR * nPixSum;
- nGSum += nG * nPixSum;
- nBSum += nB * nPixSum;
- }
- }
- }
- }
-
- aCol.SetRed( static_cast<sal_uInt8>( ( nRSum / nPixels ) << 3 ) );
- aCol.SetGreen( static_cast<sal_uInt8>( ( nGSum / nPixels ) << 3 ) );
- aCol.SetBlue( static_cast<sal_uInt8>( ( nBSum / nPixels ) << 3 ) );
- rPal[ static_cast<sal_uInt16>(rIndex++) ] = aCol;
- }
- else
- {
- const long nTest = ( nPixels >> 1 );
- long nPixOld = 0;
- long nPixNew = 0;
-
- if( nBLen > nGLen && nBLen > nRLen )
- {
- long nB = nB1 - 1;
-
- while( nPixNew < nTest )
- {
- nB++;
- nPixOld = nPixNew;
- for( long nR = nR1; nR <= nR2; nR++ )
- for( long nG = nG1; nG <= nG2; nG++ )
- nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
- }
-
- if( nB < nB2 )
- {
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
- }
- else
- {
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
- }
- }
- else if( nGLen > nRLen )
- {
- long nG = nG1 - 1;
-
- while( nPixNew < nTest )
- {
- nG++;
- nPixOld = nPixNew;
- for( long nR = nR1; nR <= nR2; nR++ )
- for( long nB = nB1; nB <= nB2; nB++ )
- nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
- }
-
- if( nG < nG2 )
- {
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
- }
- else
- {
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
- ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
- }
- }
- else
- {
- long nR = nR1 - 1;
-
- while( nPixNew < nTest )
- {
- nR++;
- nPixOld = nPixNew;
- for( long nG = nG1; nG <= nG2; nG++ )
- for( long nB = nB1; nB <= nB2; nB++ )
- nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
- }
-
- if( nR < nR2 )
- {
- ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
- ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
- }
- else
- {
- ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
- ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
- }
- }
- }
- }
-}
void Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, const Link<long,void>* pProgress )
{
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
index 5b03870578cd..2f6f9bfb5870 100644
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -446,11 +446,6 @@ bool BitmapEx::Convert( BmpConversion eConversion )
return !!maBitmap && maBitmap.Convert( eConversion );
}
-bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount )
-{
- return !!maBitmap && maBitmap.ReduceColors( nNewColorCount, BMP_REDUCE_POPULAR );
-}
-
void BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, bool bExpandTransparent )
{
bool bRet = false;
diff --git a/vcl/unx/generic/dtrans/bmp.cxx b/vcl/unx/generic/dtrans/bmp.cxx
index c72e93100eb4..b6b5d1888aa1 100644
--- a/vcl/unx/generic/dtrans/bmp.cxx
+++ b/vcl/unx/generic/dtrans/bmp.cxx
@@ -17,20 +17,23 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include <unistd.h>
-#include <cstdio>
-#include <cstring>
-
-#include "bmp.hxx"
-
-#include "X11_selection.hxx"
-#include <unx/x11/xlimits.hxx>
-
#include <sal/macros.h>
#include <tools/stream.hxx>
+
#include <vcl/dibtools.hxx>
#include <vcl/svapp.hxx>
#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/BitmapSimpleColorQuantizationFilter.hxx>
+
+#include <unx/x11/xlimits.hxx>
+
+#include "bmp.hxx"
+#include "X11_selection.hxx"
+
+#include <unistd.h>
+#include <cstdio>
+#include <cstring>
using namespace x11;
@@ -753,11 +756,21 @@ css::uno::Sequence<sal_Int8> x11::convertBitmapDepth(
bm.Convert(BmpConversion::N1BitThreshold);
break;
case 4:
- bm.ReduceColors(1<<4);
- break;
+ {
+ BitmapEx aBmpEx(bm);
+ BitmapFilter::Filter(aBmpEx, BitmapSimpleColorQuantizationFilter(1<<4));
+ bm = aBmpEx.GetBitmap();
+ }
+ break;
+
case 8:
- bm.ReduceColors(1<<8);
- break;
+ {
+ BitmapEx aBmpEx(bm);
+ BitmapFilter::Filter(aBmpEx, BitmapSimpleColorQuantizationFilter(1<<8));
+ bm = aBmpEx.GetBitmap();
+ }
+ break;
+
case 24:
bm.Convert(BmpConversion::N24Bit);
break;