blob: cea50b8886b4b8acad1e5b4f72e6f6b2b3533f61 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
8#ifndef SkBitmap_DEFINED
9#define SkBitmap_DEFINED
10
reed@android.com8a1c16f2008-12-17 15:59:43 +000011#include "SkColor.h"
reed@google.com3443fd82013-11-13 19:09:13 +000012#include "SkImageInfo.h"
reed92fc2ae2015-05-22 08:06:21 -070013#include "SkPixmap.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014#include "SkPoint.h"
15#include "SkRefCnt.h"
16
commit-bot@chromium.orgdac52252014-02-17 21:21:46 +000017struct SkMask;
reed@android.com8a1c16f2008-12-17 15:59:43 +000018struct SkIRect;
reed@google.comfb2d3c62012-03-15 21:18:11 +000019struct SkRect;
reed@android.com8a1c16f2008-12-17 15:59:43 +000020class SkPaint;
21class SkPixelRef;
robertphillips@google.com76f9e932013-01-15 20:17:47 +000022class SkString;
reedc7ec7c92016-07-25 08:29:10 -070023
reed@android.com8a1c16f2008-12-17 15:59:43 +000024/** \class SkBitmap
25
26 The SkBitmap class specifies a raster bitmap. A bitmap has an integer width
reedddd014e2014-06-05 08:51:20 -070027 and height, and a format (colortype), and a pointer to the actual pixels.
tomhudson@google.com4b33d282011-04-27 15:39:30 +000028 Bitmaps can be drawn into a SkCanvas, but they are also used to specify the
29 target of a SkCanvas' drawing operations.
30 A const SkBitmap exposes getAddr(), which lets a caller write its pixels;
31 the constness is considered to apply to the bitmap's configuration, not
32 its contents.
Mike Kleinafe7a5f2017-03-01 11:16:17 -050033
34 SkBitmap is not thread safe. Each thread must use its own (shallow) copy.
reed@android.com8a1c16f2008-12-17 15:59:43 +000035*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000036class SK_API SkBitmap {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037public:
commit-bot@chromium.orgeddb02c2013-11-25 15:44:37 +000038 class SK_API Allocator;
reed@android.com8a1c16f2008-12-17 15:59:43 +000039
reed@google.com5dd510f2012-05-16 13:04:22 +000040 /**
41 * Default construct creates a bitmap with zero width and height, and no pixels.
reedddd014e2014-06-05 08:51:20 -070042 * Its colortype is set to kUnknown_SkColorType.
reed@google.com5dd510f2012-05-16 13:04:22 +000043 */
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 SkBitmap();
reed@google.com5dd510f2012-05-16 13:04:22 +000045
46 /**
47 * Copy the settings from the src into this bitmap. If the src has pixels
48 * allocated, they will be shared, not copied, so that the two bitmaps will
Brian Osman29e6f312017-06-20 09:45:16 -040049 * reference the same memory for the pixels.
reed@google.com5dd510f2012-05-16 13:04:22 +000050 */
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 SkBitmap(const SkBitmap& src);
reed@google.com5dd510f2012-05-16 13:04:22 +000052
halcanary023bda02015-12-14 10:19:17 -080053 /**
54 * Copy the settings from the src into this bitmap. If the src has pixels
55 * allocated, ownership of the pixels will be taken.
56 */
57 SkBitmap(SkBitmap&& src);
58
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 ~SkBitmap();
60
halcanary023bda02015-12-14 10:19:17 -080061 /** Copies the src bitmap into this bitmap. Ownership of the src
62 bitmap's pixels is shared with the src bitmap.
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 */
64 SkBitmap& operator=(const SkBitmap& src);
halcanary023bda02015-12-14 10:19:17 -080065
66 /** Copies the src bitmap into this bitmap. Takes ownership of the src
67 bitmap's pixels.
68 */
69 SkBitmap& operator=(SkBitmap&& src);
70
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 /** Swap the fields of the two bitmaps. This routine is guaranteed to never fail or throw.
72 */
73 // This method is not exported to java.
74 void swap(SkBitmap& other);
weita@google.comf9ab99a2009-05-03 18:23:30 +000075
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +000076 ///////////////////////////////////////////////////////////////////////////
77
78 const SkImageInfo& info() const { return fInfo; }
79
reede5ea5002014-09-03 11:54:58 -070080 int width() const { return fInfo.width(); }
81 int height() const { return fInfo.height(); }
82 SkColorType colorType() const { return fInfo.colorType(); }
83 SkAlphaType alphaType() const { return fInfo.alphaType(); }
brianosmanb109b8c2016-06-16 13:03:24 -070084 SkColorSpace* colorSpace() const { return fInfo.colorSpace(); }
Robert Phillips70b49fd2017-01-13 11:21:36 -050085 sk_sp<SkColorSpace> refColorSpace() const { return fInfo.refColorSpace(); }
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +000086
reedddd014e2014-06-05 08:51:20 -070087 /**
88 * Return the number of bytes per pixel based on the colortype. If the colortype is
89 * kUnknown_SkColorType, then 0 is returned.
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +000090 */
91 int bytesPerPixel() const { return fInfo.bytesPerPixel(); }
92
reedddd014e2014-06-05 08:51:20 -070093 /**
94 * Return the rowbytes expressed as a number of pixels (like width and height).
95 * If the colortype is kUnknown_SkColorType, then 0 is returned.
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +000096 */
97 int rowBytesAsPixels() const {
98 return fRowBytes >> this->shiftPerPixel();
99 }
100
reedddd014e2014-06-05 08:51:20 -0700101 /**
102 * Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel
103 * colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType.
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000104 */
reed8c3fd4f2016-04-15 06:59:38 -0700105 int shiftPerPixel() const { return this->fInfo.shiftPerPixel(); }
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000106
107 ///////////////////////////////////////////////////////////////////////////
108
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 /** Return true iff the bitmap has empty dimensions.
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000110 * Hey! Before you use this, see if you really want to know drawsNothing() instead.
111 */
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000112 bool empty() const { return fInfo.isEmpty(); }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000113
djsollen@google.comc84b8332012-07-27 13:41:44 +0000114 /** Return true iff the bitmap has no pixelref. Note: this can return true even if the
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000115 * dimensions of the bitmap are > 0 (see empty()).
116 * Hey! Before you use this, see if you really want to know drawsNothing() instead.
117 */
Hal Canary1b3387b2016-12-12 13:48:12 -0500118 bool isNull() const { return nullptr == fPixelRef; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000120 /** Return true iff drawing this bitmap has no effect.
121 */
Mike Reed0401c0d2017-07-02 15:46:49 -0400122 bool drawsNothing() const {
Mike Reed58050132017-07-12 22:10:29 -0400123 return this->empty() || this->isNull();
Mike Reed0401c0d2017-07-02 15:46:49 -0400124 }
commit-bot@chromium.org50b393a2014-02-10 18:29:10 +0000125
reed@google.com44699382013-10-31 17:28:30 +0000126 /** Return the number of bytes between subsequent rows of the bitmap. */
scroggo@google.com0ba4bf42013-02-25 16:02:36 +0000127 size_t rowBytes() const { return fRowBytes; }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000128
reed@google.com383a6972013-10-21 14:00:07 +0000129 /**
130 * Set the bitmap's alphaType, returning true on success. If false is
131 * returned, then the specified new alphaType is incompatible with the
reedddd014e2014-06-05 08:51:20 -0700132 * colortype, and the current alphaType is unchanged.
commit-bot@chromium.org0e8d0d62014-01-27 15:41:07 +0000133 *
134 * Note: this changes the alphatype for the underlying pixels, which means
135 * that all bitmaps that might be sharing (subsets of) the pixels will
reed@google.comc1587f92014-01-28 16:05:39 +0000136 * be affected.
reed@google.com383a6972013-10-21 14:00:07 +0000137 */
138 bool setAlphaType(SkAlphaType);
139
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 /** Return the address of the pixels for this SkBitmap.
141 */
142 void* getPixels() const { return fPixels; }
143
Mike Reede74dafc2017-09-29 13:41:58 -0400144 /**
145 * Returns the size (in bytes) of the bitmap's image buffer.
146 * If the calculation overflows, or if the height is 0, this returns 0.
147 */
148 size_t computeByteSize() const { return fInfo.computeByteSize(fRowBytes); }
149
Mike Reedcd284c52017-09-29 15:22:56 -0400150#ifdef SK_SUPPORT_LEGACY_SAFESIZE64
reede5ea5002014-09-03 11:54:58 -0700151 size_t getSize() const { return fInfo.height() * fRowBytes; }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000152
wjmaclean@chromium.org86bff1f2010-11-16 20:22:41 +0000153 /** Return the number of bytes from the pointer returned by getPixels()
154 to the end of the allocated space in the buffer. Required in
epoger@google.comd27fe342012-12-07 15:27:27 +0000155 cases where extractSubset has been called.
wjmaclean@chromium.org86bff1f2010-11-16 20:22:41 +0000156 */
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000157 size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
wjmaclean@chromium.org86bff1f2010-11-16 20:22:41 +0000158
reed@google.com57212f92013-12-30 14:40:38 +0000159 /**
160 * Return the full size of the bitmap, in bytes.
161 */
162 int64_t computeSize64() const {
reede5ea5002014-09-03 11:54:58 -0700163 return sk_64_mul(fInfo.height(), fRowBytes);
reed@google.com57212f92013-12-30 14:40:38 +0000164 }
165
166 /**
167 * Return the number of bytes from the pointer returned by getPixels()
168 * to the end of the allocated space in the buffer. This may be smaller
169 * than computeSize64() if there is any rowbytes padding beyond the width.
170 */
171 int64_t computeSafeSize64() const {
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000172 return fInfo.getSafeSize64(fRowBytes);
reed@google.com57212f92013-12-30 14:40:38 +0000173 }
Mike Reedcd284c52017-09-29 15:22:56 -0400174#endif
reed@google.com57212f92013-12-30 14:40:38 +0000175
junov@chromium.orgb0521292011-12-15 20:14:06 +0000176 /** Returns true if this bitmap is marked as immutable, meaning that the
177 contents of its pixels will not change for the lifetime of the bitmap.
178 */
179 bool isImmutable() const;
180
181 /** Marks this bitmap as immutable, meaning that the contents of its
182 pixels will not change for the lifetime of the bitmap and of the
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000183 underlying pixelref. This state can be set, but it cannot be
junov@chromium.orgb0521292011-12-15 20:14:06 +0000184 cleared once it is set. This state propagates to all other bitmaps
185 that share the same pixelref.
186 */
187 void setImmutable();
188
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 /** Returns true if the bitmap is opaque (has no translucent/transparent pixels).
190 */
reed@google.com383a6972013-10-21 14:00:07 +0000191 bool isOpaque() const {
192 return SkAlphaTypeIsOpaque(this->alphaType());
193 }
junov@google.com4ee7ae52011-06-30 17:30:49 +0000194
junov@google.com4ee7ae52011-06-30 17:30:49 +0000195 /** Returns true if the bitmap is volatile (i.e. should not be cached by devices.)
196 */
197 bool isVolatile() const;
198
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000199 /** Specify whether this bitmap is volatile. Bitmaps are not volatile by
junov@google.com4ee7ae52011-06-30 17:30:49 +0000200 default. Temporary bitmaps that are discarded after use should be
201 marked as volatile. This provides a hint to the device that the bitmap
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000202 should not be cached. Providing this hint when appropriate can
203 improve performance by avoiding unnecessary overhead and resource
junov@google.com4ee7ae52011-06-30 17:30:49 +0000204 consumption on the device.
205 */
206 void setIsVolatile(bool);
207
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 /** Reset the bitmap to its initial state (see default constructor). If we are a (shared)
209 owner of the pixels, that ownership is decremented.
210 */
211 void reset();
212
reed@google.com86b2e432012-03-15 21:17:03 +0000213 /**
reed@google.com2a7579d2012-11-07 18:30:18 +0000214 * This will brute-force return true if all of the pixels in the bitmap
215 * are opaque. If it fails to read the pixels, or encounters an error,
216 * it will return false.
217 *
218 * Since this can be an expensive operation, the bitmap stores a flag for
commit-bot@chromium.org21a0b102013-11-12 18:16:34 +0000219 * this (isOpaque). Only call this if you need to compute this value from
220 * "unknown" pixels.
reed@google.com2a7579d2012-11-07 18:30:18 +0000221 */
Hal Canary58a76942016-12-07 15:24:59 -0500222 static bool ComputeIsOpaque(const SkBitmap& bm) {
Mike Reed4edb5d22017-04-17 11:02:51 -0400223 SkPixmap pmap;
224 return bm.peekPixels(&pmap) && pmap.computeIsOpaque();
Hal Canary58a76942016-12-07 15:24:59 -0500225 }
reed@google.com2a7579d2012-11-07 18:30:18 +0000226
227 /**
reed@google.com86b2e432012-03-15 21:17:03 +0000228 * Return the bitmap's bounds [0, 0, width, height] as an SkRect
229 */
230 void getBounds(SkRect* bounds) const;
reed@google.com80e14592012-03-16 14:58:07 +0000231 void getBounds(SkIRect* bounds) const;
reed@google.com86b2e432012-03-15 21:17:03 +0000232
halcanaryf622a6c2014-10-24 12:54:53 -0700233 SkIRect bounds() const { return fInfo.bounds(); }
234 SkISize dimensions() const { return fInfo.dimensions(); }
reed85d91782015-09-10 14:33:38 -0700235 // Returns the bounds of this bitmap, offset by its pixelref origin.
236 SkIRect getSubset() const {
237 return SkIRect::MakeXYWH(fPixelRefOrigin.x(), fPixelRefOrigin.y(),
238 fInfo.width(), fInfo.height());
239 }
halcanaryf622a6c2014-10-24 12:54:53 -0700240
Cary Clarkd74d7752017-09-21 12:36:48 -0400241 bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0);
commit-bot@chromium.orga3264e52014-05-30 13:26:10 +0000242
Mike Reed6b3155c2017-04-03 14:41:44 -0400243 enum AllocFlags {
244 kZeroPixels_AllocFlag = 1 << 0,
245 };
Mike Reed086a4272017-07-18 10:53:11 -0400246
reed@google.com9230ea22013-12-09 22:01:03 +0000247 /**
reedbae704b2014-06-28 14:26:35 -0700248 * Allocate the bitmap's pixels to match the requested image info. If the Factory
Mike Reedb7648a22017-07-19 15:45:45 -0400249 * is non-null, call it to allcoate the pixelref.
Mike Reed6b3155c2017-04-03 14:41:44 -0400250 *
reed@google.com9ebcac52014-01-24 18:53:42 +0000251 * On failure, the bitmap will be set to empty and return false.
252 */
Mike Reed086a4272017-07-18 10:53:11 -0400253 bool SK_WARN_UNUSED_RESULT tryAllocPixelsFlags(const SkImageInfo& info, uint32_t flags);
254 void allocPixelsFlags(const SkImageInfo& info, uint32_t flags) {
Ben Wagner7ca9a742017-08-17 14:05:04 -0400255 SkASSERT_RELEASE(this->tryAllocPixelsFlags(info, flags));
reed84825042014-09-02 12:50:45 -0700256 }
skia.committer@gmail.comd2ac07b2014-01-25 07:01:49 +0000257
reed@google.com9ebcac52014-01-24 18:53:42 +0000258 /**
reedbae704b2014-06-28 14:26:35 -0700259 * Allocate the bitmap's pixels to match the requested image info and
260 * rowBytes. If the request cannot be met (e.g. the info is invalid or
261 * the requested rowBytes are not compatible with the info
262 * (e.g. rowBytes < info.minRowBytes() or rowBytes is not aligned with
263 * the pixel size specified by info.colorType()) then false is returned
264 * and the bitmap is set to empty.
265 */
reed84825042014-09-02 12:50:45 -0700266 bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info, size_t rowBytes);
reedbae704b2014-06-28 14:26:35 -0700267
reed68331cd2014-12-18 12:48:16 -0800268 void allocPixels(const SkImageInfo& info, size_t rowBytes) {
Ben Wagner7ca9a742017-08-17 14:05:04 -0400269 SkASSERT_RELEASE(this->tryAllocPixels(info, rowBytes));
reed84825042014-09-02 12:50:45 -0700270 }
271
272 bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info) {
273 return this->tryAllocPixels(info, info.minRowBytes());
274 }
275
reed68331cd2014-12-18 12:48:16 -0800276 void allocPixels(const SkImageInfo& info) {
277 this->allocPixels(info, info.minRowBytes());
reed@google.com9ebcac52014-01-24 18:53:42 +0000278 }
skia.committer@gmail.comd2ac07b2014-01-25 07:01:49 +0000279
reed84825042014-09-02 12:50:45 -0700280 bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false) {
reede5ea5002014-09-03 11:54:58 -0700281 SkImageInfo info = SkImageInfo::MakeN32(width, height,
282 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
reed84825042014-09-02 12:50:45 -0700283 return this->tryAllocPixels(info);
284 }
mtklein775b8192014-12-02 09:11:25 -0800285
reed68331cd2014-12-18 12:48:16 -0800286 void allocN32Pixels(int width, int height, bool isOpaque = false) {
reede5ea5002014-09-03 11:54:58 -0700287 SkImageInfo info = SkImageInfo::MakeN32(width, height,
288 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
reed68331cd2014-12-18 12:48:16 -0800289 this->allocPixels(info);
reed@google.comeb9a46c2014-01-25 16:46:20 +0000290 }
mtklein775b8192014-12-02 09:11:25 -0800291
reed@google.comeb9a46c2014-01-25 16:46:20 +0000292 /**
reed@google.com9ebcac52014-01-24 18:53:42 +0000293 * Install a pixelref that wraps the specified pixels and rowBytes, and
294 * optional ReleaseProc and context. When the pixels are no longer
commit-bot@chromium.org00f8d6c2014-05-29 15:57:20 +0000295 * referenced, if releaseProc is not null, it will be called with the
reed@google.com9ebcac52014-01-24 18:53:42 +0000296 * pixels and context as parameters.
297 * On failure, the bitmap will be set to empty and return false.
reeddb74f622015-05-30 13:41:15 -0700298 *
299 * If specified, the releaseProc will always be called, even on failure. It is also possible
300 * for success but the releaseProc is immediately called (e.g. valid Info but NULL pixels).
reed@google.com9ebcac52014-01-24 18:53:42 +0000301 */
Cary Clarkd74d7752017-09-21 12:36:48 -0400302 bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
commit-bot@chromium.org00f8d6c2014-05-29 15:57:20 +0000303 void (*releaseProc)(void* addr, void* context), void* context);
304
commit-bot@chromium.orgdac52252014-02-17 21:21:46 +0000305 /**
306 * Call installPixels with no ReleaseProc specified. This means that the
307 * caller must ensure that the specified pixels are valid for the lifetime
308 * of the created bitmap (and its pixelRef).
309 */
310 bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
Mike Reed086a4272017-07-18 10:53:11 -0400311 return this->installPixels(info, pixels, rowBytes, nullptr, nullptr);
commit-bot@chromium.orgdac52252014-02-17 21:21:46 +0000312 }
313
314 /**
Mike Reedb7648a22017-07-19 15:45:45 -0400315 * Call installPixels with no ReleaseProc specified. This means that the caller must ensure
316 * that the specified pixels are valid for the lifetime of the created bitmap
halcanarye36ec872015-12-09 11:36:59 -0800317 * (and its pixelRef).
318 */
Cary Clarkd74d7752017-09-21 12:36:48 -0400319 bool installPixels(const SkPixmap& pixmap);
halcanarye36ec872015-12-09 11:36:59 -0800320
321 /**
commit-bot@chromium.orgdac52252014-02-17 21:21:46 +0000322 * Calls installPixels() with the value in the SkMask. The caller must
323 * ensure that the specified mask pixels are valid for the lifetime
324 * of the created bitmap (and its pixelRef).
325 */
Cary Clarkd74d7752017-09-21 12:36:48 -0400326 bool installMaskPixels(const SkMask& mask);
skia.committer@gmail.comd2ac07b2014-01-25 07:01:49 +0000327
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328 /** Use this to assign a new pixel address for an existing bitmap. This
329 will automatically release any pixelref previously installed. Only call
330 this if you are handling ownership/lifetime of the pixel memory.
weita@google.comf9ab99a2009-05-03 18:23:30 +0000331
reed@android.com8a1c16f2008-12-17 15:59:43 +0000332 @param pixels Address for the pixels, managed by the caller.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000333 */
Cary Clarkd74d7752017-09-21 12:36:48 -0400334 void setPixels(void* pixels);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335
336 /** Use the standard HeapAllocator to create the pixelref that manages the
reedddd014e2014-06-05 08:51:20 -0700337 pixel memory. It will be sized based on the current ImageInfo.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 If this is called multiple times, a new pixelref object will be created
339 each time.
weita@google.comf9ab99a2009-05-03 18:23:30 +0000340
reed@android.com8a1c16f2008-12-17 15:59:43 +0000341 @return true if the allocation succeeds. If not the pixelref field of
342 the bitmap will be unchanged.
343 */
Mike Reed086a4272017-07-18 10:53:11 -0400344 bool SK_WARN_UNUSED_RESULT tryAllocPixels() {
345 return this->tryAllocPixels((Allocator*)nullptr);
reed84825042014-09-02 12:50:45 -0700346 }
347
Mike Reed086a4272017-07-18 10:53:11 -0400348 void allocPixels() {
349 this->allocPixels((Allocator*)nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350 }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000351
reed@android.com8a1c16f2008-12-17 15:59:43 +0000352 /** Use the specified Allocator to create the pixelref that manages the
reedddd014e2014-06-05 08:51:20 -0700353 pixel memory. It will be sized based on the current ImageInfo.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000354 If this is called multiple times, a new pixelref object will be created
355 each time.
weita@google.comf9ab99a2009-05-03 18:23:30 +0000356
reed@android.com8a1c16f2008-12-17 15:59:43 +0000357 @param allocator The Allocator to use to create a pixelref that can
reedddd014e2014-06-05 08:51:20 -0700358 manage the pixel memory for the current ImageInfo.
359 If allocator is NULL, the standard HeapAllocator will be used.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000360 @return true if the allocation succeeds. If not the pixelref field of
361 the bitmap will be unchanged.
362 */
Mike Reed086a4272017-07-18 10:53:11 -0400363 bool SK_WARN_UNUSED_RESULT tryAllocPixels(Allocator* allocator);
reed84825042014-09-02 12:50:45 -0700364
Mike Reed086a4272017-07-18 10:53:11 -0400365 void allocPixels(Allocator* allocator) {
Ben Wagner7ca9a742017-08-17 14:05:04 -0400366 SkASSERT_RELEASE(this->tryAllocPixels(allocator));
reed84825042014-09-02 12:50:45 -0700367 }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000368
reed@google.com672588b2014-01-08 15:42:01 +0000369 /**
370 * Return the current pixelref object or NULL if there is none. This does
371 * not affect the refcount of the pixelref.
372 */
Hal Canary1b3387b2016-12-12 13:48:12 -0500373 SkPixelRef* pixelRef() const { return fPixelRef.get(); }
reed@google.com672588b2014-01-08 15:42:01 +0000374
375 /**
376 * A bitmap can reference a subset of a pixelref's pixels. That means the
377 * bitmap's width/height can be <= the dimensions of the pixelref. The
378 * pixelref origin is the x,y location within the pixelref's pixels for
379 * the bitmap's top/left corner. To be valid the following must be true:
380 *
381 * origin_x + bitmap_width <= pixelref_width
382 * origin_y + bitmap_height <= pixelref_height
383 *
384 * pixelRefOrigin() returns this origin, or (0,0) if there is no pixelRef.
385 */
386 SkIPoint pixelRefOrigin() const { return fPixelRefOrigin; }
387
388 /**
Hal Canary1b3387b2016-12-12 13:48:12 -0500389 * Assign a pixelref and origin to the bitmap. (dx,dy) specify the offset
390 * within the pixelref's pixels for the top/left corner of the bitmap. For
391 * a bitmap that encompases the entire pixels of the pixelref, these will
392 * be (0,0).
393 */
Cary Clarkd74d7752017-09-21 12:36:48 -0400394 void setPixelRef(sk_sp<SkPixelRef> pixelRef, int dx, int dy);
Hal Canary1b3387b2016-12-12 13:48:12 -0500395
reed@android.com8a1c16f2008-12-17 15:59:43 +0000396 /** Call this to be sure that the bitmap is valid enough to be drawn (i.e.
Mike Reedb7648a22017-07-19 15:45:45 -0400397 it has non-null pixels).
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398 */
399 bool readyToDraw() const {
Ben Wagnera93a14a2017-08-28 10:34:05 -0400400 return this->getPixels() != nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401 }
402
reed@android.com8a1c16f2008-12-17 15:59:43 +0000403 /** Returns a non-zero, unique value corresponding to the pixels in our
djsollen@google.comc84b8332012-07-27 13:41:44 +0000404 pixelref. Each time the pixels are changed (and notifyPixelsChanged
405 is called), a different generation ID will be returned. Finally, if
scroggo58edea82014-06-05 07:49:04 -0700406 there is no pixelRef then zero is returned.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000407 */
408 uint32_t getGenerationID() const;
weita@google.comf9ab99a2009-05-03 18:23:30 +0000409
reed@android.com8a1c16f2008-12-17 15:59:43 +0000410 /** Call this if you have changed the contents of the pixels. This will in-
411 turn cause a different generation ID value to be returned from
412 getGenerationID().
413 */
414 void notifyPixelsChanged() const;
415
reed@google.com60d32352013-06-28 19:40:50 +0000416 /**
417 * Fill the entire bitmap with the specified color.
reedddd014e2014-06-05 08:51:20 -0700418 * If the bitmap's colortype does not support alpha (e.g. 565) then the alpha
419 * of the color is ignored (treated as opaque). If the colortype only supports
reed@google.com60d32352013-06-28 19:40:50 +0000420 * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
421 */
reed7aefe032015-06-08 10:22:22 -0700422 void eraseColor(SkColor c) const;
weita@google.comf9ab99a2009-05-03 18:23:30 +0000423
reed@google.com60d32352013-06-28 19:40:50 +0000424 /**
425 * Fill the entire bitmap with the specified color.
reedddd014e2014-06-05 08:51:20 -0700426 * If the bitmap's colortype does not support alpha (e.g. 565) then the alpha
427 * of the color is ignored (treated as opaque). If the colortype only supports
reed@google.com60d32352013-06-28 19:40:50 +0000428 * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
429 */
reed7aefe032015-06-08 10:22:22 -0700430 void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
431 this->eraseColor(SkColorSetARGB(a, r, g, b));
432 }
reed@google.com60d32352013-06-28 19:40:50 +0000433
reed@google.com44699382013-10-31 17:28:30 +0000434 SK_ATTR_DEPRECATED("use eraseARGB or eraseColor")
reed@google.com60d32352013-06-28 19:40:50 +0000435 void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const {
436 this->eraseARGB(0xFF, r, g, b);
437 }
438
439 /**
440 * Fill the specified area of this bitmap with the specified color.
reedddd014e2014-06-05 08:51:20 -0700441 * If the bitmap's colortype does not support alpha (e.g. 565) then the alpha
442 * of the color is ignored (treated as opaque). If the colortype only supports
reed@google.com60d32352013-06-28 19:40:50 +0000443 * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
444 */
reed7aefe032015-06-08 10:22:22 -0700445 void erase(SkColor c, const SkIRect& area) const;
446
447 // DEPRECATED
448 void eraseArea(const SkIRect& area, SkColor c) const {
449 this->erase(c, area);
450 }
reed@google.com60d32352013-06-28 19:40:50 +0000451
reed@google.com3b521d02011-04-29 11:53:41 +0000452 /**
Hal Canary94e1a2f2016-10-31 09:38:12 -0400453 * Converts the pixel at the specified coordinate to an unpremultiplied
454 * SkColor. Note: this ignores any SkColorSpace information, and may return
455 * lower precision data than is actually in the pixel. Alpha only
456 * colortypes (e.g. kAlpha_8_SkColorType) return black with the appropriate
457 * alpha set. The value is undefined for kUnknown_SkColorType or if x or y
Leon Scroggins III56269ef2017-05-09 09:18:03 -0400458 * are out of bounds, or if the bitmap does not have any pixels.
reed@google.com3b521d02011-04-29 11:53:41 +0000459 */
Hal Canary94e1a2f2016-10-31 09:38:12 -0400460 SkColor getColor(int x, int y) const {
461 SkPixmap pixmap;
462 SkAssertResult(this->peekPixels(&pixmap));
463 return pixmap.getColor(x, y);
464 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000465
reed@android.com8a1c16f2008-12-17 15:59:43 +0000466 /** Returns the address of the specified pixel. This performs a runtime
467 check to know the size of the pixels, and will return the same answer
468 as the corresponding size-specific method (e.g. getAddr16). Since the
469 check happens at runtime, it is much slower than using a size-specific
470 version. Unlike the size-specific methods, this routine also checks if
471 getPixels() returns null, and returns that. The size-specific routines
472 perform a debugging assert that getPixels() is not null, but they do
473 not do any runtime checks.
474 */
475 void* getAddr(int x, int y) const;
476
477 /** Returns the address of the pixel specified by x,y for 32bit pixels.
Leon Scroggins III56269ef2017-05-09 09:18:03 -0400478 * In debug build, this asserts that the pixels are allocated and that the
479 * colortype is 32-bit, however none of these checks are performed
reed@google.com3b521d02011-04-29 11:53:41 +0000480 * in the release build.
481 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000482 inline uint32_t* getAddr32(int x, int y) const;
reed@google.com3b521d02011-04-29 11:53:41 +0000483
reed@android.com8a1c16f2008-12-17 15:59:43 +0000484 /** Returns the address of the pixel specified by x,y for 16bit pixels.
Leon Scroggins III56269ef2017-05-09 09:18:03 -0400485 * In debug build, this asserts that the pixels are allocated
reedddd014e2014-06-05 08:51:20 -0700486 * and that the colortype is 16-bit, however none of these checks are performed
reed@google.com3b521d02011-04-29 11:53:41 +0000487 * in the release build.
488 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000489 inline uint16_t* getAddr16(int x, int y) const;
reed@google.com3b521d02011-04-29 11:53:41 +0000490
reed@android.com8a1c16f2008-12-17 15:59:43 +0000491 /** Returns the address of the pixel specified by x,y for 8bit pixels.
Leon Scroggins III56269ef2017-05-09 09:18:03 -0400492 * In debug build, this asserts that the pixels are allocated
reedddd014e2014-06-05 08:51:20 -0700493 * and that the colortype is 8-bit, however none of these checks are performed
reed@google.com3b521d02011-04-29 11:53:41 +0000494 * in the release build.
495 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000496 inline uint8_t* getAddr8(int x, int y) const;
reed@google.com3b521d02011-04-29 11:53:41 +0000497
epoger@google.com9ef2d832011-07-01 21:12:20 +0000498 /** Set dst to be a setset of this bitmap. If possible, it will share the
reedddd014e2014-06-05 08:51:20 -0700499 pixel memory, and just point into a subset of it. However, if the colortype
reed@android.com8a1c16f2008-12-17 15:59:43 +0000500 does not support this, a local copy will be made and associated with
501 the dst bitmap. If the subset rectangle, intersected with the bitmap's
reedddd014e2014-06-05 08:51:20 -0700502 dimensions is empty, or if there is an unsupported colortype, false will be
reed@android.com8a1c16f2008-12-17 15:59:43 +0000503 returned and dst will be untouched.
504 @param dst The bitmap that will be set to a subset of this bitmap
505 @param subset The rectangle of pixels in this bitmap that dst will
506 reference.
507 @return true if the subset copy was successfully made.
508 */
509 bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
510
commit-bot@chromium.org8a2ad3c2014-02-23 03:59:35 +0000511 /**
reedb184f7f2014-07-13 04:32:32 -0700512 * Copy the bitmap's pixels into the specified buffer (pixels + rowBytes),
513 * converting them into the requested format (SkImageInfo). The src pixels are read
514 * starting at the specified (srcX,srcY) offset, relative to the top-left corner.
515 *
516 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
517 *
518 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
519 *
520 * srcR is intersected with the bounds of the bitmap. If this intersection is not empty,
521 * then we have two sets of pixels (of equal size). Replace the dst pixels with the
522 * corresponding src pixels, performing any colortype/alphatype transformations needed
523 * (in the case where the src and dst have different colortypes or alphatypes).
524 *
525 * This call can fail, returning false, for several reasons:
526 * - If srcR does not intersect the bitmap bounds.
527 * - If the requested colortype/alphatype cannot be converted from the src's types.
528 * - If the src pixels are not available.
529 */
530 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
Matt Sarett3928ff82017-06-06 10:11:34 -0400531 int srcX, int srcY, SkTransferFunctionBehavior behavior) const;
532 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
533 int srcX, int srcY) const {
534 return this->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY,
535 SkTransferFunctionBehavior::kRespect);
536 }
Mike Reed68dd8d02017-01-04 16:34:31 -0500537 bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;
538 bool readPixels(const SkPixmap& dst) const {
539 return this->readPixels(dst, 0, 0);
540 }
541
542 /**
543 * Copy the src pixmap's pixels into this bitmap, offset by dstX, dstY.
544 *
545 * This is logically the same as creating a bitmap around src, and calling readPixels on it
546 * with this bitmap as the dst.
547 */
Matt Sarettd2adc662017-03-27 15:07:35 -0400548 bool writePixels(const SkPixmap& src, int dstX, int dstY) {
549 return this->writePixels(src, dstX, dstY, SkTransferFunctionBehavior::kRespect);
550 }
Mike Reed68dd8d02017-01-04 16:34:31 -0500551 bool writePixels(const SkPixmap& src) {
552 return this->writePixels(src, 0, 0);
553 }
Matt Sarett3928ff82017-06-06 10:11:34 -0400554 bool writePixels(const SkPixmap& src, int x, int y, SkTransferFunctionBehavior behavior);
reedb184f7f2014-07-13 04:32:32 -0700555
djsollen@google.com4bd2bdb2013-03-08 18:35:13 +0000556#ifdef SK_BUILD_FOR_ANDROID
557 bool hasHardwareMipMap() const {
558 return (fFlags & kHasHardwareMipMap_Flag) != 0;
559 }
560
561 void setHasHardwareMipMap(bool hasHardwareMipMap) {
562 if (hasHardwareMipMap) {
563 fFlags |= kHasHardwareMipMap_Flag;
564 } else {
565 fFlags &= ~kHasHardwareMipMap_Flag;
566 }
567 }
568#endif
569
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000570 bool extractAlpha(SkBitmap* dst) const {
Ben Wagnera93a14a2017-08-28 10:34:05 -0400571 return this->extractAlpha(dst, nullptr, nullptr, nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000572 }
573
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000574 bool extractAlpha(SkBitmap* dst, const SkPaint* paint,
djsollen@google.com57f49692011-02-23 20:46:31 +0000575 SkIPoint* offset) const {
Ben Wagnera93a14a2017-08-28 10:34:05 -0400576 return this->extractAlpha(dst, paint, nullptr, offset);
djsollen@google.com57f49692011-02-23 20:46:31 +0000577 }
578
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000579 /** Set dst to contain alpha layer of this bitmap. If destination bitmap
580 fails to be initialized, e.g. because allocator can't allocate pixels
581 for it, dst will not be modified and false will be returned.
582
583 @param dst The bitmap to be filled with alpha layer
584 @param paint The paint to draw with
585 @param allocator Allocator used to allocate the pixelref for the dst
586 bitmap. If this is null, the standard HeapAllocator
587 will be used.
588 @param offset If not null, it is set to top-left coordinate to position
589 the returned bitmap so that it visually lines up with the
590 original
591 */
592 bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000593 SkIPoint* offset) const;
weita@google.comf9ab99a2009-05-03 18:23:30 +0000594
reedcb674142015-06-05 06:58:22 -0700595 /**
Leon Scroggins III56269ef2017-05-09 09:18:03 -0400596 * If the pixels are available from this bitmap return true, and fill out the
597 * specified pixmap (if not null). If there are no pixels, return false and
reedcb674142015-06-05 06:58:22 -0700598 * ignore the pixmap parameter.
599 *
600 * Note: if this returns true, the results (in the pixmap) are only valid until the bitmap
Leon Scroggins III56269ef2017-05-09 09:18:03 -0400601 * is changed in any way, in which case the results are invalid.
reedcb674142015-06-05 06:58:22 -0700602 */
Cary Clarkd74d7752017-09-21 12:36:48 -0400603 bool peekPixels(SkPixmap* pixmap) const;
reedcb674142015-06-05 06:58:22 -0700604
reed@android.com8a1c16f2008-12-17 15:59:43 +0000605 SkDEBUGCODE(void validate() const;)
606
607 class Allocator : public SkRefCnt {
608 public:
609 /** Allocate the pixel memory for the bitmap, given its dimensions and
reedddd014e2014-06-05 08:51:20 -0700610 colortype. Return true on success, where success means either setPixels
Mike Reedb7648a22017-07-19 15:45:45 -0400611 or setPixelRef was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000612 */
Cary Clarkd74d7752017-09-21 12:36:48 -0400613 virtual bool allocPixelRef(SkBitmap* bitmap) = 0;
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +0000614 private:
615 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616 };
617
618 /** Subclass of Allocator that returns a pixelref that allocates its pixel
619 memory from the heap. This is the default Allocator invoked by
620 allocPixels().
621 */
622 class HeapAllocator : public Allocator {
623 public:
Cary Clarkd74d7752017-09-21 12:36:48 -0400624 bool allocPixelRef(SkBitmap* bitmap) override;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000625 };
626
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000627 SK_TO_STRING_NONVIRT()
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000628
reed@android.com8a1c16f2008-12-17 15:59:43 +0000629private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000630 enum Flags {
junov@chromium.orgb0521292011-12-15 20:14:06 +0000631 kImageIsVolatile_Flag = 0x02,
djsollen@google.com4bd2bdb2013-03-08 18:35:13 +0000632#ifdef SK_BUILD_FOR_ANDROID
633 /* A hint for the renderer responsible for drawing this bitmap
634 * indicating that it should attempt to use mipmaps when this bitmap
635 * is drawn scaled down.
636 */
637 kHasHardwareMipMap_Flag = 0x08,
638#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000639 };
640
Mike Reedb7120892017-04-14 17:16:36 -0400641 sk_sp<SkPixelRef> fPixelRef;
642 void* fPixels;
643 SkIPoint fPixelRefOrigin;
644 SkImageInfo fInfo;
645 uint32_t fRowBytes;
646 uint8_t fFlags;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000647
Mike Reedb7648a22017-07-19 15:45:45 -0400648 /* Unreference any pixelrefs
reed@android.com8a1c16f2008-12-17 15:59:43 +0000649 */
650 void freePixels();
Mike Reedb7120892017-04-14 17:16:36 -0400651 void updatePixelsFromRef();
skia.committer@gmail.com3c134a92014-05-24 03:05:26 +0000652
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000653 static void WriteRawPixels(SkWriteBuffer*, const SkBitmap&);
654 static bool ReadRawPixels(SkReadBuffer*, SkBitmap*);
weita@google.comf9ab99a2009-05-03 18:23:30 +0000655
brianosmanfad98562016-05-04 11:06:28 -0700656 friend class SkReadBuffer; // unflatten, rawpixels
657 friend class SkBinaryWriteBuffer; // rawpixels
reed@android.com8a1c16f2008-12-17 15:59:43 +0000658};
659
reed@android.com8a1c16f2008-12-17 15:59:43 +0000660///////////////////////////////////////////////////////////////////////////////
661
662inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
663 SkASSERT(fPixels);
reed@google.com69e64632014-03-14 20:48:05 +0000664 SkASSERT(4 == this->bytesPerPixel());
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000665 SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000666 return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
667}
668
669inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
670 SkASSERT(fPixels);
reed@google.com69e64632014-03-14 20:48:05 +0000671 SkASSERT(2 == this->bytesPerPixel());
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000672 SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000673 return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
674}
675
676inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
677 SkASSERT(fPixels);
reed@google.com69e64632014-03-14 20:48:05 +0000678 SkASSERT(1 == this->bytesPerPixel());
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000679 SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000680 return (uint8_t*)fPixels + y * fRowBytes + x;
681}
682
reed@android.com8a1c16f2008-12-17 15:59:43 +0000683#endif