Avoid potential negative array index access to cached text.
[LibreOffice.git] / include / vcl / bitmap.hxx
blob8ce5d9cf74fa7abb0902074480c29728d133352a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_VCL_BITMAP_HXX
21 #define INCLUDED_VCL_BITMAP_HXX
23 #include <tools/degree.hxx>
24 #include <tools/helpers.hxx>
25 #include <vcl/checksum.hxx>
26 #include <vcl/dllapi.h>
27 #include <vcl/mapmod.hxx>
28 #include <vcl/region.hxx>
29 #include <vcl/bitmap/BitmapTypes.hxx>
31 #include <o3tl/typed_flags_set.hxx>
33 #include <algorithm>
34 #include <memory>
36 inline sal_uInt8 GAMMA(double _def_cVal, double _def_InvGamma)
38 return FRound(std::clamp(pow(_def_cVal / 255.0, _def_InvGamma) * 255.0, 0.0, 255.0));
41 class Color;
43 template <typename Arg, typename Ret> class Link;
45 enum class BmpMirrorFlags
47 NONE = 0x00,
48 Horizontal = 0x01,
49 Vertical = 0x02,
52 namespace o3tl
54 template<> struct typed_flags<BmpMirrorFlags> : is_typed_flags<BmpMirrorFlags, 0x03> {};
57 enum class BmpScaleFlag
59 // Try to preferably use these.
60 Default,
61 Fast,
62 BestQuality,
63 // Specific algorithms, use only if you really need to (mainly used for tests)
64 NearestNeighbor,
65 Interpolate, // fast, integer bilinear
66 Lanczos,
67 BiCubic,
68 BiLinear
71 #define BMP_COL_TRANS Color( 252, 3, 251 )
73 enum class BmpConversion
75 NNONE,
76 N1BitThreshold,
77 N8BitGreys,
78 N8BitColors,
79 N24Bit,
80 N32Bit,
81 N8BitTrans,
82 N8BitNoConversion // make 8bit without color conversion (e.g. take the red channel)
85 class BitmapInfoAccess;
86 class BitmapReadAccess;
87 class BitmapWriteAccess;
88 class BitmapPalette;
89 class GDIMetaFile;
90 class AlphaMask;
91 class OutputDevice;
92 class SalBitmap;
94 namespace basegfx { class SystemDependentDataHolder; }
96 struct BitmapSystemData
98 #if defined(_WIN32)
99 void* pDIB; // device independent byte buffer
100 #elif defined( MACOSX ) || defined( IOS )
101 // Nothing needed, apparently
102 #else
103 void* aPixmap;
104 #endif
105 int mnWidth;
106 int mnHeight;
109 class SAL_WARN_UNUSED VCL_DLLPUBLIC Bitmap final
111 public:
113 Bitmap();
114 Bitmap( const Bitmap& rBitmap );
115 Bitmap( const Size& rSizePixel, vcl::PixelFormat ePixelFormat, const BitmapPalette* pPal = nullptr );
116 explicit Bitmap( std::shared_ptr<SalBitmap> xSalBitmap );
117 ~Bitmap();
119 Bitmap& operator=( const Bitmap& rBitmap );
120 Bitmap& operator=( Bitmap&& rBitmap ) noexcept;
121 bool operator==( const Bitmap& rBitmap ) const;
122 bool operator!=( const Bitmap& rBitmap ) const { return !operator==(rBitmap); }
124 inline bool IsEmpty() const;
125 void SetEmpty();
127 inline const MapMode& GetPrefMapMode() const;
128 inline void SetPrefMapMode( const MapMode& rMapMode );
130 inline const Size& GetPrefSize() const;
131 inline void SetPrefSize( const Size& rSize );
133 Size GetSizePixel() const;
135 vcl::PixelFormat getPixelFormat() const;
136 inline sal_Int64 GetSizeBytes() const;
137 bool HasGreyPalette8Bit() const;
138 bool HasGreyPaletteAny() const;
139 /** get system dependent bitmap data
141 @param rData
142 The system dependent BitmapSystemData structure to be filled
144 @return true if the bitmap has a valid system object (e.g. not empty)
146 bool GetSystemData( BitmapSystemData& rData ) const;
148 BitmapChecksum GetChecksum() const;
150 Bitmap CreateDisplayBitmap( OutputDevice* pDisplay ) const;
152 static const BitmapPalette&
153 GetGreyPalette( int nEntries );
155 public:
157 /** Convert bitmap format
159 @param eConversion
160 The format this bitmap should be converted to.
162 @return true the conversion was completed successfully.
164 bool Convert( BmpConversion eConversion );
166 /** Apply a Floyd dither algorithm to the bitmap
168 This method dithers the bitmap inplace, i.e. a true color
169 bitmap is converted to a paletted bitmap, reducing the color
170 deviation by error diffusion.
173 bool Dither();
175 /** Crop the bitmap
177 @param rRectPixel
178 A rectangle specifying the crop amounts on all four sides of
179 the bitmap. If the upper left corner of the bitmap is assigned
180 (0,0), then this method cuts out the given rectangle from the
181 bitmap. Note that the rectangle is clipped to the bitmap's
182 dimension, i.e. negative left,top rectangle coordinates or
183 exceeding width or height is ignored.
185 @return true cropping was performed successfully. If
186 nothing had to be cropped, because e.g. the crop rectangle
187 included the bitmap, false is returned, too!
189 bool Crop( const tools::Rectangle& rRectPixel );
191 /** Expand the bitmap by pixel padding
193 @param nDX
194 Number of pixel to pad at the right border of the bitmap
196 @param nDY
197 Number of scanlines to pad at the bottom border of the bitmap
199 @param pInitColor
200 Color to use for padded pixel
202 @return true, if padding was performed successfully. false is
203 not only returned when the operation failed, but also if
204 nothing had to be done, e.g. because nDX and nDY were zero.
206 bool Expand(
207 sal_Int32 nDX, sal_Int32 nDY,
208 const Color* pInitColor = nullptr );
210 /** Copy a rectangular area from another bitmap
212 @param rRectDst
213 Destination rectangle in this bitmap. This is clipped to the
214 bitmap dimensions.
216 @param rRectSrc
217 Source rectangle in pBmpSrc. This is clipped to the source
218 bitmap dimensions. Note further that no scaling takes place
219 during this copy operation, i.e. only the minimum of source
220 and destination rectangle's width and height are used.
222 @param pBmpSrc
223 The source bitmap to copy from. If this argument is NULL, or
224 equal to the object this method is called on, copying takes
225 place within the same bitmap.
227 @return true, if the operation completed successfully. false
228 is not only returned when the operation failed, but also if
229 nothing had to be done, e.g. because one of the rectangles are
230 empty.
232 bool CopyPixel(
233 const tools::Rectangle& rRectDst,
234 const tools::Rectangle& rRectSrc,
235 const Bitmap& rBmpSrc );
237 /** Copy a rectangular area inside this bitmap.
239 @param rRectDst
240 Destination rectangle in this bitmap. This is clipped to the
241 bitmap dimensions.
243 @param rRectSrc
244 Source rectangle. This is clipped to the
245 bitmap dimensions. Note further that no scaling takes place
246 during this copy operation, i.e. only the minimum of source
247 and destination rectangle's width and height are used.
249 @return true, if the operation completed successfully. false
250 is not only returned when the operation failed, but also if
251 nothing had to be done, e.g. because one of the rectangles are
252 empty.
254 bool CopyPixel(
255 const tools::Rectangle& rRectDst,
256 const tools::Rectangle& rRectSrc );
258 bool CopyPixel_AlphaOptimized(
259 const tools::Rectangle& rRectDst,
260 const tools::Rectangle& rRectSrc,
261 const AlphaMask& rBmpSrc );
263 bool CopyPixel_AlphaOptimized(
264 const tools::Rectangle& rRectDst,
265 const tools::Rectangle& rRectSrc );
267 /** Alpha-blend the given bitmap against a specified uniform
268 background color.
270 @attention This method might convert paletted bitmaps to
271 truecolor, to be able to represent every necessary color. Note
272 that during alpha blending, lots of colors not originally
273 included in the bitmap can be generated.
275 @param rAlpha
276 Alpha mask to blend with
278 @param rBackgroundColor
279 Background color to use for every pixel during alpha blending
281 @return true, if blending was successful, false otherwise
283 bool Blend(
284 const AlphaMask& rAlpha,
285 const Color& rBackgroundColor );
287 /** Fill the entire bitmap with the given color
289 @param rFillColor
290 Color value to use for filling
292 @return true, if the operation was completed successfully.
294 bool Erase( const Color& rFillColor );
296 /** Perform the Invert operation on every pixel
298 @return true, if the operation was completed successfully.
300 bool Invert();
302 /** Mirror the bitmap
304 @param nMirrorFlags
305 About which axis (horizontal, vertical, or both) to mirror
307 @return true, if the operation was completed successfully.
309 bool Mirror( BmpMirrorFlags nMirrorFlags );
311 /** Scale the bitmap
313 @param rNewSize
314 The resulting size of the scaled bitmap
316 @param nScaleFlag
317 The algorithm to be used for scaling
319 @return true, if the operation was completed successfully.
321 bool Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
323 /** Scale the bitmap
325 @param rScaleX
326 The scale factor in x direction.
328 @param rScaleY
329 The scale factor in y direction.
331 @param nScaleFlag
332 Method of scaling - it is recommended that either BmpScaleFlag::Default or BmpScaleFlag::BestQuality be used.
334 @return true, if the operation was completed successfully.
336 bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
339 Returns true if bitmap scaling is considered to be fast.
341 Currently this returns true if OpenGL is used for scaling, otherwise false (CPU scaling is slower).
343 @since 4.5
345 static bool HasFastScale();
347 // Adapt the BitCount of rNew to BitCount of total, including grey or color palette
348 // Can be used to create alpha/mask bitmaps after their processing in 24bit
349 void AdaptBitCount(Bitmap& rNew) const;
351 /** Rotate bitmap by the specified angle
353 @param nAngle10
354 The rotation angle in tenth of a degree. The bitmap is always rotated around its center.
356 @param rFillColor
357 The color to use for filling blank areas. During rotation, the
358 bitmap is enlarged such that the whole rotation result fits
359 in. The empty spaces around that rotated original bitmap are
360 then filled with this color.
362 @return true, if the operation was completed successfully.
364 bool Rotate( Degree10 nAngle10, const Color& rFillColor );
366 /** Create on-off mask from bitmap
368 This method creates a bitmask from the bitmap, where every
369 pixel that equals rTransColor is set transparent, the rest
370 opaque.
372 @param rTransColor
373 Color value where the bitmask should be transparent
375 @return the resulting bitmask.
377 Bitmap CreateMask( const Color& rTransColor ) const;
379 /** Create on-off mask from bitmap
381 This method creates a bitmask from the bitmap, where every
382 pixel that equals rTransColor is set transparent, the rest
383 opaque.
385 @param rTransColor
386 Color value where the bitmask should be transparent
388 @param nTol
389 Tolerance value. Specifies the maximal difference between
390 rTransColor and the individual pixel values, such that the
391 corresponding pixel is still regarded as transparent.
393 @return the resulting bitmask.
395 Bitmap CreateMask( const Color& rTransColor, sal_uInt8 nTol ) const;
397 /** Create on-off alpha mask from bitmap
399 This method creates a bitmask from the bitmap, where every
400 pixel that equals rTransColor is set transparent, the rest
401 opaque.
403 @param rTransColor
404 Color value where the bitmask should be transparent
406 @return the resulting bitmask.
408 AlphaMask CreateAlphaMask( const Color& rTransColor ) const;
410 /** Create on-off alpha mask from bitmap
412 This method creates a bitmask from the bitmap, where every
413 pixel that equals rTransColor is set transparent, the rest
414 opaque.
416 @param rTransColor
417 Color value where the bitmask should be transparent
419 @param nTol
420 Tolerance value. Specifies the maximal difference between
421 rTransColor and the individual pixel values, such that the
422 corresponding pixel is still regarded as transparent.
424 @return the resulting bitmask.
426 AlphaMask CreateAlphaMask( const Color& rTransColor, sal_uInt8 nTol ) const;
428 /** Create region of similar colors in a given rectangle
430 @param rColor
431 All pixel which have this color are included in the calculated region
433 @param rRect
434 The rectangle within which matching pixel are looked for. This
435 rectangle is always clipped to the bitmap dimensions.
437 @return the generated region.
439 vcl::Region CreateRegion( const Color& rColor, const tools::Rectangle& rRect ) const;
441 /** Merge bitmap with given background color according to specified alpha mask
443 @param rAlpha
444 Alpha mask specifying the amount of background color to merge in
446 @param rMergeColor
447 Background color to be used for merging
449 @return true, if the operation was completed successfully.
451 bool Replace( const AlphaMask& rAlpha, const Color& rMergeColor );
453 /** Replace all pixel where the given mask/alpha layer is on with the specified color
455 @param rMask
456 Mask specifying which pixel should be replaced
458 @param rReplaceColor
459 Color to be placed in all changed pixel
461 @return true, if the operation was completed successfully.
463 bool ReplaceMask( const AlphaMask& rMask, const Color& rReplaceColor );
465 /** Replace all pixel having the search color with the specified color
467 @param rSearchColor
468 Color specifying which pixel should be replaced
470 @param rReplaceColor
471 Color to be placed in all changed pixel
473 @param nTol
474 Tolerance value. Specifies the maximal difference between
475 rSearchColor and the individual pixel values, such that the
476 corresponding pixel is still regarded a match.
478 @return true, if the operation was completed successfully.
480 bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTol = 0 );
482 /** Replace all pixel having one the search colors with the corresponding replace color
484 @param pSearchColors
485 Array of colors specifying which pixel should be replaced
487 @param rReplaceColors
488 Array of colors to be placed in all changed pixel
490 @param nColorCount
491 Size of the aforementioned color arrays
493 @param pTols
494 Tolerance value. Specifies the maximal difference between
495 pSearchColor colors and the individual pixel values, such that
496 the corresponding pixel is still regarded a match.
498 @return true, if the operation was completed successfully.
500 bool Replace(
501 const Color* pSearchColors,
502 const Color* rReplaceColors,
503 size_t nColorCount,
504 sal_uInt8 const * pTols );
506 /** Convert the bitmap to a meta file
508 This works by putting continuous areas of the same color into
509 polygons painted in this color, by tracing the area's bounding
510 line.
512 @param rMtf
513 The resulting meta file
515 @param cReduce
516 If non-null, minimal size of bound rects for individual polygons. Smaller ones are ignored.
518 @param pProgress
519 A callback for showing the progress of the vectorization
521 void Vectorize(
522 GDIMetaFile& rMtf,
523 sal_uInt8 cReduce,
524 const Link<tools::Long,void>* pProgress );
526 /** Change various global color characteristics
528 @param nLuminancePercent
529 Percent of luminance change, valid range [-100,100]. Values outside this range are clipped to the valid range.
531 @param nContrastPercent
532 Percent of contrast change, valid range [-100,100]. Values outside this range are clipped to the valid range.
534 @param nChannelRPercent
535 Percent of red channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
537 @param nChannelGPercent
538 Percent of green channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
540 @param nChannelBPercent
541 Percent of blue channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
543 @param fGamma
544 Exponent of the gamma function applied to the bitmap. The
545 value 1.0 results in no change, the valid range is
546 (0.0,10.0]. Values outside this range are regarded as 1.0.
548 @param bInvert
549 If true, invert the channel values with the logical 'not' operator
551 @param msoBrightness
552 Use the same formula for brightness as used by MSOffice.
554 @return true, if the operation was completed successfully.
556 bool Adjust(
557 short nLuminancePercent,
558 short nContrastPercent = 0,
559 short nChannelRPercent = 0,
560 short nChannelGPercent = 0,
561 short nChannelBPercent = 0,
562 double fGamma = 1.0,
563 bool bInvert = false,
564 bool msoBrightness = false );
566 /** Remove existing blending against COL_WHITE based on given AlphaMask
568 Inside convertToBitmapEx the content gets rendered to RGB target (no 'A'),
569 so it gets blended against the start condition of the target device which
570 is blank (usually white background, but others may be used).
571 Usually rendering to RGB is sufficient (e.g. EditViews), but for conversion
572 to BitmapEx the alpha channel is needed to e.g. allow export/conversion to
573 pixel target formats which support Alpha, e.g. PNG.
574 It is possible though to create the fully valid and correct AlphaChannel.
575 If the content, the start condition and the alpha values are known it is
576 possible to calculate back ("remove") the white blending from the result,
577 and this is what this method does.
579 @param rColor
580 The Color we know this Bitmap is blended against (usually COL_WHITE)
582 @param rAlphaMask
583 The AlphaMask which was used to blend white against this
585 void RemoveBlendedStartColor(
586 const Color& rColor,
587 const AlphaMask& rAlphaMask);
589 // access to SystemDependentDataHolder, to support overload in derived class(es)
590 const basegfx::SystemDependentDataHolder* accessSystemDependentDataHolder() const;
592 public:
593 /** ReassignWithSize and recalculate bitmap.
595 ReassignWithSizes the bitmap, and recalculates the bitmap size based on the new bitmap.
597 @param rBitmap Bitmap to reassign and use for size calculation
599 SAL_DLLPRIVATE void ReassignWithSize(const Bitmap& rBitmap);
601 SAL_DLLPRIVATE void ImplMakeUnique();
602 const std::shared_ptr<SalBitmap>& ImplGetSalBitmap() const { return mxSalBmp; }
603 SAL_DLLPRIVATE void ImplSetSalBitmap( const std::shared_ptr<SalBitmap>& xImpBmp );
605 SAL_DLLPRIVATE bool ImplMakeGreyscales();
607 private:
608 SAL_DLLPRIVATE bool ImplConvertUp(vcl::PixelFormat ePixelFormat, Color const* pExtColor = nullptr);
609 SAL_DLLPRIVATE bool ImplConvertDown8BPP(Color const* pExtColor = nullptr);
611 private:
612 std::shared_ptr<SalBitmap> mxSalBmp;
613 MapMode maPrefMapMode;
614 Size maPrefSize;
617 inline bool Bitmap::IsEmpty() const
619 return( mxSalBmp == nullptr );
622 inline const MapMode& Bitmap::GetPrefMapMode() const
624 return maPrefMapMode;
627 inline void Bitmap::SetPrefMapMode( const MapMode& rMapMode )
629 maPrefMapMode = rMapMode;
632 inline const Size& Bitmap::GetPrefSize() const
634 return maPrefSize;
637 inline void Bitmap::SetPrefSize( const Size& rSize )
639 maPrefSize = rSize;
642 inline sal_Int64 Bitmap::GetSizeBytes() const
644 const auto aSizePixel = GetSizePixel();
645 const sal_Int64 aBitCount = vcl::pixelFormatBitCount(getPixelFormat());
646 sal_Int64 aSizeInBytes = (aSizePixel.Width() * aSizePixel.Height() * aBitCount) / 8;
647 return aSizeInBytes;
650 #endif // INCLUDED_VCL_BITMAP_HXX
652 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */