• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 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 SkImage_DEFINED
9 #define SkImage_DEFINED
10 
11 #include "include/core/SkAlphaType.h"
12 #include "include/core/SkImageInfo.h"
13 #include "include/core/SkRect.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkSize.h"
16 #include "include/private/base/SkAPI.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <memory>
21 #include <optional>
22 
23 class GrDirectContext;
24 class GrRecordingContext;
25 class SkBitmap;
26 class SkColorSpace;
27 class SkData;
28 class SkImage;
29 class SkImageFilter;
30 class SkImageGenerator;
31 class SkMatrix;
32 class SkMipmap;
33 class SkPaint;
34 class SkPicture;
35 class SkPixmap;
36 class SkShader;
37 class SkSurfaceProps;
38 enum SkColorType : int;
39 enum class SkTextureCompressionType;
40 enum class SkTileMode;
41 
42 struct SkIPoint;
43 struct SkSamplingOptions;
44 
45 namespace skgpu::graphite { class Recorder; }
46 
47 namespace SkImages {
48 
49 /** Caller data passed to RasterReleaseProc; may be nullptr. */
50 using ReleaseContext = void*;
51 /** Function called when SkImage no longer shares pixels. ReleaseContext is
52     provided by caller when SkImage is created, and may be nullptr.
53 */
54 using RasterReleaseProc = void(const void* pixels, ReleaseContext);
55 
56 /** Creates a CPU-backed SkImage from bitmap, sharing or copying bitmap pixels. If the bitmap
57     is marked immutable, and its pixel memory is shareable, it may be shared
58     instead of copied.
59 
60     SkImage is returned if bitmap is valid. Valid SkBitmap parameters include:
61     dimensions are greater than zero;
62     each dimension fits in 29 bits;
63     SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
64     row bytes are large enough to hold one row of pixels;
65     pixel address is not nullptr.
66 
67     @param bitmap  SkImageInfo, row bytes, and pixels
68     @return        created SkImage, or nullptr
69 */
70 SK_API sk_sp<SkImage> RasterFromBitmap(const SkBitmap& bitmap);
71 
72 /** Creates a CPU-backed SkImage from compressed data.
73 
74     This method will decompress the compressed data and create an image wrapping
75     it. Any mipmap levels present in the compressed data are discarded.
76 
77     @param data     compressed data to store in SkImage
78     @param width    width of full SkImage
79     @param height   height of full SkImage
80     @param type     type of compression used
81     @return         created SkImage, or nullptr
82 */
83 SK_API sk_sp<SkImage> RasterFromCompressedTextureData(sk_sp<SkData> data,
84                                                       int width,
85                                                       int height,
86                                                       SkTextureCompressionType type);
87 
88 /**
89  *  Return a SkImage using the encoded data, but attempts to defer decoding until the
90  *  image is actually used/drawn. This deferral allows the system to cache the result, either on the
91  *  CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may
92  *  be purged, causing the next draw of the image to have to re-decode.
93  *
94  *  If alphaType is nullopt, the image's alpha type will be chosen automatically based on the
95  *  image format. Transparent images will default to kPremul_SkAlphaType. If alphaType contains
96  *  kPremul_SkAlphaType or kUnpremul_SkAlphaType, that alpha type will be used. Forcing opaque
97  *  (passing kOpaque_SkAlphaType) is not allowed, and will return nullptr.
98  *
99  *  If the encoded format is not supported, nullptr is returned.
100  *
101  *  If possible, clients should use SkCodecs::DeferredImage instead.
102  *
103  *  @param encoded  the encoded data
104  *  @return         created SkImage, or nullptr
105 
106     example: https://fiddle.skia.org/c/@Image_DeferredFromEncodedData
107 */
108 SK_API sk_sp<SkImage> DeferredFromEncodedData(sk_sp<SkData> encoded,
109                                               std::optional<SkAlphaType> alphaType = std::nullopt);
110 
111 /** Creates SkImage from data returned by imageGenerator. The image data will not be created
112     (on either the CPU or GPU) until the image is actually drawn.
113     Generated data is owned by SkImage and may not be shared or accessed.
114 
115     SkImage is returned if generator data is valid. Valid data parameters vary by type of data
116     and platform.
117 
118     imageGenerator may wrap SkPicture data, codec data, or custom data.
119 
120     @param imageGenerator  stock or custom routines to retrieve SkImage
121     @return                created SkImage, or nullptr
122 */
123 SK_API sk_sp<SkImage> DeferredFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator);
124 
125 enum class BitDepth {
126     kU8,   //!< uses 8-bit unsigned int per color component
127     kF16,  //!< uses 16-bit float per color component
128 };
129 
130 /** Creates SkImage from picture. Returned SkImage width and height are set by dimensions.
131     SkImage draws picture with matrix and paint, set to bitDepth and colorSpace.
132 
133     The Picture data is not turned into an image (CPU or GPU) until it is drawn.
134 
135     If matrix is nullptr, draws with identity SkMatrix. If paint is nullptr, draws
136     with default SkPaint. colorSpace may be nullptr.
137 
138     @param picture     stream of drawing commands
139     @param dimensions  width and height
140     @param matrix      SkMatrix to rotate, scale, translate, and so on; may be nullptr
141     @param paint       SkPaint to apply transparency, filtering, and so on; may be nullptr
142     @param bitDepth    8-bit integer or 16-bit float: per component
143     @param colorSpace  range of colors; may be nullptr
144     @param props       props to use when rasterizing the picture
145     @return            created SkImage, or nullptr
146 */
147 SK_API sk_sp<SkImage> DeferredFromPicture(sk_sp<SkPicture> picture,
148                                           const SkISize& dimensions,
149                                           const SkMatrix* matrix,
150                                           const SkPaint* paint,
151                                           BitDepth bitDepth,
152                                           sk_sp<SkColorSpace> colorSpace,
153                                           SkSurfaceProps props);
154 SK_API sk_sp<SkImage> DeferredFromPicture(sk_sp<SkPicture> picture,
155                                           const SkISize& dimensions,
156                                           const SkMatrix* matrix,
157                                           const SkPaint* paint,
158                                           BitDepth bitDepth,
159                                           sk_sp<SkColorSpace> colorSpace);
160 
161 /** Creates a CPU-backed SkImage from pixmap, copying the pixel data.
162     As a result, pixmap pixels may be modified or deleted without affecting SkImage.
163 
164     SkImage is returned if SkPixmap is valid. Valid SkPixmap parameters include:
165     dimensions are greater than zero;
166     each dimension fits in 29 bits;
167     SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
168     row bytes are large enough to hold one row of pixels;
169     pixel address is not nullptr.
170 
171     @param pixmap  SkImageInfo, pixel address, and row bytes
172     @return        copy of SkPixmap pixels, or nullptr
173 
174     example: https://fiddle.skia.org/c/@Image_RasterFromPixmapCopy
175 */
176 SK_API sk_sp<SkImage> RasterFromPixmapCopy(const SkPixmap& pixmap);
177 
178 /** Creates CPU-backed SkImage from pixmap, sharing SkPixmap pixels. Pixels must remain valid and
179     unchanged until rasterReleaseProc is called. rasterReleaseProc is passed
180     releaseContext when SkImage is deleted or no longer refers to pixmap pixels.
181 
182     Pass nullptr for rasterReleaseProc to share SkPixmap without requiring a callback
183     when SkImage is released. Pass nullptr for releaseContext if rasterReleaseProc
184     does not require state.
185 
186     SkImage is returned if pixmap is valid. Valid SkPixmap parameters include:
187     dimensions are greater than zero;
188     each dimension fits in 29 bits;
189     SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
190     row bytes are large enough to hold one row of pixels;
191     pixel address is not nullptr.
192 
193     @param pixmap             SkImageInfo, pixel address, and row bytes
194     @param rasterReleaseProc  function called when pixels can be released; or nullptr
195     @param releaseContext     state passed to rasterReleaseProc; or nullptr
196     @return                   SkImage sharing pixmap
197 */
198 SK_API sk_sp<SkImage> RasterFromPixmap(const SkPixmap& pixmap,
199                                        RasterReleaseProc rasterReleaseProc,
200                                        ReleaseContext releaseContext);
201 
202 /** Creates CPU-backed SkImage from pixel data described by info.
203     The pixels data will *not* be copied.
204 
205     SkImage is returned if SkImageInfo is valid. Valid SkImageInfo parameters include:
206     dimensions are greater than zero;
207     each dimension fits in 29 bits;
208     SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
209     rowBytes are large enough to hold one row of pixels;
210     pixels is not nullptr, and contains enough data for SkImage.
211 
212     @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
213     @param pixels    address or pixel storage
214     @param rowBytes  size of pixel row or larger
215     @return          SkImage sharing pixels, or nullptr
216 */
217 SK_API sk_sp<SkImage> RasterFromData(const SkImageInfo& info,
218                                      sk_sp<SkData> pixels,
219                                      size_t rowBytes);
220 
221 /** Creates a filtered SkImage on the CPU. filter processes the src image, potentially changing
222     the color, position, and size. subset is the bounds of src that are processed
223     by filter. clipBounds is the expected bounds of the filtered SkImage. outSubset
224     is required storage for the actual bounds of the filtered SkImage. offset is
225     required storage for translation of returned SkImage.
226 
227     Returns nullptr a filtered result could not be created. If nullptr is returned, outSubset
228     and offset are undefined.
229 
230     Useful for animation of SkImageFilter that varies size from frame to frame.
231     outSubset describes the valid bounds of returned image. offset translates the returned SkImage
232     to keep subsequent animation frames aligned with respect to each other.
233 
234     @param src         the image to be filtered
235     @param filter      the image filter to be applied
236     @param subset      bounds of SkImage processed by filter
237     @param clipBounds  expected bounds of filtered SkImage
238     @param outSubset   storage for returned SkImage bounds
239     @param offset      storage for returned SkImage translation
240     @return            filtered SkImage, or nullptr
241 */
242 SK_API sk_sp<SkImage> MakeWithFilter(sk_sp<SkImage> src,
243                                      const SkImageFilter* filter,
244                                      const SkIRect& subset,
245                                      const SkIRect& clipBounds,
246                                      SkIRect* outSubset,
247                                      SkIPoint* offset);
248 
249 }  // namespace SkImages
250 
251 /** \class SkImage
252     SkImage describes a two dimensional array of pixels to draw. The pixels may be
253     decoded in a raster bitmap, encoded in a SkPicture or compressed data stream,
254     or located in GPU memory as a GPU texture.
255 
256     SkImage cannot be modified after it is created. SkImage may allocate additional
257     storage as needed; for instance, an encoded SkImage may decode when drawn.
258 
259     SkImage width and height are greater than zero. Creating an SkImage with zero width
260     or height returns SkImage equal to nullptr.
261 
262     SkImage may be created from SkBitmap, SkPixmap, SkSurface, SkPicture, encoded streams,
263     GPU texture, YUV_ColorSpace data, or hardware buffer. Encoded streams supported
264     include BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP. Supported encoding details
265     vary with platform.
266 
267     See SkImages namespace for the static factory methods to make SkImages.
268 
269     Clients should *not* subclass SkImage as there is a lot of internal machinery that is
270     not publicly accessible.
271 */
272 class SK_API SkImage : public SkRefCnt {
273 public:
274     /** Returns a SkImageInfo describing the width, height, color type, alpha type, and color space
275         of the SkImage.
276 
277         @return  image info of SkImage.
278     */
imageInfo()279     const SkImageInfo& imageInfo() const { return fInfo; }
280 
281     /** Returns pixel count in each row.
282 
283         @return  pixel width in SkImage
284     */
width()285     int width() const { return fInfo.width(); }
286 
287     /** Returns pixel row count.
288 
289         @return  pixel height in SkImage
290     */
height()291     int height() const { return fInfo.height(); }
292 
293     /** Returns SkISize { width(), height() }.
294 
295         @return  integral size of width() and height()
296     */
dimensions()297     SkISize dimensions() const { return SkISize::Make(fInfo.width(), fInfo.height()); }
298 
299     /** Returns SkIRect { 0, 0, width(), height() }.
300 
301         @return  integral rectangle from origin to width() and height()
302     */
bounds()303     SkIRect bounds() const { return SkIRect::MakeWH(fInfo.width(), fInfo.height()); }
304 
305     /** Returns value unique to image. SkImage contents cannot change after SkImage is
306         created. Any operation to create a new SkImage will receive generate a new
307         unique number.
308 
309         @return  unique identifier
310     */
uniqueID()311     uint32_t uniqueID() const { return fUniqueID; }
312 
313     /** Returns SkAlphaType.
314 
315         SkAlphaType returned was a parameter to an SkImage constructor,
316         or was parsed from encoded data.
317 
318         @return  SkAlphaType in SkImage
319 
320         example: https://fiddle.skia.org/c/@Image_alphaType
321     */
322     SkAlphaType alphaType() const;
323 
324     /** Returns SkColorType if known; otherwise, returns kUnknown_SkColorType.
325 
326         @return  SkColorType of SkImage
327 
328         example: https://fiddle.skia.org/c/@Image_colorType
329     */
330     SkColorType colorType() const;
331 
332     /** Returns SkColorSpace, the range of colors, associated with SkImage.  The
333         reference count of SkColorSpace is unchanged. The returned SkColorSpace is
334         immutable.
335 
336         SkColorSpace returned was passed to an SkImage constructor,
337         or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
338         is drawn, depending on the capabilities of the SkSurface receiving the drawing.
339 
340         @return  SkColorSpace in SkImage, or nullptr
341 
342         example: https://fiddle.skia.org/c/@Image_colorSpace
343     */
344     SkColorSpace* colorSpace() const;
345 
346     /** Returns a smart pointer to SkColorSpace, the range of colors, associated with
347         SkImage.  The smart pointer tracks the number of objects sharing this
348         SkColorSpace reference so the memory is released when the owners destruct.
349 
350         The returned SkColorSpace is immutable.
351 
352         SkColorSpace returned was passed to an SkImage constructor,
353         or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
354         is drawn, depending on the capabilities of the SkSurface receiving the drawing.
355 
356         @return  SkColorSpace in SkImage, or nullptr, wrapped in a smart pointer
357 
358         example: https://fiddle.skia.org/c/@Image_refColorSpace
359     */
360     sk_sp<SkColorSpace> refColorSpace() const;
361 
362     /** Returns true if SkImage pixels represent transparency only. If true, each pixel
363         is packed in 8 bits as defined by kAlpha_8_SkColorType.
364 
365         @return  true if pixels represent a transparency mask
366 
367         example: https://fiddle.skia.org/c/@Image_isAlphaOnly
368     */
369     bool isAlphaOnly() const;
370 
371     /** Returns true if pixels ignore their alpha value and are treated as fully opaque.
372 
373         @return  true if SkAlphaType is kOpaque_SkAlphaType
374     */
isOpaque()375     bool isOpaque() const { return SkAlphaTypeIsOpaque(this->alphaType()); }
376 
377     /**
378      *  Make a shader with the specified tiling and mipmap sampling.
379      */
380     sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
381                                const SkMatrix* localMatrix = nullptr) const;
382     sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
383                                const SkMatrix& lm) const;
384     /** Defaults to clamp in both X and Y. */
385     sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
386     sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling,
387                                const SkMatrix* lm = nullptr) const;
388 
389     /**
390      *  makeRawShader functions like makeShader, but for images that contain non-color data.
391      *  This includes images encoding things like normals, material properties (eg, roughness),
392      *  heightmaps, or any other purely mathematical data that happens to be stored in an image.
393      *  These types of images are useful with some programmable shaders (see: SkRuntimeEffect).
394      *
395      *  Raw image shaders work like regular image shaders (including filtering and tiling), with
396      *  a few major differences:
397      *    - No color space transformation is ever applied (the color space of the image is ignored).
398      *    - Images with an alpha type of kUnpremul are *not* automatically premultiplied.
399      *    - Bicubic filtering is not supported. If SkSamplingOptions::useCubic is true, these
400      *      factories will return nullptr.
401      */
402     sk_sp<SkShader> makeRawShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
403                                   const SkMatrix* localMatrix = nullptr) const;
404     sk_sp<SkShader> makeRawShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
405                                   const SkMatrix& lm) const;
406     /** Defaults to clamp in both X and Y. */
407     sk_sp<SkShader> makeRawShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
408     sk_sp<SkShader> makeRawShader(const SkSamplingOptions& sampling,
409                                   const SkMatrix* lm = nullptr) const;
410 
411     /** Copies SkImage pixel address, row bytes, and SkImageInfo to pixmap, if address
412         is available, and returns true. If pixel address is not available, return
413         false and leave pixmap unchanged.
414 
415         @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored
416         @return        true if SkImage has direct access to pixels
417 
418         example: https://fiddle.skia.org/c/@Image_peekPixels
419     */
420     bool peekPixels(SkPixmap* pixmap) const;
421 
422     /** Returns true if the contents of SkImage was created on or uploaded to GPU memory,
423         and is available as a GPU texture.
424 
425         @return  true if SkImage is a GPU texture
426 
427         example: https://fiddle.skia.org/c/@Image_isTextureBacked
428     */
429     virtual bool isTextureBacked() const = 0;
430 
431     /** Returns an approximation of the amount of texture memory used by the image. Returns
432         zero if the image is not texture backed or if the texture has an external format.
433      */
434     virtual size_t textureSize() const = 0;
435 
436     /** Returns true if SkImage can be drawn on either raster surface or GPU surface.
437         If context is nullptr, tests if SkImage draws on raster surface;
438         otherwise, tests if SkImage draws on GPU surface associated with context.
439 
440         SkImage backed by GPU texture may become invalid if associated context is
441         invalid. lazy image may be invalid and may not draw to raster surface or
442         GPU surface or both.
443 
444         @param context  GPU context
445         @return         true if SkImage can be drawn
446 
447         example: https://fiddle.skia.org/c/@Image_isValid
448     */
449     virtual bool isValid(GrRecordingContext* context) const = 0;
450 
451     /** \enum SkImage::CachingHint
452         CachingHint selects whether Skia may internally cache SkBitmap generated by
453         decoding SkImage, or by copying SkImage from GPU to CPU. The default behavior
454         allows caching SkBitmap.
455 
456         Choose kDisallow_CachingHint if SkImage pixels are to be used only once, or
457         if SkImage pixels reside in a cache outside of Skia, or to reduce memory pressure.
458 
459         Choosing kAllow_CachingHint does not ensure that pixels will be cached.
460         SkImage pixels may not be cached if memory requirements are too large or
461         pixels are not accessible.
462     */
463     enum CachingHint {
464         kAllow_CachingHint,    //!< allows internally caching decoded and copied pixels
465         kDisallow_CachingHint, //!< disallows internally caching decoded and copied pixels
466     };
467 
468     /** Copies SkRect of pixels from SkImage to dstPixels. Copy starts at offset (srcX, srcY),
469         and does not exceed SkImage (width(), height()).
470 
471         dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
472         destination. dstRowBytes specifies the gap from one destination row to the next.
473         Returns true if pixels are copied. Returns false if:
474         - dstInfo.addr() equals nullptr
475         - dstRowBytes is less than dstInfo.minRowBytes()
476         - SkPixelRef is nullptr
477 
478         Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
479         kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
480         If SkImage SkColorType is kGray_8_SkColorType, dstInfo.colorSpace() must match.
481         If SkImage SkAlphaType is kOpaque_SkAlphaType, dstInfo.alphaType() must
482         match. If SkImage SkColorSpace is nullptr, dstInfo.colorSpace() must match. Returns
483         false if pixel conversion is not possible.
484 
485         srcX and srcY may be negative to copy only top or left of source. Returns
486         false if width() or height() is zero or negative.
487         Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
488 
489         If cachingHint is kAllow_CachingHint, pixels may be retained locally.
490         If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
491 
492         @param context      the GrDirectContext in play, if it exists
493         @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace
494         @param dstPixels    destination pixel storage
495         @param dstRowBytes  destination row length
496         @param srcX         column index whose absolute value is less than width()
497         @param srcY         row index whose absolute value is less than height()
498         @param cachingHint  whether the pixels should be cached locally
499         @return             true if pixels are copied to dstPixels
500     */
501     bool readPixels(GrDirectContext* context,
502                     const SkImageInfo& dstInfo,
503                     void* dstPixels,
504                     size_t dstRowBytes,
505                     int srcX, int srcY,
506                     CachingHint cachingHint = kAllow_CachingHint) const;
507 
508     /** Copies a SkRect of pixels from SkImage to dst. Copy starts at (srcX, srcY), and
509         does not exceed SkImage (width(), height()).
510 
511         dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
512         and row bytes of destination. dst.rowBytes() specifics the gap from one destination
513         row to the next. Returns true if pixels are copied. Returns false if:
514         - dst pixel storage equals nullptr
515         - dst.rowBytes is less than SkImageInfo::minRowBytes
516         - SkPixelRef is nullptr
517 
518         Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
519         kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
520         If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
521         If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
522         match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
523         false if pixel conversion is not possible.
524 
525         srcX and srcY may be negative to copy only top or left of source. Returns
526         false if width() or height() is zero or negative.
527         Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
528 
529         If cachingHint is kAllow_CachingHint, pixels may be retained locally.
530         If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
531 
532         @param context      the GrDirectContext in play, if it exists
533         @param dst          destination SkPixmap: SkImageInfo, pixels, row bytes
534         @param srcX         column index whose absolute value is less than width()
535         @param srcY         row index whose absolute value is less than height()
536         @param cachingHint  whether the pixels should be cached locallyZ
537         @return             true if pixels are copied to dst
538     */
539     bool readPixels(GrDirectContext* context,
540                     const SkPixmap& dst,
541                     int srcX,
542                     int srcY,
543                     CachingHint cachingHint = kAllow_CachingHint) const;
544 
545 #if defined(GRAPHITE_TEST_UTILS)
546     bool readPixelsGraphite(skgpu::graphite::Recorder*,
547                             const SkPixmap& dst,
548                             int srcX,
549                             int srcY) const;
550 #endif
551 
552 #ifndef SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API
553     /** Deprecated. Use the variants that accept a GrDirectContext. */
554     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
555                     int srcX, int srcY, CachingHint cachingHint = kAllow_CachingHint) const;
556     bool readPixels(const SkPixmap& dst, int srcX, int srcY,
557                     CachingHint cachingHint = kAllow_CachingHint) const;
558 #endif
559 
560     /** The result from asyncRescaleAndReadPixels() or asyncRescaleAndReadPixelsYUV420(). */
561     class AsyncReadResult {
562     public:
563         AsyncReadResult(const AsyncReadResult&) = delete;
564         AsyncReadResult(AsyncReadResult&&) = delete;
565         AsyncReadResult& operator=(const AsyncReadResult&) = delete;
566         AsyncReadResult& operator=(AsyncReadResult&&) = delete;
567 
568         virtual ~AsyncReadResult() = default;
569         virtual int count() const = 0;
570         virtual const void* data(int i) const = 0;
571         virtual size_t rowBytes(int i) const = 0;
572 
573     protected:
574         AsyncReadResult() = default;
575     };
576 
577     /** Client-provided context that is passed to client-provided ReadPixelsContext. */
578     using ReadPixelsContext = void*;
579 
580     /**  Client-provided callback to asyncRescaleAndReadPixels() or
581          asyncRescaleAndReadPixelsYUV420() that is called when read result is ready or on failure.
582      */
583     using ReadPixelsCallback = void(ReadPixelsContext, std::unique_ptr<const AsyncReadResult>);
584 
585     enum class RescaleGamma : bool { kSrc, kLinear };
586 
587     enum class RescaleMode {
588         kNearest,
589         kLinear,
590         kRepeatedLinear,
591         kRepeatedCubic,
592     };
593 
594     /** Makes image pixel data available to caller, possibly asynchronously. It can also rescale
595         the image pixels.
596 
597         Currently asynchronous reads are only supported on the GPU backend and only when the
598         underlying 3D API supports transfer buffers and CPU/GPU synchronization primitives. In all
599         other cases this operates synchronously.
600 
601         Data is read from the source sub-rectangle, is optionally converted to a linear gamma, is
602         rescaled to the size indicated by 'info', is then converted to the color space, color type,
603         and alpha type of 'info'. A 'srcRect' that is not contained by the bounds of the image
604         causes failure.
605 
606         When the pixel data is ready the caller's ReadPixelsCallback is called with a
607         AsyncReadResult containing pixel data in the requested color type, alpha type, and color
608         space. The AsyncReadResult will have count() == 1. Upon failure the callback is called with
609         nullptr for AsyncReadResult. For a GPU image this flushes work but a submit must occur to
610         guarantee a finite time before the callback is called.
611 
612         The data is valid for the lifetime of AsyncReadResult with the exception that if the SkImage
613         is GPU-backed the data is immediately invalidated if the context is abandoned or
614         destroyed.
615 
616         @param info            info of the requested pixels
617         @param srcRect         subrectangle of image to read
618         @param rescaleGamma    controls whether rescaling is done in the image's gamma or whether
619                                the source data is transformed to a linear gamma before rescaling.
620         @param rescaleMode     controls the technique (and cost) of the rescaling
621         @param callback        function to call with result of the read
622         @param context         passed to callback
623     */
624     void asyncRescaleAndReadPixels(const SkImageInfo& info,
625                                    const SkIRect& srcRect,
626                                    RescaleGamma rescaleGamma,
627                                    RescaleMode rescaleMode,
628                                    ReadPixelsCallback callback,
629                                    ReadPixelsContext context) const;
630 
631     /**
632         Similar to asyncRescaleAndReadPixels but performs an additional conversion to YUV. The
633         RGB->YUV conversion is controlled by 'yuvColorSpace'. The YUV data is returned as three
634         planes ordered y, u, v. The u and v planes are half the width and height of the resized
635         rectangle. The y, u, and v values are single bytes. Currently this fails if 'dstSize'
636         width and height are not even. A 'srcRect' that is not contained by the bounds of the
637         image causes failure.
638 
639         When the pixel data is ready the caller's ReadPixelsCallback is called with a
640         AsyncReadResult containing the planar data. The AsyncReadResult will have count() == 3.
641         Upon failure the callback is called with nullptr for AsyncReadResult. For a GPU image this
642         flushes work but a submit must occur to guarantee a finite time before the callback is
643         called.
644 
645         The data is valid for the lifetime of AsyncReadResult with the exception that if the SkImage
646         is GPU-backed the data is immediately invalidated if the context is abandoned or
647         destroyed.
648 
649         @param yuvColorSpace  The transformation from RGB to YUV. Applied to the resized image
650                               after it is converted to dstColorSpace.
651         @param dstColorSpace  The color space to convert the resized image to, after rescaling.
652         @param srcRect        The portion of the image to rescale and convert to YUV planes.
653         @param dstSize        The size to rescale srcRect to
654         @param rescaleGamma   controls whether rescaling is done in the image's gamma or whether
655                               the source data is transformed to a linear gamma before rescaling.
656         @param rescaleMode    controls the technique (and cost) of the rescaling
657         @param callback       function to call with the planar read result
658         @param context        passed to callback
659      */
660     void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
661                                          sk_sp<SkColorSpace> dstColorSpace,
662                                          const SkIRect& srcRect,
663                                          const SkISize& dstSize,
664                                          RescaleGamma rescaleGamma,
665                                          RescaleMode rescaleMode,
666                                          ReadPixelsCallback callback,
667                                          ReadPixelsContext context) const;
668 
669     /**
670      * Identical to asyncRescaleAndReadPixelsYUV420 but a fourth plane is returned in the
671      * AsyncReadResult passed to 'callback'. The fourth plane contains the alpha chanel at the
672      * same full resolution as the Y plane.
673      */
674     void asyncRescaleAndReadPixelsYUVA420(SkYUVColorSpace yuvColorSpace,
675                                           sk_sp<SkColorSpace> dstColorSpace,
676                                           const SkIRect& srcRect,
677                                           const SkISize& dstSize,
678                                           RescaleGamma rescaleGamma,
679                                           RescaleMode rescaleMode,
680                                           ReadPixelsCallback callback,
681                                           ReadPixelsContext context) const;
682 
683     /** Copies SkImage to dst, scaling pixels to fit dst.width() and dst.height(), and
684         converting pixels to match dst.colorType() and dst.alphaType(). Returns true if
685         pixels are copied. Returns false if dst.addr() is nullptr, or dst.rowBytes() is
686         less than dst SkImageInfo::minRowBytes.
687 
688         Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
689         kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
690         If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
691         If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
692         match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
693         false if pixel conversion is not possible.
694 
695         If cachingHint is kAllow_CachingHint, pixels may be retained locally.
696         If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
697 
698         @param dst            destination SkPixmap: SkImageInfo, pixels, row bytes
699         @return               true if pixels are scaled to fit dst
700     */
701     bool scalePixels(const SkPixmap& dst, const SkSamplingOptions&,
702                      CachingHint cachingHint = kAllow_CachingHint) const;
703 
704     /** Returns encoded SkImage pixels as SkData, if SkImage was created from supported
705         encoded stream format. Platform support for formats vary and may require building
706         with one or more of: SK_ENCODE_JPEG, SK_ENCODE_PNG, SK_ENCODE_WEBP.
707 
708         Returns nullptr if SkImage contents are not encoded.
709 
710         @return  encoded SkImage, or nullptr
711 
712         example: https://fiddle.skia.org/c/@Image_refEncodedData
713     */
714     sk_sp<SkData> refEncodedData() const;
715 
716     /** Returns subset of this image.
717 
718         Returns nullptr if any of the following are true:
719           - Subset is empty
720           - Subset is not contained inside the image's bounds
721           - Pixels in the source image could not be read or copied
722           - This image is texture-backed and the provided context is null or does not match
723             the source image's context.
724 
725         If the source image was texture-backed, the resulting image will be texture-backed also.
726         Otherwise, the returned image will be raster-backed.
727 
728         @param direct  the GrDirectContext of the source image (nullptr is ok if the source image
729                        is not texture-backed).
730         @param subset  bounds of returned SkImage
731         @return        the subsetted image, or nullptr
732 
733         example: https://fiddle.skia.org/c/@Image_makeSubset
734     */
735     virtual sk_sp<SkImage> makeSubset(GrDirectContext* direct, const SkIRect& subset) const = 0;
736 
737     struct RequiredProperties {
738         bool fMipmapped;
739 
740         bool operator==(const RequiredProperties& other) const {
741             return fMipmapped == other.fMipmapped;
742         }
743 
744         bool operator!=(const RequiredProperties& other) const { return !(*this == other); }
745 
746         bool operator<(const RequiredProperties& other) const {
747             return fMipmapped < other.fMipmapped;
748         }
749     };
750 
751     /** Returns subset of this image.
752 
753         Returns nullptr if any of the following are true:
754           - Subset is empty
755           - Subset is not contained inside the image's bounds
756           - Pixels in the image could not be read or copied
757           - This image is texture-backed and the provided context is null or does not match
758             the source image's context.
759 
760         If the source image was texture-backed, the resulting image will be texture-backed also.
761         Otherwise, the returned image will be raster-backed.
762 
763         @param recorder            the recorder of the source image (nullptr is ok if the
764                                    source image was texture-backed).
765         @param subset              bounds of returned SkImage
766         @param RequiredProperties  properties the returned SkImage must possess (e.g. mipmaps)
767         @return                    the subsetted image, or nullptr
768     */
769     virtual sk_sp<SkImage> makeSubset(skgpu::graphite::Recorder*,
770                                       const SkIRect& subset,
771                                       RequiredProperties) const = 0;
772 
773     /**
774      *  Returns true if the image has mipmap levels.
775      */
776     bool hasMipmaps() const;
777 
778     /**
779      *  Returns true if the image holds protected content.
780      */
781     bool isProtected() const;
782 
783     /**
784      *  Returns an image with the same "base" pixels as the this image, but with mipmap levels
785      *  automatically generated and attached.
786      */
787     sk_sp<SkImage> withDefaultMipmaps() const;
788 
789     /** Returns raster image or lazy image. Copies SkImage backed by GPU texture into
790         CPU memory if needed. Returns original SkImage if decoded in raster bitmap,
791         or if encoded in a stream.
792 
793         Returns nullptr if backed by GPU texture and copy fails.
794 
795         @return  raster image, lazy image, or nullptr
796 
797         example: https://fiddle.skia.org/c/@Image_makeNonTextureImage
798     */
799     sk_sp<SkImage> makeNonTextureImage(GrDirectContext* = nullptr) const;
800 
801     /** Returns raster image. Copies SkImage backed by GPU texture into CPU memory,
802         or decodes SkImage from lazy image. Returns original SkImage if decoded in
803         raster bitmap.
804 
805         Returns nullptr if copy, decode, or pixel read fails.
806 
807         If cachingHint is kAllow_CachingHint, pixels may be retained locally.
808         If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
809 
810         @return  raster image, or nullptr
811 
812         example: https://fiddle.skia.org/c/@Image_makeRasterImage
813     */
814     sk_sp<SkImage> makeRasterImage(GrDirectContext*,
815                                    CachingHint cachingHint = kDisallow_CachingHint) const;
816 
817 #if !defined(SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API)
818     sk_sp<SkImage> makeRasterImage(CachingHint cachingHint = kDisallow_CachingHint) const {
819         return this->makeRasterImage(nullptr, cachingHint);
820     }
821 #endif
822 
823     /** Deprecated.
824      */
825     enum LegacyBitmapMode {
826         kRO_LegacyBitmapMode, //!< returned bitmap is read-only and immutable
827     };
828 
829     /** Deprecated.
830         Creates raster SkBitmap with same pixels as SkImage. If legacyBitmapMode is
831         kRO_LegacyBitmapMode, returned bitmap is read-only and immutable.
832         Returns true if SkBitmap is stored in bitmap. Returns false and resets bitmap if
833         SkBitmap write did not succeed.
834 
835         @param bitmap            storage for legacy SkBitmap
836         @param legacyBitmapMode  bitmap is read-only and immutable
837         @return                  true if SkBitmap was created
838     */
839     bool asLegacyBitmap(SkBitmap* bitmap,
840                         LegacyBitmapMode legacyBitmapMode = kRO_LegacyBitmapMode) const;
841 
842     /** Returns true if SkImage is backed by an image-generator or other service that creates
843         and caches its pixels or texture on-demand.
844 
845         @return  true if SkImage is created as needed
846 
847         example: https://fiddle.skia.org/c/@Image_isLazyGenerated_a
848         example: https://fiddle.skia.org/c/@Image_isLazyGenerated_b
849     */
850     virtual bool isLazyGenerated() const = 0;
851 
852     /** Creates SkImage in target SkColorSpace.
853         Returns nullptr if SkImage could not be created.
854 
855         Returns original SkImage if it is in target SkColorSpace.
856         Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
857         If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
858 
859         If this image is texture-backed, the context parameter is required and must match the
860         context of the source image.
861 
862         @param direct  The GrDirectContext in play, if it exists
863         @param target  SkColorSpace describing color range of returned SkImage
864         @return        created SkImage in target SkColorSpace
865 
866         example: https://fiddle.skia.org/c/@Image_makeColorSpace
867     */
868     virtual sk_sp<SkImage> makeColorSpace(GrDirectContext* direct,
869                                           sk_sp<SkColorSpace> target) const = 0;
870 
871     /** Creates SkImage in target SkColorSpace.
872         Returns nullptr if SkImage could not be created.
873 
874         Returns original SkImage if it is in target SkColorSpace.
875         Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
876         If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
877 
878         If this image is graphite-backed, the recorder parameter is required.
879 
880         @param targetColorSpace    SkColorSpace describing color range of returned SkImage
881         @param recorder            The Recorder in which to create the new image
882         @param RequiredProperties  properties the returned SkImage must possess (e.g. mipmaps)
883         @return                    created SkImage in target SkColorSpace
884     */
885     virtual sk_sp<SkImage> makeColorSpace(skgpu::graphite::Recorder*,
886                                           sk_sp<SkColorSpace> targetColorSpace,
887                                           RequiredProperties) const = 0;
888 
889     /** Experimental.
890         Creates SkImage in target SkColorType and SkColorSpace.
891         Returns nullptr if SkImage could not be created.
892 
893         Returns original SkImage if it is in target SkColorType and SkColorSpace.
894 
895         If this image is texture-backed, the context parameter is required and must match the
896         context of the source image.
897 
898         @param direct           The GrDirectContext in play, if it exists
899         @param targetColorType  SkColorType of returned SkImage
900         @param targetColorSpace SkColorSpace of returned SkImage
901         @return                 created SkImage in target SkColorType and SkColorSpace
902     */
903     virtual sk_sp<SkImage> makeColorTypeAndColorSpace(GrDirectContext* direct,
904                                                       SkColorType targetColorType,
905                                                       sk_sp<SkColorSpace> targetCS) const = 0;
906 
907     /** Experimental.
908         Creates SkImage in target SkColorType and SkColorSpace.
909         Returns nullptr if SkImage could not be created.
910 
911         Returns original SkImage if it is in target SkColorType and SkColorSpace.
912 
913         If this image is graphite-backed, the recorder parameter is required.
914 
915         @param targetColorType     SkColorType of returned SkImage
916         @param targetColorSpace    SkColorSpace of returned SkImage
917         @param recorder            The Recorder in which to create the new image
918         @param RequiredProperties  properties the returned SkImage must possess (e.g. mipmaps)
919         @return                    created SkImage in target SkColorType and SkColorSpace
920     */
921     virtual sk_sp<SkImage> makeColorTypeAndColorSpace(skgpu::graphite::Recorder*,
922                                                       SkColorType targetColorType,
923                                                       sk_sp<SkColorSpace> targetColorSpace,
924                                                       RequiredProperties) const = 0;
925 
926     /** Creates a new SkImage identical to this one, but with a different SkColorSpace.
927         This does not convert the underlying pixel data, so the resulting image will draw
928         differently.
929     */
930     sk_sp<SkImage> reinterpretColorSpace(sk_sp<SkColorSpace> newColorSpace) const;
931 
932 private:
933     SkImage(const SkImageInfo& info, uint32_t uniqueID);
934 
935     friend class SkBitmap;
936     friend class SkImage_Base;   // for private ctor
937     friend class SkImage_Raster; // for withMipmaps
938     friend class SkMipmapBuilder;
939 
940     SkImageInfo     fInfo;
941     const uint32_t  fUniqueID;
942 
943     sk_sp<SkImage> withMipmaps(sk_sp<SkMipmap>) const;
944 
945     using INHERITED = SkRefCnt;
946 };
947 
948 #endif
949