summaryrefslogtreecommitdiffstats
path: root/vcl/source/bitmap/BitmapReadAccess.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/bitmap/BitmapReadAccess.cxx')
-rw-r--r--vcl/source/bitmap/BitmapReadAccess.cxx550
1 files changed, 550 insertions, 0 deletions
diff --git a/vcl/source/bitmap/BitmapReadAccess.cxx b/vcl/source/bitmap/BitmapReadAccess.cxx
new file mode 100644
index 000000000..6e87debd1
--- /dev/null
+++ b/vcl/source/bitmap/BitmapReadAccess.cxx
@@ -0,0 +1,550 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/BitmapTools.hxx>
+
+#include <salbmp.hxx>
+#include <svdata.hxx>
+#include <salinst.hxx>
+
+BitmapReadAccess::BitmapReadAccess(Bitmap& rBitmap, BitmapAccessMode nMode)
+ : BitmapInfoAccess(rBitmap, nMode)
+ , mFncGetPixel(nullptr)
+ , mFncSetPixel(nullptr)
+{
+ if (!mpBuffer)
+ return;
+
+ const std::shared_ptr<SalBitmap>& xImpBmp = rBitmap.ImplGetSalBitmap();
+ if (!xImpBmp)
+ return;
+
+ maColorMask = mpBuffer->maColorMask;
+
+ mFncGetPixel = GetPixelFunction(mpBuffer->mnFormat);
+ mFncSetPixel = SetPixelFunction(mpBuffer->mnFormat);
+
+ if (!mFncGetPixel || !mFncSetPixel)
+ {
+ xImpBmp->ReleaseBuffer(mpBuffer, mnAccessMode);
+ mpBuffer = nullptr;
+ }
+}
+
+BitmapReadAccess::~BitmapReadAccess() {}
+
+bool Bitmap32IsPreMultipled() { return ImplGetSVData()->mpDefInst->supportsBitmap32(); }
+
+FncGetPixel BitmapReadAccess::GetPixelFunction(ScanlineFormat nFormat)
+{
+ switch (RemoveScanline(nFormat))
+ {
+ case ScanlineFormat::N1BitMsbPal:
+ return GetPixelForN1BitMsbPal;
+ case ScanlineFormat::N1BitLsbPal:
+ return GetPixelForN1BitLsbPal;
+ case ScanlineFormat::N8BitPal:
+ return GetPixelForN8BitPal;
+ case ScanlineFormat::N24BitTcBgr:
+ return GetPixelForN24BitTcBgr;
+ case ScanlineFormat::N24BitTcRgb:
+ return GetPixelForN24BitTcRgb;
+ case ScanlineFormat::N32BitTcAbgr:
+ if (Bitmap32IsPreMultipled())
+ return GetPixelForN32BitTcAbgr;
+ else
+ return GetPixelForN32BitTcXbgr;
+ case ScanlineFormat::N32BitTcArgb:
+ if (Bitmap32IsPreMultipled())
+ return GetPixelForN32BitTcArgb;
+ else
+ return GetPixelForN32BitTcXrgb;
+ case ScanlineFormat::N32BitTcBgra:
+ if (Bitmap32IsPreMultipled())
+ return GetPixelForN32BitTcBgra;
+ else
+ return GetPixelForN32BitTcBgrx;
+ case ScanlineFormat::N32BitTcRgba:
+ if (Bitmap32IsPreMultipled())
+ return GetPixelForN32BitTcRgba;
+ else
+ return GetPixelForN32BitTcRgbx;
+ case ScanlineFormat::N32BitTcMask:
+ return GetPixelForN32BitTcMask;
+
+ default:
+ return nullptr;
+ }
+}
+
+FncSetPixel BitmapReadAccess::SetPixelFunction(ScanlineFormat nFormat)
+{
+ switch (RemoveScanline(nFormat))
+ {
+ case ScanlineFormat::N1BitMsbPal:
+ return SetPixelForN1BitMsbPal;
+ case ScanlineFormat::N1BitLsbPal:
+ return SetPixelForN1BitLsbPal;
+ case ScanlineFormat::N8BitPal:
+ return SetPixelForN8BitPal;
+ case ScanlineFormat::N24BitTcBgr:
+ return SetPixelForN24BitTcBgr;
+ case ScanlineFormat::N24BitTcRgb:
+ return SetPixelForN24BitTcRgb;
+ case ScanlineFormat::N32BitTcAbgr:
+ if (Bitmap32IsPreMultipled())
+ return SetPixelForN32BitTcAbgr;
+ else
+ return SetPixelForN32BitTcXbgr;
+ case ScanlineFormat::N32BitTcArgb:
+ if (Bitmap32IsPreMultipled())
+ return SetPixelForN32BitTcArgb;
+ else
+ return SetPixelForN32BitTcXrgb;
+ case ScanlineFormat::N32BitTcBgra:
+ if (Bitmap32IsPreMultipled())
+ return SetPixelForN32BitTcBgra;
+ else
+ return SetPixelForN32BitTcBgrx;
+ case ScanlineFormat::N32BitTcRgba:
+ if (Bitmap32IsPreMultipled())
+ return SetPixelForN32BitTcRgba;
+ else
+ return SetPixelForN32BitTcRgbx;
+ case ScanlineFormat::N32BitTcMask:
+ return SetPixelForN32BitTcMask;
+
+ default:
+ return nullptr;
+ }
+}
+
+BitmapColor BitmapReadAccess::GetInterpolatedColorWithFallback(double fY, double fX,
+ const BitmapColor& rFallback) const
+{
+ // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
+ // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
+ if (mpBuffer && fX >= 0.0 && fY >= 0.0)
+ {
+ const sal_Int64 nX(static_cast<sal_Int64>(fX));
+ const sal_Int64 nY(static_cast<sal_Int64>(fY));
+
+ if (nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
+ {
+ // get base-return value from inside pixel
+ BitmapColor aRetval(GetColor(nY, nX));
+
+ // calculate deltas and indices for neighbour accesses
+ sal_Int16 nDeltaX((fX - (nX + 0.5)) * 255.0); // [-255 .. 255]
+ sal_Int16 nDeltaY((fY - (nY + 0.5)) * 255.0); // [-255 .. 255]
+ sal_Int16 nIndX(0);
+ sal_Int16 nIndY(0);
+
+ if (nDeltaX > 0)
+ {
+ nIndX = nX + 1;
+ }
+ else
+ {
+ nIndX = nX - 1;
+ nDeltaX = -nDeltaX;
+ }
+
+ if (nDeltaY > 0)
+ {
+ nIndY = nY + 1;
+ }
+ else
+ {
+ nIndY = nY - 1;
+ nDeltaY = -nDeltaY;
+ }
+
+ // get right/left neighbour
+ BitmapColor aXCol(rFallback);
+
+ if (nDeltaX && nIndX >= 0 && nIndX < mpBuffer->mnWidth)
+ {
+ aXCol = GetColor(nY, nIndX);
+ }
+
+ // get top/bottom neighbour
+ BitmapColor aYCol(rFallback);
+
+ if (nDeltaY && nIndY >= 0 && nIndY < mpBuffer->mnHeight)
+ {
+ aYCol = GetColor(nIndY, nX);
+ }
+
+ // get one of four edge neighbours
+ BitmapColor aXYCol(rFallback);
+
+ if (nDeltaX && nDeltaY && nIndX >= 0 && nIndY >= 0 && nIndX < mpBuffer->mnWidth
+ && nIndY < mpBuffer->mnHeight)
+ {
+ aXYCol = GetColor(nIndY, nIndX);
+ }
+
+ // merge return value with right/left neighbour
+ if (aXCol != aRetval)
+ {
+ aRetval.Merge(aXCol, 255 - nDeltaX);
+ }
+
+ // merge top/bottom neighbour with edge
+ if (aYCol != aXYCol)
+ {
+ aYCol.Merge(aXYCol, 255 - nDeltaX);
+ }
+
+ // merge return value with already merged top/bottom neighbour
+ if (aRetval != aYCol)
+ {
+ aRetval.Merge(aYCol, 255 - nDeltaY);
+ }
+
+ return aRetval;
+ }
+ }
+
+ return rFallback;
+}
+
+BitmapColor BitmapReadAccess::GetColorWithFallback(double fY, double fX,
+ const BitmapColor& rFallback) const
+{
+ // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
+ // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
+ if (mpBuffer && fX >= 0.0 && fY >= 0.0)
+ {
+ const sal_Int32 nX(static_cast<sal_Int32>(fX));
+ const sal_Int32 nY(static_cast<sal_Int32>(fY));
+
+ if (nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
+ {
+ return GetColor(nY, nX);
+ }
+ }
+
+ return rFallback;
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN1BitMsbPal(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ return BitmapColor(pScanline[nX >> 3] & (1 << (7 - (nX & 7))) ? 1 : 0);
+}
+
+void BitmapReadAccess::SetPixelForN1BitMsbPal(const Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ sal_uInt8& rByte = pScanline[nX >> 3];
+
+ if (rBitmapColor.GetIndex() & 1)
+ rByte |= 1 << (7 - (nX & 7));
+ else
+ rByte &= ~(1 << (7 - (nX & 7)));
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN1BitLsbPal(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ return BitmapColor(pScanline[nX >> 3] & (1 << (nX & 7)) ? 1 : 0);
+}
+
+void BitmapReadAccess::SetPixelForN1BitLsbPal(const Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ sal_uInt8& rByte = pScanline[nX >> 3];
+
+ if (rBitmapColor.GetIndex() & 1)
+ rByte |= 1 << (nX & 7);
+ else
+ rByte &= ~(1 << (nX & 7));
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN8BitPal(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ return BitmapColor(pScanline[nX]);
+}
+
+void BitmapReadAccess::SetPixelForN8BitPal(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline[nX] = rBitmapColor.GetIndex();
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN24BitTcBgr(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ BitmapColor aBitmapColor;
+
+ pScanline = pScanline + nX * 3;
+ aBitmapColor.SetBlue(*pScanline++);
+ aBitmapColor.SetGreen(*pScanline++);
+ aBitmapColor.SetRed(*pScanline);
+
+ return aBitmapColor;
+}
+
+void BitmapReadAccess::SetPixelForN24BitTcBgr(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + nX * 3;
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetRed();
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN24BitTcRgb(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ BitmapColor aBitmapColor;
+
+ pScanline = pScanline + nX * 3;
+ aBitmapColor.SetRed(*pScanline++);
+ aBitmapColor.SetGreen(*pScanline++);
+ aBitmapColor.SetBlue(*pScanline);
+
+ return aBitmapColor;
+}
+
+void BitmapReadAccess::SetPixelForN24BitTcRgb(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + nX * 3;
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetBlue();
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcAbgr(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 a = *pScanline++;
+ sal_uInt8 b = *pScanline++;
+ sal_uInt8 g = *pScanline++;
+ sal_uInt8 r = *pScanline;
+
+ return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
+ vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcXbgr(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ BitmapColor aBitmapColor;
+
+ pScanline = pScanline + (nX << 2) + 1;
+ aBitmapColor.SetBlue(*pScanline++);
+ aBitmapColor.SetGreen(*pScanline++);
+ aBitmapColor.SetRed(*pScanline);
+
+ return aBitmapColor;
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcAbgr(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 alpha = rBitmapColor.GetAlpha();
+ *pScanline++ = alpha;
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+ *pScanline = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcXbgr(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + (nX << 2);
+ *pScanline++ = 0xFF;
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetRed();
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcArgb(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 a = *pScanline++;
+ sal_uInt8 r = *pScanline++;
+ sal_uInt8 g = *pScanline++;
+ sal_uInt8 b = *pScanline;
+
+ return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
+ vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcXrgb(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ BitmapColor aBitmapColor;
+
+ pScanline = pScanline + (nX << 2) + 1;
+ aBitmapColor.SetRed(*pScanline++);
+ aBitmapColor.SetGreen(*pScanline++);
+ aBitmapColor.SetBlue(*pScanline);
+
+ return aBitmapColor;
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcArgb(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 alpha = rBitmapColor.GetAlpha();
+ *pScanline++ = alpha;
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+ *pScanline = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcXrgb(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + (nX << 2);
+ *pScanline++ = 0xFF;
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline = rBitmapColor.GetBlue();
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcBgra(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 b = *pScanline++;
+ sal_uInt8 g = *pScanline++;
+ sal_uInt8 r = *pScanline++;
+ sal_uInt8 a = *pScanline;
+
+ return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
+ vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcBgrx(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ BitmapColor aBitmapColor;
+
+ pScanline = pScanline + (nX << 2);
+ aBitmapColor.SetBlue(*pScanline++);
+ aBitmapColor.SetGreen(*pScanline++);
+ aBitmapColor.SetRed(*pScanline);
+
+ return aBitmapColor;
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcBgra(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 alpha = rBitmapColor.GetAlpha();
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
+ *pScanline = alpha;
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcBgrx(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + (nX << 2);
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline = 0xFF;
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcRgba(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 r = *pScanline++;
+ sal_uInt8 g = *pScanline++;
+ sal_uInt8 b = *pScanline++;
+ sal_uInt8 a = *pScanline;
+
+ return BitmapColor(ColorAlpha, vcl::bitmap::unpremultiply(r, a),
+ vcl::bitmap::unpremultiply(g, a), vcl::bitmap::unpremultiply(b, a), a);
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcRgbx(ConstScanline pScanline, tools::Long nX,
+ const ColorMask&)
+{
+ BitmapColor aBitmapColor;
+
+ pScanline = pScanline + (nX << 2);
+ aBitmapColor.SetRed(*pScanline++);
+ aBitmapColor.SetGreen(*pScanline++);
+ aBitmapColor.SetBlue(*pScanline);
+
+ return aBitmapColor;
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcRgba(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + nX * 4;
+
+ sal_uInt8 alpha = rBitmapColor.GetAlpha();
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+ *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
+ *pScanline = alpha;
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcRgbx(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor, const ColorMask&)
+{
+ pScanline = pScanline + (nX << 2);
+ *pScanline++ = rBitmapColor.GetRed();
+ *pScanline++ = rBitmapColor.GetGreen();
+ *pScanline++ = rBitmapColor.GetBlue();
+ *pScanline = 0xFF;
+}
+
+BitmapColor BitmapReadAccess::GetPixelForN32BitTcMask(ConstScanline pScanline, tools::Long nX,
+ const ColorMask& rMask)
+{
+ BitmapColor aColor;
+ rMask.GetColorFor32Bit(aColor, pScanline + (nX << 2));
+ return aColor;
+}
+
+void BitmapReadAccess::SetPixelForN32BitTcMask(Scanline pScanline, tools::Long nX,
+ const BitmapColor& rBitmapColor,
+ const ColorMask& rMask)
+{
+ rMask.SetColorFor32Bit(rBitmapColor, pScanline + (nX << 2));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */