summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/BitmapMonochromeMatrixFilter.hxx28
-rw-r--r--include/vcl/bitmap.hxx1
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/source/bitmap/BitmapMonochromeMatrixFilter.cxx142
-rw-r--r--vcl/source/gdi/bitmap3.cxx9
5 files changed, 181 insertions, 0 deletions
diff --git a/include/vcl/BitmapMonochromeMatrixFilter.hxx b/include/vcl/BitmapMonochromeMatrixFilter.hxx
new file mode 100644
index 000000000000..58d1d917f65d
--- /dev/null
+++ b/include/vcl/BitmapMonochromeMatrixFilter.hxx
@@ -0,0 +1,28 @@
+/* -*- 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_BITMAPMONOCHROMEMATRIXFILTER_HXX
+#define INCLUDED_INCLUDE_VCL_BITMAPMONOCHROMEMATRIXFILTER_HXX
+
+#include <vcl/BitmapFilter.hxx>
+
+class VCL_DLLPUBLIC BitmapMonochromeMatrixFilter final : public BitmapFilter
+{
+public:
+ /** Convert to monochrome (1-bit) bitmap using dithering
+ */
+ BitmapMonochromeMatrixFilter() {}
+
+ virtual BitmapEx execute(BitmapEx const& rBitmapEx) const override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index 3d57e5dfe741..72473ecbed30 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -66,6 +66,7 @@ enum class BmpConversion
{
NNONE,
N1BitThreshold,
+ N1BitMatrix, // aka Dithered, used in export to bitmap
N4BitGreys,
N4BitColors,
N8BitGreys,
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 38bce206f72f..6635c3fcdc43 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -329,6 +329,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/bitmap/bitmapfilter \
vcl/source/bitmap/BitmapAlphaClampFilter \
vcl/source/bitmap/BitmapMonochromeFilter \
+ vcl/source/bitmap/BitmapMonochromeMatrixFilter \
vcl/source/bitmap/BitmapSmoothenFilter \
vcl/source/bitmap/BitmapLightenFilter \
vcl/source/bitmap/BitmapDisabledImageFilter \
diff --git a/vcl/source/bitmap/BitmapMonochromeMatrixFilter.cxx b/vcl/source/bitmap/BitmapMonochromeMatrixFilter.cxx
new file mode 100644
index 000000000000..12e72ad1c710
--- /dev/null
+++ b/vcl/source/bitmap/BitmapMonochromeMatrixFilter.cxx
@@ -0,0 +1,142 @@
+/* -*- 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/BitmapMonochromeMatrixFilter.hxx>
+#include <vcl/bitmapaccess.hxx>
+
+#include <bitmapwriteaccess.hxx>
+
+static void ImplCreateDitherMatrix(sal_uInt8 (*pDitherMatrix)[16][16])
+{
+ const double fVal = 3.125;
+ const double fVal16 = fVal / 16.;
+ const double fValScale = 254.;
+ sal_uInt16 pMtx[16][16];
+ sal_uInt16 nMax = 0;
+ static const sal_uInt8 pMagic[4][4] = { {
+ 0,
+ 14,
+ 3,
+ 13,
+ },
+ {
+ 11,
+ 5,
+ 8,
+ 6,
+ },
+ {
+ 12,
+ 2,
+ 15,
+ 1,
+ },
+ { 7, 9, 4, 10 } };
+
+ // Build MagicSquare
+ for (long i = 0; i < 4; i++)
+ for (long j = 0; j < 4; j++)
+ for (long k = 0; k < 4; k++)
+ for (long l = 0; l < 4; l++)
+ {
+ pMtx[(k << 2) + i][(l << 2) + j] = static_cast<sal_uInt16>(
+ 0.5 + pMagic[i][j] * fVal + pMagic[k][l] * fVal16);
+ nMax = std::max(pMtx[(k << 2) + i][(l << 2) + j], nMax);
+ }
+
+ // Scale to interval [0;254]
+ double tmp = fValScale / nMax;
+ for (long i = 0; i < 16; i++)
+ for (long j = 0; j < 16; j++)
+ (*pDitherMatrix)[i][j] = static_cast<sal_uInt8>(tmp * pMtx[i][j]);
+}
+
+BitmapEx BitmapMonochromeMatrixFilter::execute(BitmapEx const& aBitmapEx) const
+{
+ Bitmap aBitmap = aBitmapEx.GetBitmap();
+ Bitmap::ScopedReadAccess pReadAcc(aBitmap);
+ bool bRet = false;
+
+ if (pReadAcc)
+ {
+ Bitmap aNewBmp(aBitmap.GetSizePixel(), 1);
+ BitmapScopedWriteAccess pWriteAcc(aNewBmp);
+
+ if (pWriteAcc)
+ {
+ const BitmapColor aBlack(pWriteAcc->GetBestMatchingColor(COL_BLACK));
+ const BitmapColor aWhite(pWriteAcc->GetBestMatchingColor(COL_WHITE));
+ const long nWidth = pWriteAcc->Width();
+ const long nHeight = pWriteAcc->Height();
+ sal_uInt8 pDitherMatrix[16][16];
+
+ ImplCreateDitherMatrix(&pDitherMatrix);
+
+ if (pReadAcc->HasPalette())
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ for (long nX = 0, nModY = nY % 16; nX < nWidth; nX++)
+ {
+ const sal_uInt8 cIndex = pReadAcc->GetPixelIndex(nY, nX);
+ if (pReadAcc->GetPaletteColor(cIndex).GetLuminance()
+ > pDitherMatrix[nModY][nX % 16])
+ {
+ pWriteAcc->SetPixel(nY, nX, aWhite);
+ }
+ else
+ pWriteAcc->SetPixel(nY, nX, aBlack);
+ }
+ }
+ }
+ else
+ {
+ for (long nY = 0; nY < nHeight; nY++)
+ {
+ for (long nX = 0, nModY = nY % 16; nX < nWidth; nX++)
+ {
+ if (pReadAcc->GetPixel(nY, nX).GetLuminance()
+ > pDitherMatrix[nModY][nX % 16])
+ {
+ pWriteAcc->SetPixel(nY, nX, aWhite);
+ }
+ else
+ pWriteAcc->SetPixel(nY, nX, aBlack);
+ }
+ }
+ }
+
+ pWriteAcc.reset();
+ bRet = true;
+ }
+
+ pReadAcc.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/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index e35636044f3f..159b5feed3fa 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -30,6 +30,7 @@
#include <vcl/opengl/OpenGLHelper.hxx>
#endif
#include <vcl/BitmapMonochromeFilter.hxx>
+#include <vcl/BitmapMonochromeMatrixFilter.hxx>
#include <BitmapScaleSuperFilter.hxx>
#include <BitmapScaleConvolutionFilter.hxx>
@@ -255,6 +256,14 @@ bool Bitmap::Convert( BmpConversion eConversion )
}
break;
+ case BmpConversion::N1BitMatrix:
+ {
+ BitmapEx aBmpEx(*this);
+ bRet = BitmapFilter::Filter(aBmpEx, BitmapMonochromeMatrixFilter());
+ *this = aBmpEx.GetBitmap();
+ }
+ break;
+
case BmpConversion::N4BitGreys:
bRet = ImplMakeGreyscales( 16 );
break;