[Libreoffice-commits] core.git: cui/source include/vcl sd/source vcl/Library_vcl.mk vcl/source vcl/unx
Chris Sherlock
chris.sherlock79 at gmail.com
Fri Apr 20 06:36:45 UTC 2018
cui/source/dialogs/cuigrfflt.cxx | 3
include/vcl/BitmapColorQuantizationFilter.hxx | 45 +
include/vcl/BitmapMedianColorQuantizationFilter.hxx | 49 +
include/vcl/BitmapSimpleColorQuantizationFilter.hxx | 39 +
include/vcl/bitmap.hxx | 28
include/vcl/bitmapex.hxx | 9
sd/source/ui/dlg/vectdlg.cxx | 9
vcl/Library_vcl.mk | 3
vcl/source/bitmap/BitmapColorQuantizationFilter.cxx | 229 ++++++
vcl/source/bitmap/BitmapMedianColorQuantizationFilter.cxx | 300 ++++++++
vcl/source/bitmap/BitmapSimpleColorQuantizationFilter.cxx | 108 +++
vcl/source/gdi/animate.cxx | 14
vcl/source/gdi/bitmap3.cxx | 493 --------------
vcl/source/gdi/bitmapex.cxx | 5
vcl/unx/generic/dtrans/bmp.cxx | 39 -
15 files changed, 817 insertions(+), 556 deletions(-)
New commits:
commit 900b1109a94c1d72c17ab429da1b6c6c2bf79ac6
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date: Tue Apr 17 22:06:20 2018 +1000
vcl: move Bitmap{Ex}::ReduceColors() to BitmapColorQuantizationFilter class
Change-Id: I32b58e8d451e7303e94788a546a5b5f9a5bb4590
Reviewed-on: https://gerrit.libreoffice.org/53037
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/cui/source/dialogs/cuigrfflt.cxx b/cui/source/dialogs/cuigrfflt.cxx
index 9f0f60d27aa3..406e2b6a7f7f 100644
--- a/cui/source/dialogs/cuigrfflt.cxx
+++ b/cui/source/dialogs/cuigrfflt.cxx
@@ -17,6 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <vcl/BitmapColorQuantizationFilter.hxx>
#include <vcl/builderfactory.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
@@ -502,7 +503,7 @@ Graphic GraphicFilterPoster::GetFilteredGraphic( const Graphic& rGraphic, double
{
BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
- if( aBmpEx.ReduceColors( nPosterCount ) )
+ if (BitmapFilter::Filter(aBmpEx, BitmapColorQuantizationFilter(nPosterCount)))
aRet = aBmpEx;
}
diff --git a/include/vcl/BitmapColorQuantizationFilter.hxx b/include/vcl/BitmapColorQuantizationFilter.hxx
new file mode 100644
index 000000000000..e695567a7bc0
--- /dev/null
+++ b/include/vcl/BitmapColorQuantizationFilter.hxx
@@ -0,0 +1,45 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_INCLUDE_VCL_BITMAPCOLORQUANTIZATIONFILTER_HXX
+#define INCLUDED_INCLUDE_VCL_BITMAPCOLORQUANTIZATIONFILTER_HXX
+
+#include <tools/color.hxx>
+
+#include <vcl/BitmapFilter.hxx>
+
+class VCL_DLLPUBLIC BitmapColorQuantizationFilter : public BitmapFilter
+{
+public:
+ /** Reduce number of colors for the bitmap using the POPULAR algorithm
+
+ @param nNewColorCount
+ Maximal number of bitmap colors after the reduce operation
+ */
+ BitmapColorQuantizationFilter(sal_uInt16 nNewColorCount)
+ : mnNewColorCount(nNewColorCount)
+ {
+ }
+
+ virtual BitmapEx execute(BitmapEx const& rBitmapEx) override;
+
+private:
+ sal_uInt16 mnNewColorCount;
+
+ struct PopularColorCount
+ {
+ sal_uInt32 mnIndex;
+ sal_uInt32 mnCount;
+ };
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/BitmapMedianColorQuantizationFilter.hxx b/include/vcl/BitmapMedianColorQuantizationFilter.hxx
new file mode 100644
index 000000000000..c15b0ac80ac7
--- /dev/null
+++ b/include/vcl/BitmapMedianColorQuantizationFilter.hxx
@@ -0,0 +1,49 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_INCLUDE_VCL_BITMAPMEDIANCOLORQUANTIZATIONFILTER_HXX
+#define INCLUDED_INCLUDE_VCL_BITMAPMEDIANCOLORQUANTIZATIONFILTER_HXX
+
+#include <tools/color.hxx>
+
+#include <vcl/BitmapFilter.hxx>
+
+#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)))
+
+class VCL_DLLPUBLIC BitmapMedianColorQuantizationFilter : public BitmapFilter
+{
+public:
+ /** Reduce number of colors for the bitmap using the median algorithm
+
+ @param nNewColorCount
+ Maximal number of bitmap colors after the reduce operation
+ */
+ BitmapMedianColorQuantizationFilter(sal_uInt16 nNewColorCount)
+ : mnNewColorCount(nNewColorCount)
+ {
+ }
+
+ virtual BitmapEx execute(BitmapEx const& rBitmapEx) override;
+
+private:
+ sal_uInt16 mnNewColorCount;
+
+ void 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);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/BitmapSimpleColorQuantizationFilter.hxx b/include/vcl/BitmapSimpleColorQuantizationFilter.hxx
new file mode 100644
index 000000000000..b05b13fe6896
--- /dev/null
+++ b/include/vcl/BitmapSimpleColorQuantizationFilter.hxx
@@ -0,0 +1,39 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_INCLUDE_VCL_BITMAPSIMPLECOLORQUANTIZATIONFILTER_HXX
+#define INCLUDED_INCLUDE_VCL_BITMAPSIMPLECOLORQUANTIZATIONFILTER_HXX
+
+#include <tools/color.hxx>
+
+#include <vcl/BitmapFilter.hxx>
+
+class VCL_DLLPUBLIC BitmapSimpleColorQuantizationFilter : public BitmapFilter
+{
+public:
+ /** Reduce number of colors for the bitmap using the POPULAR algorithm
+
+ @param nNewColorCount
+ Maximal number of bitmap colors after the reduce operation
+ */
+ BitmapSimpleColorQuantizationFilter(sal_uInt16 nNewColorCount)
+ : mnNewColorCount(nNewColorCount)
+ {
+ }
+
+ virtual BitmapEx execute(BitmapEx const& rBitmapEx) override;
+
+private:
+ sal_uInt16 mnNewColorCount;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index 6370a63d116f..ad1efb8bb862 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -89,12 +89,6 @@ enum class BmpCombine
Or, And
};
-enum BmpReduce
-{
- BMP_REDUCE_SIMPLE = 0,
- BMP_REDUCE_POPULAR = 1
-};
-
enum class BmpFilter
{
Smooth = 0,
@@ -285,20 +279,6 @@ public:
*/
bool MakeMonochrome(sal_uInt8 cThreshold);
- /** Reduce number of colors for the bitmap
-
- @param nNewColorCount
- Maximal number of bitmap colors after the reduce operation
-
- @param eReduce
- Algorithm to use for color reduction
-
- @return true the color reduction operation was completed successfully.
- */
- bool ReduceColors(
- sal_uInt16 nNewColorCount,
- BmpReduce eReduce = BMP_REDUCE_SIMPLE );
-
/** Apply a dither algorithm to the bitmap
This method dithers the bitmap inplace, i.e. a true color
@@ -680,14 +660,6 @@ public:
SAL_DLLPRIVATE bool ImplDitherMatrix();
SAL_DLLPRIVATE bool ImplDitherFloyd();
SAL_DLLPRIVATE bool ImplDitherFloyd16();
- SAL_DLLPRIVATE bool ImplReduceSimple( sal_uInt16 nColorCount );
- SAL_DLLPRIVATE bool ImplReducePopular( sal_uInt16 nColorCount );
- SAL_DLLPRIVATE bool ImplReduceMedian( sal_uInt16 nColorCount );
- SAL_DLLPRIVATE void ImplMedianCut(
- sal_uLong* pColBuf,
- BitmapPalette& rPal,
- long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
- long nColors, long nPixels, long& rIndex );
SAL_DLLPRIVATE bool ImplConvolute3( const long* pMatrix );
diff --git a/include/vcl/bitmapex.hxx b/include/vcl/bitmapex.hxx
index 41b1fb28a010..390a2c0eef45 100644
--- a/include/vcl/bitmapex.hxx
+++ b/include/vcl/bitmapex.hxx
@@ -109,15 +109,6 @@ public:
*/
bool Convert( BmpConversion eConversion );
- /** Reduce number of colors for the bitmap using the POPULAR algorithm
-
- @param nNewColorCount
- Maximal number of bitmap colors after the reduce operation
-
- @return true, if the color reduction operation was completed successfully.
- */
- bool ReduceColors( sal_uInt16 nNewColorCount );
-
/** Apply a dither algorithm to the bitmap
This method dithers the bitmap inplace, i.e. a true color
diff --git a/sd/source/ui/dlg/vectdlg.cxx b/sd/source/ui/dlg/vectdlg.cxx
index 2c64760f3265..44ed925dc767 100644
--- a/sd/source/ui/dlg/vectdlg.cxx
+++ b/sd/source/ui/dlg/vectdlg.cxx
@@ -19,13 +19,14 @@
#include <vcl/vclenum.hxx>
#include <vcl/wrkwin.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/BitmapSimpleColorQuantizationFilter.hxx>
#include <DrawDocShell.hxx>
#include <sdmod.hxx>
#include <sdiocmpt.hxx>
#include <vectdlg.hxx>
-#include <vcl/bitmapaccess.hxx>
-#include <vcl/metaact.hxx>
#define VECTORIZE_MAX_EXTENT 512
@@ -140,7 +141,9 @@ Bitmap SdVectorizeDlg::GetPreparedBitmap( Bitmap const & rBmp, Fraction& rScale
else
rScale = Fraction( 1, 1 );
- aNew.ReduceColors( static_cast<sal_uInt16>(m_pNmLayers->GetValue()) );
+ BitmapEx aNewBmpEx(aNew);
+ BitmapFilter::Filter(aNewBmpEx, BitmapSimpleColorQuantizationFilter(static_cast<sal_uInt16>(m_pNmLayers->GetValue())));
+ aNew = aNewBmpEx.GetBitmap();
return aNew;
}
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;
More information about the Libreoffice-commits
mailing list