xref: /core/include/vcl/bitmap.hxx (revision e3cc7b94)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #ifndef INCLUDED_VCL_BITMAP_HXX
21 #define INCLUDED_VCL_BITMAP_HXX
22 
23 #include <tools/solar.h>
24 #include <vcl/checksum.hxx>
25 #include <vcl/dllapi.h>
26 #include <vcl/mapmod.hxx>
27 #include <vcl/region.hxx>
28 #include <vcl/scopedbitmapaccess.hxx>
29 #include <o3tl/typed_flags_set.hxx>
30 #include <memory>
31 
32 class Color;
33 
34 template <typename Arg, typename Ret> class Link;
35 
36 enum class BmpMirrorFlags
37 {
38     NONE             = 0x00,
39     Horizontal       = 0x01,
40     Vertical         = 0x02,
41 };
42 
43 namespace o3tl
44 {
45     template<> struct typed_flags<BmpMirrorFlags> : is_typed_flags<BmpMirrorFlags, 0x03> {};
46 }
47 
48 enum class BmpScaleFlag
49 {
50 // Try to preferably use these.
51     Default,
52     Fast,
53     BestQuality,
54 // Specific algorithms, use only if you really need to (mainly used for tests)
55     NearestNeighbor,
56     Interpolate, // fast, integer bilinear
57     Lanczos,
58     BiCubic,
59     BiLinear,
60     Super // bilinear interpolation when supersampling and averaging when subsampling under certain scale
61 };
62 
63 #define BMP_COL_TRANS               Color( 252, 3, 251 )
64 
65 enum class BmpConversion
66 {
67     NNONE,
68     N1BitThreshold,
69     N4BitGreys,
70     N4BitColors,
71     N8BitGreys,
72     N8BitColors,
73     N24Bit,
74     N32Bit,
75     N8BitTrans,
76     N8BitNoConversion // make 8bit without color conversion (e.g. take the red channel)
77 };
78 
79 enum class BmpCombine
80 {
81     Or, And
82 };
83 
84 class   BitmapInfoAccess;
85 class   BitmapReadAccess;
86 class   BitmapWriteAccess;
87 class   BitmapPalette;
88 class   GDIMetaFile;
89 class   AlphaMask;
90 class   OutputDevice;
91 class   SalBitmap;
92 
93 struct BitmapSystemData
94 {
95     #if defined(_WIN32)
96     void* pDIB; // device independent byte buffer
97     #elif defined( MACOSX ) || defined( IOS )
98     // Nothing needed, apparently
99     #else
100     void* aPixmap;
101     #endif
102     int mnWidth;
103     int mnHeight;
104 };
105 
106 class SAL_WARN_UNUSED VCL_DLLPUBLIC Bitmap
107 {
108 public:
109 
110                             Bitmap();
111                             Bitmap( const Bitmap& rBitmap );
112                             Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal = nullptr );
113     explicit                Bitmap( std::shared_ptr<SalBitmap> const & xSalBitmap );
114     virtual                 ~Bitmap();
115 
116     Bitmap&                 operator=( const Bitmap& rBitmap );
117     Bitmap&                 operator=( Bitmap&& rBitmap ) noexcept;
118     inline bool             operator!() const;
119     bool                    operator==( const Bitmap& rBitmap ) const;
120     bool                    operator!=( const Bitmap& rBitmap ) const { return !operator==(rBitmap); }
121 
122     inline bool             IsEmpty() const;
123     void                    SetEmpty();
124 
125     inline const MapMode&   GetPrefMapMode() const;
126     inline void             SetPrefMapMode( const MapMode& rMapMode );
127 
128     inline const Size&      GetPrefSize() const;
129     inline void             SetPrefSize( const Size& rSize );
130 
131     Size                    GetSizePixel() const;
132 
133     sal_uInt16              GetBitCount() const;
134     inline sal_Int64        GetColorCount() const;
135     inline sal_uLong        GetSizeBytes() const;
136     bool                    HasGreyPalette() const;
137     /** get system dependent bitmap data
138 
139         @param rData
140         The system dependent BitmapSystemData structure to be filled
141 
142         @return true if the bitmap has a valid system object (e.g. not empty)
143     */
144     bool                    GetSystemData( BitmapSystemData& rData ) const;
145 
146     BitmapChecksum          GetChecksum() const;
147 
148     Bitmap                  CreateDisplayBitmap( OutputDevice* pDisplay ) const;
149 
150     static const BitmapPalette&
151                             GetGreyPalette( int nEntries );
152 
153 public:
154 
155     /** Convert bitmap format
156 
157         @param eConversion
158         The format this bitmap should be converted to.
159 
160         @return true the conversion was completed successfully.
161      */
162     bool                    Convert( BmpConversion eConversion );
163 
164     /** Apply a Floyd dither algorithm to the bitmap
165 
166      This method dithers the bitmap inplace, i.e. a true color
167      bitmap is converted to a paletted bitmap, reducing the color
168      deviation by error diffusion.
169 
170      */
171     bool                    Dither();
172 
173     /** Crop the bitmap
174 
175         @param rRectPixel
176         A rectangle specifying the crop amounts on all four sides of
177         the bitmap. If the upper left corner of the bitmap is assigned
178         (0,0), then this method cuts out the given rectangle from the
179         bitmap. Note that the rectangle is clipped to the bitmap's
180         dimension, i.e. negative left,top rectangle coordinates or
181         exceeding width or height is ignored.
182 
183         @return true cropping was performed successfully. If
184         nothing had to be cropped, because e.g. the crop rectangle
185         included the bitmap, false is returned, too!
186      */
187     bool                    Crop( const tools::Rectangle& rRectPixel );
188 
189     /** Expand the bitmap by pixel padding
190 
191         @param nDX
192         Number of pixel to pad at the right border of the bitmap
193 
194         @param nDY
195         Number of scanlines to pad at the bottom border of the bitmap
196 
197         @param pInitColor
198         Color to use for padded pixel
199 
200         @return true, if padding was performed successfully. false is
201         not only returned when the operation failed, but also if
202         nothing had to be done, e.g. because nDX and nDY were zero.
203      */
204     bool                    Expand(
205                                 sal_uLong nDX, sal_uLong nDY,
206                                 const Color* pInitColor = nullptr );
207 
208     /** Copy a rectangular area from another bitmap
209 
210         @param rRectDst
211         Destination rectangle in this bitmap. This is clipped to the
212         bitmap dimensions.
213 
214         @param rRectSrc
215         Source rectangle in pBmpSrc. This is clipped to the source
216         bitmap dimensions. Note further that no scaling takes place
217         during this copy operation, i.e. only the minimum of source
218         and destination rectangle's width and height are used.
219 
220         @param pBmpSrc
221         The source bitmap to copy from. If this argument is NULL, or
222         equal to the object this method is called on, copying takes
223         place within the same bitmap.
224 
225         @return true, if the operation completed successfully. false
226         is not only returned when the operation failed, but also if
227         nothing had to be done, e.g. because one of the rectangles are
228         empty.
229      */
230     bool                    CopyPixel(
231                                 const tools::Rectangle& rRectDst,
232                                 const tools::Rectangle& rRectSrc,
233                                 const Bitmap* pBmpSrc = nullptr );
234 
235     bool                    CopyPixel_AlphaOptimized(
236                                 const tools::Rectangle& rRectDst,
237                                 const tools::Rectangle& rRectSrc,
238                                 const Bitmap* pBmpSrc );
239 
240     /** Perform boolean operations with another bitmap
241 
242         @param rMask
243         The mask bitmap in the selected combine operation
244 
245         @param eCombine
246         The combine operation to perform on the bitmap
247 
248         @return true, if the operation was completed successfully.
249      */
250     bool                    CombineSimple(
251                                 const Bitmap& rMask,
252                                 BmpCombine eCombine );
253 
254     /** Alpha-blend the given bitmap against a specified uniform
255           background color.
256 
257         @attention This method might convert paletted bitmaps to
258         truecolor, to be able to represent every necessary color. Note
259         that during alpha blending, lots of colors not originally
260         included in the bitmap can be generated.
261 
262         @param rAlpha
263         Alpha mask to blend with
264 
265         @param rBackgroundColor
266         Background color to use for every pixel during alpha blending
267 
268         @return true, if blending was successful, false otherwise
269      */
270     bool                    Blend(
271                                 const AlphaMask& rAlpha,
272                                 const Color& rBackgroundColor );
273 
274     /** Fill the entire bitmap with the given color
275 
276         @param rFillColor
277         Color value to use for filling
278 
279         @return true, if the operation was completed successfully.
280      */
281     bool                    Erase( const Color& rFillColor );
282 
283     /** Perform the Invert operation on every pixel
284 
285         @return true, if the operation was completed successfully.
286      */
287     bool                    Invert();
288 
289     /** Mirror the bitmap
290 
291         @param nMirrorFlags
292         About which axis (horizontal, vertical, or both) to mirror
293 
294         @return true, if the operation was completed successfully.
295      */
296     bool                    Mirror( BmpMirrorFlags nMirrorFlags );
297 
298     /** Scale the bitmap
299 
300         @param rNewSize
301         The resulting size of the scaled bitmap
302 
303         @param nScaleFlag
304         The algorithm to be used for scaling
305 
306         @return true, if the operation was completed successfully.
307      */
308     bool                    Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
309 
310     /** Scale the bitmap
311 
312         @param rScaleX
313         The scale factor in x direction.
314 
315         @param rScaleY
316         The scale factor in y direction.
317 
318         @param nScaleFlag
319         Method of scaling - it is recommended that either BmpScaleFlag::Default or BmpScaleFlag::BestQuality be used.
320 
321         @return true, if the operation was completed successfully.
322      */
323     bool                    Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
324 
325     /**
326       Returns true if bitmap scaling is considered to be fast.
327 
328       Currently this returns true if OpenGL is used for scaling, otherwise false (CPU scaling is slower).
329 
330       @since 4.5
331     */
332     static bool HasFastScale();
333 
334     // Adapt the BitCount of rNew to BitCount of total, including grey or color palette
335     // Can be used to create alpha/mask bitmaps after their processing in 24bit
336     void AdaptBitCount(Bitmap& rNew) const;
337 
338     /** Rotate bitmap by the specified angle
339 
340         @param nAngle10
341         The rotation angle in tenth of a degree. The bitmap is always rotated around its center.
342 
343         @param rFillColor
344         The color to use for filling blank areas. During rotation, the
345         bitmap is enlarged such that the whole rotation result fits
346         in. The empty spaces around that rotated original bitmap are
347         then filled with this color.
348 
349         @return true, if the operation was completed successfully.
350      */
351     bool                    Rotate( long nAngle10, const Color& rFillColor );
352 
353     /** Create on-off mask from bitmap
354 
355         This method creates a bitmask from the bitmap, where every
356         pixel that equals rTransColor is set transparent, the rest
357         opaque.
358 
359         @param rTransColor
360         Color value where the bitmask should be transparent
361 
362         @param nTol
363         Tolerance value. Specifies the maximal difference between
364         rTransColor and the individual pixel values, such that the
365         corresponding pixel is still regarded as transparent.
366 
367         @return the resulting bitmask.
368      */
369     Bitmap                  CreateMask( const Color& rTransColor, sal_uInt8 nTol = 0 ) const;
370 
371     /** Create region of similar colors in a given rectangle
372 
373         @param rColor
374         All pixel which have this color are included in the calculated region
375 
376         @param rRect
377         The rectangle within which matching pixel are looked for. This
378         rectangle is always clipped to the bitmap dimensions.
379 
380         @return the generated region.
381      */
382     vcl::Region                  CreateRegion( const Color& rColor, const tools::Rectangle& rRect ) const;
383 
384     /** Replace all pixel where the given mask is on with the specified color
385 
386         @param rMask
387         Mask specifying which pixel should be replaced
388 
389         @param rReplaceColor
390         Color to be placed in all changed pixel
391 
392         @return true, if the operation was completed successfully.
393      */
394     bool                    Replace( const Bitmap& rMask, const Color& rReplaceColor );
395 
396     /** Merge bitmap with given background color according to specified alpha mask
397 
398         @param rAlpha
399         Alpha mask specifying the amount of background color to merge in
400 
401         @param rMergeColor
402         Background color to be used for merging
403 
404         @return true, if the operation was completed successfully.
405      */
406     bool                    Replace( const AlphaMask& rAlpha, const Color& rMergeColor );
407 
408     /** Replace all pixel having the search color with the specified color
409 
410         @param rSearchColor
411         Color specifying which pixel should be replaced
412 
413         @param rReplaceColor
414         Color to be placed in all changed pixel
415 
416         @param nTol
417         Tolerance value. Specifies the maximal difference between
418         rSearchColor and the individual pixel values, such that the
419         corresponding pixel is still regarded a match.
420 
421         @return true, if the operation was completed successfully.
422      */
423     bool                    Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTol = 0 );
424 
425     /** Replace all pixel having one the search colors with the corresponding replace color
426 
427         @param pSearchColors
428         Array of colors specifying which pixel should be replaced
429 
430         @param rReplaceColors
431         Array of colors to be placed in all changed pixel
432 
433         @param nColorCount
434         Size of the aforementioned color arrays
435 
436         @param pTols
437         Tolerance value. Specifies the maximal difference between
438         pSearchColor colors and the individual pixel values, such that
439         the corresponding pixel is still regarded a match.
440 
441         @return true, if the operation was completed successfully.
442      */
443     bool                    Replace(
444                                 const Color* pSearchColors,
445                                 const Color* rReplaceColors,
446                                 sal_uLong nColorCount,
447                                 sal_uInt8 const * pTols );
448 
449     /** Convert the bitmap to a meta file
450 
451         This works by putting continuous areas of the same color into
452         polygons painted in this color, by tracing the area's bounding
453         line.
454 
455         @param rMtf
456         The resulting meta file
457 
458         @param cReduce
459         If non-null, minimal size of bound rects for individual polygons. Smaller ones are ignored.
460 
461         @param pProgress
462         A callback for showing the progress of the vectorization
463      */
464     void                    Vectorize(
465                                 GDIMetaFile& rMtf,
466                                 sal_uInt8 cReduce,
467                                 const Link<long,void>* pProgress );
468 
469     /** Change various global color characteristics
470 
471         @param nLuminancePercent
472         Percent of luminance change, valid range [-100,100]. Values outside this range are clipped to the valid range.
473 
474         @param nContrastPercent
475         Percent of contrast change, valid range [-100,100]. Values outside this range are clipped to the valid range.
476 
477         @param nChannelRPercent
478         Percent of red channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
479 
480         @param nChannelGPercent
481         Percent of green channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
482 
483         @param nChannelBPercent
484         Percent of blue channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
485 
486         @param fGamma
487         Exponent of the gamma function applied to the bitmap. The
488         value 1.0 results in no change, the valid range is
489         (0.0,10.0]. Values outside this range are regarded as 1.0.
490 
491         @param bInvert
492         If true, invert the channel values with the logical 'not' operator
493 
494         @param msoBrightness
495         Use the same formula for brightness as used by MSOffice.
496 
497         @return true, if the operation was completed successfully.
498      */
499     bool                    Adjust(
500                                 short nLuminancePercent,
501                                 short nContrastPercent = 0,
502                                 short nChannelRPercent = 0,
503                                 short nChannelGPercent = 0,
504                                 short nChannelBPercent = 0,
505                                 double fGamma = 1.0,
506                                 bool bInvert = false,
507                                 bool msoBrightness = false );
508 
509 public:
510     /** ReassignWithSize and recalculate bitmap.
511 
512       ReassignWithSizes the bitmap, and recalculates the bitmap size based on the new bitmap.
513 
514       @param rBitmap Bitmap to reassign and use for size calculation
515      */
516     SAL_DLLPRIVATE void     ReassignWithSize(const Bitmap& rBitmap);
517 
518     SAL_DLLPRIVATE void     ImplMakeUnique();
519     const std::shared_ptr<SalBitmap>& ImplGetSalBitmap() const { return mxSalBmp; }
520     SAL_DLLPRIVATE void     ImplSetSalBitmap( const std::shared_ptr<SalBitmap>& xImpBmp );
521 
522     SAL_DLLPRIVATE bool     ImplMakeGreyscales( sal_uInt16 nGreyscales );
523 
524 public:
525 
526     BitmapInfoAccess*       AcquireInfoAccess();
527     BitmapReadAccess*       AcquireReadAccess();
528     BitmapWriteAccess*      AcquireWriteAccess();
529     static void             ReleaseAccess( BitmapInfoAccess* pAccess );
530 
531     typedef vcl::ScopedBitmapAccess<BitmapReadAccess, Bitmap, &Bitmap::AcquireReadAccess> ScopedReadAccess;
532     typedef vcl::ScopedBitmapAccess<BitmapInfoAccess, Bitmap, &Bitmap::AcquireInfoAccess> ScopedInfoAccess;
533 
534 private:
535     SAL_DLLPRIVATE bool ImplConvertUp(sal_uInt16 nBitCount, Color const* pExtColor = nullptr);
536     SAL_DLLPRIVATE bool ImplConvertDown(sal_uInt16 nBitCount, Color const* pExtColor = nullptr);
537 
538 private:
539     std::shared_ptr<SalBitmap> mxSalBmp;
540     MapMode maPrefMapMode;
541     Size maPrefSize;
542 
543 };
544 
545 inline bool Bitmap::operator!() const
546 {
547     return( mxSalBmp == nullptr );
548 }
549 
550 inline bool Bitmap::IsEmpty() const
551 {
552     return( mxSalBmp == nullptr );
553 }
554 
555 inline const MapMode& Bitmap::GetPrefMapMode() const
556 {
557     return maPrefMapMode;
558 }
559 
560 inline void Bitmap::SetPrefMapMode( const MapMode& rMapMode )
561 {
562     maPrefMapMode = rMapMode;
563 }
564 
565 inline const Size& Bitmap::GetPrefSize() const
566 {
567     return maPrefSize;
568 }
569 
570 inline void Bitmap::SetPrefSize( const Size& rSize )
571 {
572     maPrefSize = rSize;
573 }
574 
575 inline sal_Int64 Bitmap::GetColorCount() const
576 {
577     return sal_Int64(1) << sal_Int64(GetBitCount());
578 }
579 
580 inline sal_uLong Bitmap::GetSizeBytes() const
581 {
582     const Size aSizePix( GetSizePixel() );
583     return( ( static_cast<sal_uLong>(aSizePix.Width()) * aSizePix.Height() * GetBitCount() ) >> 3 );
584 }
585 
586 #endif // INCLUDED_VCL_BITMAP_HXX
587 
588 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
589