diff options
Diffstat (limited to '')
-rw-r--r-- | include/vcl/bitmap.hxx | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx new file mode 100644 index 0000000000..8ce5d9cf74 --- /dev/null +++ b/include/vcl/bitmap.hxx @@ -0,0 +1,652 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_VCL_BITMAP_HXX +#define INCLUDED_VCL_BITMAP_HXX + +#include <tools/degree.hxx> +#include <tools/helpers.hxx> +#include <vcl/checksum.hxx> +#include <vcl/dllapi.h> +#include <vcl/mapmod.hxx> +#include <vcl/region.hxx> +#include <vcl/bitmap/BitmapTypes.hxx> + +#include <o3tl/typed_flags_set.hxx> + +#include <algorithm> +#include <memory> + +inline sal_uInt8 GAMMA(double _def_cVal, double _def_InvGamma) +{ + return FRound(std::clamp(pow(_def_cVal / 255.0, _def_InvGamma) * 255.0, 0.0, 255.0)); +} + +class Color; + +template <typename Arg, typename Ret> class Link; + +enum class BmpMirrorFlags +{ + NONE = 0x00, + Horizontal = 0x01, + Vertical = 0x02, +}; + +namespace o3tl +{ + template<> struct typed_flags<BmpMirrorFlags> : is_typed_flags<BmpMirrorFlags, 0x03> {}; +} + +enum class BmpScaleFlag +{ +// Try to preferably use these. + Default, + Fast, + BestQuality, +// Specific algorithms, use only if you really need to (mainly used for tests) + NearestNeighbor, + Interpolate, // fast, integer bilinear + Lanczos, + BiCubic, + BiLinear +}; + +#define BMP_COL_TRANS Color( 252, 3, 251 ) + +enum class BmpConversion +{ + NNONE, + N1BitThreshold, + N8BitGreys, + N8BitColors, + N24Bit, + N32Bit, + N8BitTrans, + N8BitNoConversion // make 8bit without color conversion (e.g. take the red channel) +}; + +class BitmapInfoAccess; +class BitmapReadAccess; +class BitmapWriteAccess; +class BitmapPalette; +class GDIMetaFile; +class AlphaMask; +class OutputDevice; +class SalBitmap; + +namespace basegfx { class SystemDependentDataHolder; } + +struct BitmapSystemData +{ + #if defined(_WIN32) + void* pDIB; // device independent byte buffer + #elif defined( MACOSX ) || defined( IOS ) + // Nothing needed, apparently + #else + void* aPixmap; + #endif + int mnWidth; + int mnHeight; +}; + +class SAL_WARN_UNUSED VCL_DLLPUBLIC Bitmap final +{ +public: + + Bitmap(); + Bitmap( const Bitmap& rBitmap ); + Bitmap( const Size& rSizePixel, vcl::PixelFormat ePixelFormat, const BitmapPalette* pPal = nullptr ); + explicit Bitmap( std::shared_ptr<SalBitmap> xSalBitmap ); + ~Bitmap(); + + Bitmap& operator=( const Bitmap& rBitmap ); + Bitmap& operator=( Bitmap&& rBitmap ) noexcept; + bool operator==( const Bitmap& rBitmap ) const; + bool operator!=( const Bitmap& rBitmap ) const { return !operator==(rBitmap); } + + inline bool IsEmpty() const; + void SetEmpty(); + + inline const MapMode& GetPrefMapMode() const; + inline void SetPrefMapMode( const MapMode& rMapMode ); + + inline const Size& GetPrefSize() const; + inline void SetPrefSize( const Size& rSize ); + + Size GetSizePixel() const; + + vcl::PixelFormat getPixelFormat() const; + inline sal_Int64 GetSizeBytes() const; + bool HasGreyPalette8Bit() const; + bool HasGreyPaletteAny() const; + /** get system dependent bitmap data + + @param rData + The system dependent BitmapSystemData structure to be filled + + @return true if the bitmap has a valid system object (e.g. not empty) + */ + bool GetSystemData( BitmapSystemData& rData ) const; + + BitmapChecksum GetChecksum() const; + + Bitmap CreateDisplayBitmap( OutputDevice* pDisplay ) const; + + static const BitmapPalette& + GetGreyPalette( int nEntries ); + +public: + + /** Convert bitmap format + + @param eConversion + The format this bitmap should be converted to. + + @return true the conversion was completed successfully. + */ + bool Convert( BmpConversion eConversion ); + + /** Apply a Floyd dither algorithm to the bitmap + + This method dithers the bitmap inplace, i.e. a true color + bitmap is converted to a paletted bitmap, reducing the color + deviation by error diffusion. + + */ + bool Dither(); + + /** Crop the bitmap + + @param rRectPixel + A rectangle specifying the crop amounts on all four sides of + the bitmap. If the upper left corner of the bitmap is assigned + (0,0), then this method cuts out the given rectangle from the + bitmap. Note that the rectangle is clipped to the bitmap's + dimension, i.e. negative left,top rectangle coordinates or + exceeding width or height is ignored. + + @return true cropping was performed successfully. If + nothing had to be cropped, because e.g. the crop rectangle + included the bitmap, false is returned, too! + */ + bool Crop( const tools::Rectangle& rRectPixel ); + + /** Expand the bitmap by pixel padding + + @param nDX + Number of pixel to pad at the right border of the bitmap + + @param nDY + Number of scanlines to pad at the bottom border of the bitmap + + @param pInitColor + Color to use for padded pixel + + @return true, if padding was performed successfully. false is + not only returned when the operation failed, but also if + nothing had to be done, e.g. because nDX and nDY were zero. + */ + bool Expand( + sal_Int32 nDX, sal_Int32 nDY, + const Color* pInitColor = nullptr ); + + /** Copy a rectangular area from another bitmap + + @param rRectDst + Destination rectangle in this bitmap. This is clipped to the + bitmap dimensions. + + @param rRectSrc + Source rectangle in pBmpSrc. This is clipped to the source + bitmap dimensions. Note further that no scaling takes place + during this copy operation, i.e. only the minimum of source + and destination rectangle's width and height are used. + + @param pBmpSrc + The source bitmap to copy from. If this argument is NULL, or + equal to the object this method is called on, copying takes + place within the same bitmap. + + @return true, if the operation completed successfully. false + is not only returned when the operation failed, but also if + nothing had to be done, e.g. because one of the rectangles are + empty. + */ + bool CopyPixel( + const tools::Rectangle& rRectDst, + const tools::Rectangle& rRectSrc, + const Bitmap& rBmpSrc ); + + /** Copy a rectangular area inside this bitmap. + + @param rRectDst + Destination rectangle in this bitmap. This is clipped to the + bitmap dimensions. + + @param rRectSrc + Source rectangle. This is clipped to the + bitmap dimensions. Note further that no scaling takes place + during this copy operation, i.e. only the minimum of source + and destination rectangle's width and height are used. + + @return true, if the operation completed successfully. false + is not only returned when the operation failed, but also if + nothing had to be done, e.g. because one of the rectangles are + empty. + */ + bool CopyPixel( + const tools::Rectangle& rRectDst, + const tools::Rectangle& rRectSrc ); + + bool CopyPixel_AlphaOptimized( + const tools::Rectangle& rRectDst, + const tools::Rectangle& rRectSrc, + const AlphaMask& rBmpSrc ); + + bool CopyPixel_AlphaOptimized( + const tools::Rectangle& rRectDst, + const tools::Rectangle& rRectSrc ); + + /** Alpha-blend the given bitmap against a specified uniform + background color. + + @attention This method might convert paletted bitmaps to + truecolor, to be able to represent every necessary color. Note + that during alpha blending, lots of colors not originally + included in the bitmap can be generated. + + @param rAlpha + Alpha mask to blend with + + @param rBackgroundColor + Background color to use for every pixel during alpha blending + + @return true, if blending was successful, false otherwise + */ + bool Blend( + const AlphaMask& rAlpha, + const Color& rBackgroundColor ); + + /** Fill the entire bitmap with the given color + + @param rFillColor + Color value to use for filling + + @return true, if the operation was completed successfully. + */ + bool Erase( const Color& rFillColor ); + + /** Perform the Invert operation on every pixel + + @return true, if the operation was completed successfully. + */ + bool Invert(); + + /** Mirror the bitmap + + @param nMirrorFlags + About which axis (horizontal, vertical, or both) to mirror + + @return true, if the operation was completed successfully. + */ + bool Mirror( BmpMirrorFlags nMirrorFlags ); + + /** Scale the bitmap + + @param rNewSize + The resulting size of the scaled bitmap + + @param nScaleFlag + The algorithm to be used for scaling + + @return true, if the operation was completed successfully. + */ + bool Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default ); + + /** Scale the bitmap + + @param rScaleX + The scale factor in x direction. + + @param rScaleY + The scale factor in y direction. + + @param nScaleFlag + Method of scaling - it is recommended that either BmpScaleFlag::Default or BmpScaleFlag::BestQuality be used. + + @return true, if the operation was completed successfully. + */ + bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default ); + + /** + Returns true if bitmap scaling is considered to be fast. + + Currently this returns true if OpenGL is used for scaling, otherwise false (CPU scaling is slower). + + @since 4.5 + */ + static bool HasFastScale(); + + // Adapt the BitCount of rNew to BitCount of total, including grey or color palette + // Can be used to create alpha/mask bitmaps after their processing in 24bit + void AdaptBitCount(Bitmap& rNew) const; + + /** Rotate bitmap by the specified angle + + @param nAngle10 + The rotation angle in tenth of a degree. The bitmap is always rotated around its center. + + @param rFillColor + The color to use for filling blank areas. During rotation, the + bitmap is enlarged such that the whole rotation result fits + in. The empty spaces around that rotated original bitmap are + then filled with this color. + + @return true, if the operation was completed successfully. + */ + bool Rotate( Degree10 nAngle10, const Color& rFillColor ); + + /** Create on-off mask from bitmap + + This method creates a bitmask from the bitmap, where every + pixel that equals rTransColor is set transparent, the rest + opaque. + + @param rTransColor + Color value where the bitmask should be transparent + + @return the resulting bitmask. + */ + Bitmap CreateMask( const Color& rTransColor ) const; + + /** Create on-off mask from bitmap + + This method creates a bitmask from the bitmap, where every + pixel that equals rTransColor is set transparent, the rest + opaque. + + @param rTransColor + Color value where the bitmask should be transparent + + @param nTol + Tolerance value. Specifies the maximal difference between + rTransColor and the individual pixel values, such that the + corresponding pixel is still regarded as transparent. + + @return the resulting bitmask. + */ + Bitmap CreateMask( const Color& rTransColor, sal_uInt8 nTol ) const; + + /** Create on-off alpha mask from bitmap + + This method creates a bitmask from the bitmap, where every + pixel that equals rTransColor is set transparent, the rest + opaque. + + @param rTransColor + Color value where the bitmask should be transparent + + @return the resulting bitmask. + */ + AlphaMask CreateAlphaMask( const Color& rTransColor ) const; + + /** Create on-off alpha mask from bitmap + + This method creates a bitmask from the bitmap, where every + pixel that equals rTransColor is set transparent, the rest + opaque. + + @param rTransColor + Color value where the bitmask should be transparent + + @param nTol + Tolerance value. Specifies the maximal difference between + rTransColor and the individual pixel values, such that the + corresponding pixel is still regarded as transparent. + + @return the resulting bitmask. + */ + AlphaMask CreateAlphaMask( const Color& rTransColor, sal_uInt8 nTol ) const; + + /** Create region of similar colors in a given rectangle + + @param rColor + All pixel which have this color are included in the calculated region + + @param rRect + The rectangle within which matching pixel are looked for. This + rectangle is always clipped to the bitmap dimensions. + + @return the generated region. + */ + vcl::Region CreateRegion( const Color& rColor, const tools::Rectangle& rRect ) const; + + /** Merge bitmap with given background color according to specified alpha mask + + @param rAlpha + Alpha mask specifying the amount of background color to merge in + + @param rMergeColor + Background color to be used for merging + + @return true, if the operation was completed successfully. + */ + bool Replace( const AlphaMask& rAlpha, const Color& rMergeColor ); + + /** Replace all pixel where the given mask/alpha layer is on with the specified color + + @param rMask + Mask specifying which pixel should be replaced + + @param rReplaceColor + Color to be placed in all changed pixel + + @return true, if the operation was completed successfully. + */ + bool ReplaceMask( const AlphaMask& rMask, const Color& rReplaceColor ); + + /** Replace all pixel having the search color with the specified color + + @param rSearchColor + Color specifying which pixel should be replaced + + @param rReplaceColor + Color to be placed in all changed pixel + + @param nTol + Tolerance value. Specifies the maximal difference between + rSearchColor and the individual pixel values, such that the + corresponding pixel is still regarded a match. + + @return true, if the operation was completed successfully. + */ + bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTol = 0 ); + + /** Replace all pixel having one the search colors with the corresponding replace color + + @param pSearchColors + Array of colors specifying which pixel should be replaced + + @param rReplaceColors + Array of colors to be placed in all changed pixel + + @param nColorCount + Size of the aforementioned color arrays + + @param pTols + Tolerance value. Specifies the maximal difference between + pSearchColor colors and the individual pixel values, such that + the corresponding pixel is still regarded a match. + + @return true, if the operation was completed successfully. + */ + bool Replace( + const Color* pSearchColors, + const Color* rReplaceColors, + size_t nColorCount, + sal_uInt8 const * pTols ); + + /** Convert the bitmap to a meta file + + This works by putting continuous areas of the same color into + polygons painted in this color, by tracing the area's bounding + line. + + @param rMtf + The resulting meta file + + @param cReduce + If non-null, minimal size of bound rects for individual polygons. Smaller ones are ignored. + + @param pProgress + A callback for showing the progress of the vectorization + */ + void Vectorize( + GDIMetaFile& rMtf, + sal_uInt8 cReduce, + const Link<tools::Long,void>* pProgress ); + + /** Change various global color characteristics + + @param nLuminancePercent + Percent of luminance change, valid range [-100,100]. Values outside this range are clipped to the valid range. + + @param nContrastPercent + Percent of contrast change, valid range [-100,100]. Values outside this range are clipped to the valid range. + + @param nChannelRPercent + Percent of red channel change, valid range [-100,100]. Values outside this range are clipped to the valid range. + + @param nChannelGPercent + Percent of green channel change, valid range [-100,100]. Values outside this range are clipped to the valid range. + + @param nChannelBPercent + Percent of blue channel change, valid range [-100,100]. Values outside this range are clipped to the valid range. + + @param fGamma + Exponent of the gamma function applied to the bitmap. The + value 1.0 results in no change, the valid range is + (0.0,10.0]. Values outside this range are regarded as 1.0. + + @param bInvert + If true, invert the channel values with the logical 'not' operator + + @param msoBrightness + Use the same formula for brightness as used by MSOffice. + + @return true, if the operation was completed successfully. + */ + bool Adjust( + short nLuminancePercent, + short nContrastPercent = 0, + short nChannelRPercent = 0, + short nChannelGPercent = 0, + short nChannelBPercent = 0, + double fGamma = 1.0, + bool bInvert = false, + bool msoBrightness = false ); + + /** Remove existing blending against COL_WHITE based on given AlphaMask + + Inside convertToBitmapEx the content gets rendered to RGB target (no 'A'), + so it gets blended against the start condition of the target device which + is blank (usually white background, but others may be used). + Usually rendering to RGB is sufficient (e.g. EditViews), but for conversion + to BitmapEx the alpha channel is needed to e.g. allow export/conversion to + pixel target formats which support Alpha, e.g. PNG. + It is possible though to create the fully valid and correct AlphaChannel. + If the content, the start condition and the alpha values are known it is + possible to calculate back ("remove") the white blending from the result, + and this is what this method does. + + @param rColor + The Color we know this Bitmap is blended against (usually COL_WHITE) + + @param rAlphaMask + The AlphaMask which was used to blend white against this + */ + void RemoveBlendedStartColor( + const Color& rColor, + const AlphaMask& rAlphaMask); + + // access to SystemDependentDataHolder, to support overload in derived class(es) + const basegfx::SystemDependentDataHolder* accessSystemDependentDataHolder() const; + +public: + /** ReassignWithSize and recalculate bitmap. + + ReassignWithSizes the bitmap, and recalculates the bitmap size based on the new bitmap. + + @param rBitmap Bitmap to reassign and use for size calculation + */ + SAL_DLLPRIVATE void ReassignWithSize(const Bitmap& rBitmap); + + SAL_DLLPRIVATE void ImplMakeUnique(); + const std::shared_ptr<SalBitmap>& ImplGetSalBitmap() const { return mxSalBmp; } + SAL_DLLPRIVATE void ImplSetSalBitmap( const std::shared_ptr<SalBitmap>& xImpBmp ); + + SAL_DLLPRIVATE bool ImplMakeGreyscales(); + +private: + SAL_DLLPRIVATE bool ImplConvertUp(vcl::PixelFormat ePixelFormat, Color const* pExtColor = nullptr); + SAL_DLLPRIVATE bool ImplConvertDown8BPP(Color const* pExtColor = nullptr); + +private: + std::shared_ptr<SalBitmap> mxSalBmp; + MapMode maPrefMapMode; + Size maPrefSize; +}; + +inline bool Bitmap::IsEmpty() const +{ + return( mxSalBmp == nullptr ); +} + +inline const MapMode& Bitmap::GetPrefMapMode() const +{ + return maPrefMapMode; +} + +inline void Bitmap::SetPrefMapMode( const MapMode& rMapMode ) +{ + maPrefMapMode = rMapMode; +} + +inline const Size& Bitmap::GetPrefSize() const +{ + return maPrefSize; +} + +inline void Bitmap::SetPrefSize( const Size& rSize ) +{ + maPrefSize = rSize; +} + +inline sal_Int64 Bitmap::GetSizeBytes() const +{ + const auto aSizePixel = GetSizePixel(); + const sal_Int64 aBitCount = vcl::pixelFormatBitCount(getPixelFormat()); + sal_Int64 aSizeInBytes = (aSizePixel.Width() * aSizePixel.Height() * aBitCount) / 8; + return aSizeInBytes; +} + +#endif // INCLUDED_VCL_BITMAP_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |