/* -*- 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 #include #include #include #include BitmapReadAccess::BitmapReadAccess(Bitmap& rBitmap, BitmapAccessMode nMode) : BitmapInfoAccess(rBitmap, nMode) , mFncGetPixel(nullptr) , mFncSetPixel(nullptr) { if (!mpBuffer) return; const std::shared_ptr& 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() { auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities(); return pBackendCapabilities->mbSupportsBitmap32; } 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(fX)); const sal_Int64 nY(static_cast(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(fX)); const sal_Int32 nY(static_cast(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: */