Line data Source code
1 : /*
2 : * Copyright 2015 Google Inc.
3 : *
4 : * Use of this source code is governed by a BSD-style license that can be
5 : * found in the LICENSE file.
6 : */
7 :
8 : #ifndef SkPixmap_DEFINED
9 : #define SkPixmap_DEFINED
10 :
11 : #include "SkColor.h"
12 : #include "SkFilterQuality.h"
13 : #include "SkImageInfo.h"
14 :
15 : class SkColorTable;
16 : class SkData;
17 : struct SkMask;
18 :
19 : /**
20 : * Pairs SkImageInfo with actual pixels and rowbytes. This class does not try to manage the
21 : * lifetime of the pixel memory (nor the colortable if provided).
22 : */
23 5109 : class SK_API SkPixmap {
24 : public:
25 2283 : SkPixmap()
26 2283 : : fPixels(NULL), fCTable(NULL), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))
27 2283 : {}
28 :
29 243 : SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes,
30 : SkColorTable* ctable = NULL)
31 243 : : fPixels(addr), fCTable(ctable), fRowBytes(rowBytes), fInfo(info)
32 : {
33 243 : if (kIndex_8_SkColorType == info.colorType()) {
34 0 : SkASSERT(ctable);
35 : } else {
36 243 : SkASSERT(NULL == ctable);
37 : }
38 243 : }
39 :
40 : void reset();
41 : void reset(const SkImageInfo& info, const void* addr, size_t rowBytes,
42 : SkColorTable* ctable = NULL);
43 : void reset(const SkImageInfo& info) {
44 : this->reset(info, NULL, 0, NULL);
45 : }
46 :
47 : // overrides the colorspace in the SkImageInfo of the pixmap
48 : void setColorSpace(sk_sp<SkColorSpace>);
49 :
50 : /**
51 : * If supported, set this pixmap to point to the pixels in the specified mask and return true.
52 : * On failure, return false and set this pixmap to empty.
53 : */
54 : bool SK_WARN_UNUSED_RESULT reset(const SkMask&);
55 :
56 : /**
57 : * Computes the intersection of area and this pixmap. If that intersection is non-empty,
58 : * set subset to that intersection and return true.
59 : *
60 : * On failure, return false and ignore the subset parameter.
61 : */
62 : bool SK_WARN_UNUSED_RESULT extractSubset(SkPixmap* subset, const SkIRect& area) const;
63 :
64 2894 : const SkImageInfo& info() const { return fInfo; }
65 3339 : size_t rowBytes() const { return fRowBytes; }
66 4692 : const void* addr() const { return fPixels; }
67 334 : SkColorTable* ctable() const { return fCTable; }
68 :
69 25036 : int width() const { return fInfo.width(); }
70 21346 : int height() const { return fInfo.height(); }
71 3940 : SkColorType colorType() const { return fInfo.colorType(); }
72 259 : SkAlphaType alphaType() const { return fInfo.alphaType(); }
73 501 : SkColorSpace* colorSpace() const { return fInfo.colorSpace(); }
74 341 : bool isOpaque() const { return fInfo.isOpaque(); }
75 :
76 25 : SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); }
77 :
78 : /**
79 : * Return the rowbytes expressed as a number of pixels (like width and height).
80 : */
81 0 : int rowBytesAsPixels() const { return int(fRowBytes >> this->shiftPerPixel()); }
82 :
83 : /**
84 : * Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel
85 : * colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType.
86 : */
87 46 : int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
88 :
89 0 : uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); }
90 : uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); }
91 0 : size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
92 :
93 : /**
94 : * This will brute-force return true if all of the pixels in the pixmap
95 : * are opaque. If there are no pixels, or encounters an error, returns false.
96 : */
97 : bool computeIsOpaque() const;
98 :
99 : /**
100 : * Converts the pixel at the specified coordinate to an unpremultiplied
101 : * SkColor. Note: this ignores any SkColorSpace information, and may return
102 : * lower precision data than is actually in the pixel. Alpha only
103 : * colortypes (e.g. kAlpha_8_SkColorType) return black with the appropriate
104 : * alpha set. The value is undefined for kUnknown_SkColorType or if x or y
105 : * are out of bounds, or if the pixtap does not have any pixels.
106 : */
107 : SkColor getColor(int x, int y) const;
108 :
109 90 : const void* addr(int x, int y) const {
110 90 : return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);
111 : }
112 62 : const uint8_t* addr8() const {
113 62 : SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType()));
114 62 : return reinterpret_cast<const uint8_t*>(fPixels);
115 : }
116 0 : const uint16_t* addr16() const {
117 0 : SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType()));
118 0 : return reinterpret_cast<const uint16_t*>(fPixels);
119 : }
120 21508 : const uint32_t* addr32() const {
121 21508 : SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType()));
122 21508 : return reinterpret_cast<const uint32_t*>(fPixels);
123 : }
124 0 : const uint64_t* addr64() const {
125 0 : SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType()));
126 0 : return reinterpret_cast<const uint64_t*>(fPixels);
127 : }
128 : const uint16_t* addrF16() const {
129 : SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType()));
130 : SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());
131 : return reinterpret_cast<const uint16_t*>(fPixels);
132 : }
133 :
134 : // Offset by the specified x,y coordinates
135 :
136 62 : const uint8_t* addr8(int x, int y) const {
137 62 : SkASSERT((unsigned)x < (unsigned)fInfo.width());
138 62 : SkASSERT((unsigned)y < (unsigned)fInfo.height());
139 62 : return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0));
140 : }
141 0 : const uint16_t* addr16(int x, int y) const {
142 0 : SkASSERT((unsigned)x < (unsigned)fInfo.width());
143 0 : SkASSERT((unsigned)y < (unsigned)fInfo.height());
144 0 : return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1));
145 : }
146 21508 : const uint32_t* addr32(int x, int y) const {
147 21508 : SkASSERT((unsigned)x < (unsigned)fInfo.width());
148 21508 : SkASSERT((unsigned)y < (unsigned)fInfo.height());
149 21508 : return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2));
150 : }
151 0 : const uint64_t* addr64(int x, int y) const {
152 0 : SkASSERT((unsigned)x < (unsigned)fInfo.width());
153 0 : SkASSERT((unsigned)y < (unsigned)fInfo.height());
154 0 : return (const uint64_t*)((const char*)this->addr64() + y * fRowBytes + (x << 3));
155 : }
156 : const uint16_t* addrF16(int x, int y) const {
157 : SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());
158 : return reinterpret_cast<const uint16_t*>(this->addr64(x, y));
159 : }
160 :
161 : // Writable versions
162 :
163 35 : void* writable_addr() const { return const_cast<void*>(fPixels); }
164 73 : void* writable_addr(int x, int y) const {
165 73 : return const_cast<void*>(this->addr(x, y));
166 : }
167 58 : uint8_t* writable_addr8(int x, int y) const {
168 58 : return const_cast<uint8_t*>(this->addr8(x, y));
169 : }
170 0 : uint16_t* writable_addr16(int x, int y) const {
171 0 : return const_cast<uint16_t*>(this->addr16(x, y));
172 : }
173 6748 : uint32_t* writable_addr32(int x, int y) const {
174 6748 : return const_cast<uint32_t*>(this->addr32(x, y));
175 : }
176 0 : uint64_t* writable_addr64(int x, int y) const {
177 0 : return const_cast<uint64_t*>(this->addr64(x, y));
178 : }
179 : uint16_t* writable_addrF16(int x, int y) const {
180 : return reinterpret_cast<uint16_t*>(writable_addr64(x, y));
181 : }
182 :
183 : // copy methods
184 :
185 : bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
186 : int srcX, int srcY) const;
187 0 : bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {
188 0 : return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);
189 : }
190 : bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {
191 : return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
192 : }
193 0 : bool readPixels(const SkPixmap& dst) const {
194 0 : return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
195 : }
196 :
197 : /**
198 : * Copy the pixels from this pixmap into the dst pixmap, converting as needed into dst's
199 : * colortype/alphatype. If the conversion cannot be performed, false is returned.
200 : *
201 : * If dst's dimensions differ from the src dimension, the image will be scaled, applying the
202 : * specified filter-quality.
203 : */
204 : bool scalePixels(const SkPixmap& dst, SkFilterQuality) const;
205 :
206 : /**
207 : * Returns true if pixels were written to (e.g. if colorType is kUnknown_SkColorType, this
208 : * will return false). If subset does not intersect the bounds of this pixmap, returns false.
209 : */
210 : bool erase(SkColor, const SkIRect& subset) const;
211 :
212 0 : bool erase(SkColor color) const { return this->erase(color, this->bounds()); }
213 : bool erase(const SkColor4f&, const SkIRect* subset = nullptr) const;
214 :
215 : private:
216 : const void* fPixels;
217 : SkColorTable* fCTable;
218 : size_t fRowBytes;
219 : SkImageInfo fInfo;
220 : };
221 :
222 : /////////////////////////////////////////////////////////////////////////////////////////////
223 :
224 : /////////////////////////////////////////////////////////////////////////////////////////////
225 :
226 : class SK_API SkAutoPixmapUnlock : ::SkNoncopyable {
227 : public:
228 152 : SkAutoPixmapUnlock() : fUnlockProc(NULL), fIsLocked(false) {}
229 : SkAutoPixmapUnlock(const SkPixmap& pm, void (*unlock)(void*), void* ctx)
230 : : fUnlockProc(unlock), fUnlockContext(ctx), fPixmap(pm), fIsLocked(true)
231 : {}
232 152 : ~SkAutoPixmapUnlock() { this->unlock(); }
233 :
234 : /**
235 : * Return the currently locked pixmap. Undefined if it has been unlocked.
236 : */
237 152 : const SkPixmap& pixmap() const {
238 152 : SkASSERT(this->isLocked());
239 152 : return fPixmap;
240 : }
241 :
242 152 : bool isLocked() const { return fIsLocked; }
243 :
244 : /**
245 : * Unlocks the pixmap. Can safely be called more than once as it will only call the underlying
246 : * unlock-proc once.
247 : */
248 304 : void unlock() {
249 304 : if (fUnlockProc) {
250 0 : SkASSERT(fIsLocked);
251 0 : fUnlockProc(fUnlockContext);
252 0 : fUnlockProc = NULL;
253 0 : fIsLocked = false;
254 : }
255 304 : }
256 :
257 : /**
258 : * If there is a currently locked pixmap, unlock it, then copy the specified pixmap
259 : * and (optional) unlock proc/context.
260 : */
261 : void reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx);
262 :
263 : private:
264 : void (*fUnlockProc)(void*);
265 : void* fUnlockContext;
266 : SkPixmap fPixmap;
267 : bool fIsLocked;
268 :
269 : friend class SkBitmap;
270 : };
271 :
272 : #endif
|