diff options
-rw-r--r-- | include/vcl/BitmapMonochromeMatrixFilter.hxx | 28 | ||||
-rw-r--r-- | include/vcl/bitmap.hxx | 1 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/source/bitmap/BitmapMonochromeMatrixFilter.cxx | 142 | ||||
-rw-r--r-- | vcl/source/gdi/bitmap3.cxx | 9 |
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; |