1 | use crate::{ |
2 | gpu, prelude::*, AlphaType, Bitmap, ColorSpace, ColorType, Data, EncodedImageFormat, IPoint, |
3 | IRect, ISize, ImageFilter, ImageGenerator, ImageInfo, Matrix, Paint, Picture, Pixmap, |
4 | SamplingOptions, Shader, SurfaceProps, TextureCompressionType, TileMode, |
5 | }; |
6 | use skia_bindings::{self as sb, SkImage, SkRefCntBase}; |
7 | use std::{fmt, ptr}; |
8 | |
9 | pub use super::CubicResampler; |
10 | |
11 | #[deprecated (since = "0.62.0" , note = "Use TextureCompressionType" )] |
12 | pub use crate::TextureCompressionType as CompressionType; |
13 | |
14 | #[deprecated (since = "0.63.0" , note = "Use images::BitDepth" )] |
15 | pub use images::BitDepth; |
16 | |
17 | pub mod images { |
18 | use std::{mem, ptr}; |
19 | |
20 | use skia_bindings as sb; |
21 | |
22 | #[allow (unused)] // doc only |
23 | use crate::ColorType; |
24 | use crate::{ |
25 | prelude::*, AlphaType, Bitmap, ColorSpace, Data, IPoint, IRect, ISize, Image, ImageFilter, |
26 | ImageGenerator, ImageInfo, Matrix, Paint, Picture, SurfaceProps, TextureCompressionType, |
27 | }; |
28 | |
29 | /// Creates a CPU-backed [`Image`] from `bitmap`, sharing or copying `bitmap` pixels. If the bitmap |
30 | /// is marked immutable, and its pixel memory is shareable, it may be shared |
31 | /// instead of copied. |
32 | /// |
33 | /// [`Image`] is returned if bitmap is valid. Valid [`Bitmap`] parameters include: |
34 | /// dimensions are greater than zero; |
35 | /// each dimension fits in 29 bits; |
36 | /// [`ColorType`] and [`AlphaType`] are valid, and [`ColorType`] is not [`ColorType::Unknown`]; |
37 | /// row bytes are large enough to hold one row of pixels; |
38 | /// pixel address is not `None`. |
39 | /// |
40 | /// * `bitmap` - [`ImageInfo`], row bytes, and pixels |
41 | /// Returns: created [`Image`], or `None` |
42 | |
43 | pub fn raster_from_bitmap(bitmap: &Bitmap) -> Option<Image> { |
44 | Image::from_ptr(unsafe { sb::C_SkImages_RasterFromBitmap(bitmap.native()) }) |
45 | } |
46 | |
47 | /// Creates a CPU-backed [`Image`] from compressed data. |
48 | /// |
49 | /// This method will decompress the compressed data and create an image wrapping |
50 | /// it. Any mipmap levels present in the compressed data are discarded. |
51 | /// |
52 | /// * `data` - compressed data to store in [`Image`] |
53 | /// * `dimension` - width and height of full [`Image`] |
54 | /// * `ty` - type of compression used |
55 | /// Returns: created [`Image`], or `None` |
56 | pub fn raster_from_compressed_texture_data( |
57 | data: impl Into<Data>, |
58 | dimensions: impl Into<ISize>, |
59 | ty: TextureCompressionType, |
60 | ) -> Option<Image> { |
61 | let dimensions = dimensions.into(); |
62 | Image::from_ptr(unsafe { |
63 | sb::C_SkImages_RasterFromCompressedTextureData( |
64 | data.into().into_ptr(), |
65 | dimensions.width, |
66 | dimensions.height, |
67 | ty, |
68 | ) |
69 | }) |
70 | } |
71 | |
72 | /// Return a [`Image`] using the encoded data, but attempts to defer decoding until the |
73 | /// image is actually used/drawn. This deferral allows the system to cache the result, either on the |
74 | /// CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may |
75 | /// be purged, causing the next draw of the image to have to re-decode. |
76 | /// |
77 | /// If `alpha_type` is `None`, the image's alpha type will be chosen automatically based on the |
78 | /// image format. Transparent images will default to [`AlphaType::Premul`]. If `alpha_type` contains |
79 | /// [`AlphaType::Premul`] or [`AlphaType::Unpremul`], that alpha type will be used. Forcing opaque |
80 | /// (passing [`AlphaType::Opaque`]) is not allowed, and will return `None`. |
81 | /// |
82 | /// If the encoded format is not supported, `None` is returned. |
83 | /// |
84 | /// * `encoded` - the encoded data |
85 | /// Returns: created [`Image`], or `None` |
86 | /// |
87 | /// example: <https://fiddle.skia.org/c/@Image_DeferredFromEncodedData> |
88 | pub fn deferred_from_encoded_data( |
89 | data: impl Into<Data>, |
90 | alpha_type: impl Into<Option<AlphaType>>, |
91 | ) -> Option<Image> { |
92 | Image::from_ptr(unsafe { |
93 | sb::C_SkImages_DeferredFromEncodedData( |
94 | data.into().into_ptr(), |
95 | alpha_type |
96 | .into() |
97 | .map(|at| &at as *const _) |
98 | .unwrap_or(ptr::null()), |
99 | ) |
100 | }) |
101 | } |
102 | |
103 | /// Creates [`Image`] from data returned by `image_generator`. The image data will not be created |
104 | /// (on either the CPU or GPU) until the image is actually drawn. |
105 | /// Generated data is owned by [`Image`] and may not be shared or accessed. |
106 | /// |
107 | /// [`Image`] is returned if generator data is valid. Valid data parameters vary by type of data |
108 | /// and platform. |
109 | /// |
110 | /// `image_generator` may wrap [`Picture`] data, codec data, or custom data. |
111 | /// |
112 | /// * `image_generator` - stock or custom routines to retrieve [`Image`] |
113 | /// Returns: created [`Image`], or `None` |
114 | pub fn deferred_from_generator(mut image_generator: ImageGenerator) -> Option<Image> { |
115 | let image = Image::from_ptr(unsafe { |
116 | sb::C_SkImages_DeferredFromGenerator(image_generator.native_mut()) |
117 | }); |
118 | mem::forget(image_generator); |
119 | image |
120 | } |
121 | |
122 | pub use skia_bindings::SkImages_BitDepth as BitDepth; |
123 | variant_name!(BitDepth::F16); |
124 | |
125 | /// Creates [`Image`] from picture. Returned [`Image`] width and height are set by dimensions. |
126 | /// [`Image`] draws picture with matrix and paint, set to `bit_depth` and `color_space`. |
127 | /// |
128 | /// The Picture data is not turned into an image (CPU or GPU) until it is drawn. |
129 | /// |
130 | /// If matrix is `None`, draws with identity [`Matrix`]. If paint is `None`, draws |
131 | /// with default [`Paint`]. `color_space` may be `None`. |
132 | /// |
133 | /// * `picture` - stream of drawing commands |
134 | /// * `dimensions` - width and height |
135 | /// * `matrix` - [`Matrix`] to rotate, scale, translate, and so on; may be `None` |
136 | /// * `paint` - [`Paint`] to apply transparency, filtering, and so on; may be `None` |
137 | /// * `bit_depth` - 8-bit integer or 16-bit float: per component |
138 | /// * `color_space` - range of colors; may be `None` |
139 | /// * `props` - props to use when rasterizing the picture |
140 | /// Returns: created [`Image`], or `None` |
141 | pub fn deferred_from_picture( |
142 | picture: impl Into<Picture>, |
143 | dimensions: impl Into<ISize>, |
144 | matrix: Option<&Matrix>, |
145 | paint: Option<&Paint>, |
146 | bit_depth: BitDepth, |
147 | color_space: impl Into<Option<ColorSpace>>, |
148 | props: impl Into<Option<SurfaceProps>>, |
149 | ) -> Option<Image> { |
150 | Image::from_ptr(unsafe { |
151 | sb::C_SkImages_DeferredFromPicture( |
152 | picture.into().into_ptr(), |
153 | dimensions.into().native(), |
154 | matrix.native_ptr_or_null(), |
155 | paint.native_ptr_or_null(), |
156 | bit_depth, |
157 | color_space.into().into_ptr_or_null(), |
158 | props.into().unwrap_or_default().native(), |
159 | ) |
160 | }) |
161 | } |
162 | |
163 | // TODO: RasterFromPixmapCopy |
164 | // TODO: RasterFromPixmap |
165 | |
166 | /// Creates CPU-backed [`Image`] from pixel data described by info. |
167 | /// The pixels data will *not* be copied. |
168 | /// |
169 | /// [`Image`] is returned if [`ImageInfo`] is valid. Valid [`ImageInfo`] parameters include: |
170 | /// dimensions are greater than zero; |
171 | /// each dimension fits in 29 bits; |
172 | /// [`ColorType`] and [`AlphaType`] are valid, and [`ColorType`] is not [`ColorType::Unknown`]; |
173 | /// `row_bytes` are large enough to hold one row of pixels; |
174 | /// pixels is not `None`, and contains enough data for [`Image`]. |
175 | /// |
176 | /// * `info` - contains width, height, [`AlphaType`], [`ColorType`], [`ColorSpace`] |
177 | /// * `pixels` - address or pixel storage |
178 | /// * `row_bytes` - size of pixel row or larger |
179 | /// Returns: [`Image`] sharing pixels, or `None` |
180 | pub fn raster_from_data( |
181 | info: &ImageInfo, |
182 | pixels: impl Into<Data>, |
183 | row_bytes: usize, |
184 | ) -> Option<Image> { |
185 | Image::from_ptr(unsafe { |
186 | sb::C_SkImages_RasterFromData(info.native(), pixels.into().into_ptr(), row_bytes) |
187 | }) |
188 | } |
189 | |
190 | /// Creates a filtered [`Image`] on the CPU. filter processes the src image, potentially |
191 | /// changing the color, position, and size. subset is the bounds of src that are processed by |
192 | /// filter. `clip_bounds` is the expected bounds of the filtered [`Image`]. `out_subset` is |
193 | /// required storage for the actual bounds of the filtered [`Image`]. `offset` is required |
194 | /// storage for translation of returned [`Image`]. |
195 | /// |
196 | /// Returns `None` a filtered result could not be created. |
197 | /// |
198 | /// Useful for animation of [`ImageFilter`] that varies size from frame to frame. `out_subset` |
199 | /// describes the valid bounds of returned image. offset translates the returned [`Image`] to |
200 | /// keep subsequent animation frames aligned with respect to each other. |
201 | /// |
202 | /// * `src` - the image to be filtered |
203 | /// * `filter` - the image filter to be applied |
204 | /// * `subset` - bounds of [`Image`] processed by filter |
205 | /// * `clip_bounds` - expected bounds of filtered [`Image`] |
206 | /// Returns filtered SkImage, or `None`: |
207 | /// * `out_subset` - storage for returned [`Image`] bounds |
208 | /// * `offset` - storage for returned [`Image`] translation Returns: filtered [`Image`], or |
209 | /// `None` |
210 | pub fn make_with_filter( |
211 | image: impl Into<Image>, |
212 | image_filter: &ImageFilter, |
213 | subset: impl AsRef<IRect>, |
214 | clip_bounds: impl AsRef<IRect>, |
215 | ) -> Option<(Image, IRect, IPoint)> { |
216 | let mut out_subset = IRect::default(); |
217 | let mut offset = IPoint::default(); |
218 | |
219 | unsafe { |
220 | Image::from_ptr(sb::C_SkImages_MakeWithFilter( |
221 | image.into().into_ptr(), |
222 | image_filter.native(), |
223 | subset.as_ref().native(), |
224 | clip_bounds.as_ref().native(), |
225 | out_subset.native_mut(), |
226 | offset.native_mut(), |
227 | )) |
228 | } |
229 | .map(|i| (i, out_subset, offset)); |
230 | None |
231 | } |
232 | } |
233 | |
234 | /// CachingHint selects whether Skia may internally cache [`Bitmap`] generated by |
235 | /// decoding [`Image`], or by copying [`Image`] from GPU to CPU. The default behavior |
236 | /// allows caching [`Bitmap`]. |
237 | /// |
238 | /// Choose [`CachingHint::Disallow`] if [`Image`] pixels are to be used only once, or |
239 | /// if [`Image`] pixels reside in a cache outside of Skia, or to reduce memory pressure. |
240 | /// |
241 | /// Choosing [`CachingHint::Allow`] does not ensure that pixels will be cached. |
242 | /// [`Image`] pixels may not be cached if memory requirements are too large or |
243 | /// pixels are not accessible. |
244 | pub use skia_bindings::SkImage_CachingHint as CachingHint; |
245 | variant_name!(CachingHint::Allow); |
246 | |
247 | /// [`Image`] describes a two dimensional array of pixels to draw. The pixels may be |
248 | /// decoded in a raster bitmap, encoded in a [`Picture`] or compressed data stream, |
249 | /// or located in GPU memory as a GPU texture. |
250 | /// |
251 | /// [`Image`] cannot be modified after it is created. [`Image`] may allocate additional |
252 | /// storage as needed; for instance, an encoded [`Image`] may decode when drawn. |
253 | /// |
254 | /// [`Image`] width and height are greater than zero. Creating an [`Image`] with zero width |
255 | /// or height returns [`Image`] equal to nullptr. |
256 | /// |
257 | /// [`Image`] may be created from [`Bitmap`], [`Pixmap`], [`crate::Surface`], [`Picture`], encoded streams, |
258 | /// GPU texture, YUV_ColorSpace data, or hardware buffer. Encoded streams supported |
259 | /// include BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP. Supported encoding details |
260 | /// vary with platform. |
261 | pub type Image = RCHandle<SkImage>; |
262 | unsafe_send_sync!(Image); |
263 | require_base_type!(SkImage, sb::SkRefCnt); |
264 | |
265 | impl NativeBase<SkRefCntBase> for SkImage {} |
266 | |
267 | impl NativeRefCountedBase for SkImage { |
268 | type Base = SkRefCntBase; |
269 | } |
270 | |
271 | impl fmt::Debug for Image { |
272 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
273 | let mut d: DebugStruct<'_, '_> = f.debug_struct(name:"Image" ); |
274 | let d: &mut DebugStruct<'_, '_> = d |
275 | .field("image_info" , &self.image_info()) |
276 | .field("unique_id" , &self.unique_id()) |
277 | .field("alpha_type" , &self.alpha_type()) |
278 | .field("color_type" , &self.color_type()) |
279 | .field("color_space" , &self.color_space()) |
280 | .field(name:"is_texture_backed" , &self.is_texture_backed()); |
281 | #[cfg (feature = "gpu" )] |
282 | let d: &mut DebugStruct<'_, '_> = d.field(name:"texture_size" , &self.texture_size()); |
283 | d&mut DebugStruct<'_, '_>.field("has_mipmaps" , &self.has_mipmaps()) |
284 | .field(name:"is_lazy_generated" , &self.is_lazy_generated()) |
285 | .finish() |
286 | } |
287 | } |
288 | |
289 | impl Image { |
290 | /// Creates [`Image`] from [`ImageInfo`], sharing pixels. |
291 | /// |
292 | /// [`Image`] is returned if [`ImageInfo`] is valid. Valid [`ImageInfo`] parameters include: |
293 | /// dimensions are greater than zero; |
294 | /// each dimension fits in 29 bits; |
295 | /// [`ColorType`] and [`AlphaType`] are valid, and [`ColorType`] is not [`ColorType::Unknown`]; |
296 | /// rowBytes are large enough to hold one row of pixels; |
297 | /// pixels is not nullptr, and contains enough data for [`Image`]. |
298 | /// |
299 | /// - `info` contains width, height, [`AlphaType`], [`ColorType`], [`ColorSpace`] |
300 | /// - `pixels` address or pixel storage |
301 | /// - `rowBytes` size of pixel row or larger |
302 | /// Returns: [`Image`] sharing pixels, or `None` |
303 | #[deprecated (since = "0.63.0" , note = "use images::raster_from_data()" )] |
304 | pub fn from_raster_data( |
305 | info: &ImageInfo, |
306 | pixels: impl Into<Data>, |
307 | row_bytes: usize, |
308 | ) -> Option<Image> { |
309 | images::raster_from_data(info, pixels, row_bytes) |
310 | } |
311 | |
312 | /// Creates [`Image`] from bitmap, sharing or copying bitmap pixels. If the bitmap |
313 | /// is marked immutable, and its pixel memory is shareable, it may be shared |
314 | /// instead of copied. |
315 | /// |
316 | /// [`Image`] is returned if bitmap is valid. Valid [`Bitmap`] parameters include: |
317 | /// dimensions are greater than zero; |
318 | /// each dimension fits in 29 bits; |
319 | /// [`ColorType`] and [`AlphaType`] are valid, and [`ColorType`] is not [`ColorType::Unknown`]; |
320 | /// row bytes are large enough to hold one row of pixels; |
321 | /// pixel address is not `null`. |
322 | /// |
323 | /// - `bitmap` [`ImageInfo`], row bytes, and pixels |
324 | /// Returns: created [`Image`], or `None` |
325 | /// |
326 | /// example: <https://fiddle.skia.org/c/@Image_MakeFromBitmap> |
327 | #[deprecated (since = "0.63.0" , note = "use images::raster_from_bitmap()" )] |
328 | pub fn from_bitmap(bitmap: &Bitmap) -> Option<Image> { |
329 | images::raster_from_bitmap(bitmap) |
330 | } |
331 | |
332 | /// Creates [`Image`] from data returned by `image_generator`. Generated data is owned by [`Image`] and |
333 | /// may not be shared or accessed. |
334 | /// |
335 | /// [`Image`] is returned if generator data is valid. Valid data parameters vary by type of data |
336 | /// and platform. |
337 | /// |
338 | /// imageGenerator may wrap [`Picture`] data, codec data, or custom data. |
339 | /// |
340 | /// - `image_generator` stock or custom routines to retrieve [`Image`] |
341 | /// Returns: created [`Image`], or `None` |
342 | #[deprecated (since = "0.63.0" , note = "use images::deferred_from_generator()" )] |
343 | pub fn from_generator(image_generator: ImageGenerator) -> Option<Image> { |
344 | images::deferred_from_generator(image_generator) |
345 | } |
346 | |
347 | /// See [`Self::from_encoded_with_alpha_type()`] |
348 | pub fn from_encoded(data: impl Into<Data>) -> Option<Image> { |
349 | images::deferred_from_encoded_data(data, None) |
350 | } |
351 | |
352 | /// Return an image backed by the encoded data, but attempt to defer decoding until the image |
353 | /// is actually used/drawn. This deferral allows the system to cache the result, either on the |
354 | /// CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may |
355 | /// be purged, causing the next draw of the image to have to re-decode. |
356 | /// |
357 | /// If alphaType is `None`, the image's alpha type will be chosen automatically based on the |
358 | /// image format. Transparent images will default to [`AlphaType::Premul`]. If alphaType contains |
359 | /// [`AlphaType::Premul`] or [`AlphaType::Unpremul`], that alpha type will be used. Forcing opaque |
360 | /// (passing [`AlphaType::Opaque`]) is not allowed, and will return nullptr. |
361 | /// |
362 | /// This is similar to `decode_to_{raster,texture}`, but this method will attempt to defer the |
363 | /// actual decode, while the `decode_to`... method explicitly decode and allocate the backend |
364 | /// when the call is made. |
365 | /// |
366 | /// If the encoded format is not supported, `None` is returned. |
367 | /// |
368 | /// - `encoded` the encoded data |
369 | /// Returns: created [`Image`], or `None` |
370 | /// |
371 | /// example: <https://fiddle.skia.org/c/@Image_MakeFromEncoded> |
372 | pub fn from_encoded_with_alpha_type( |
373 | data: impl Into<Data>, |
374 | alpha_type: impl Into<Option<AlphaType>>, |
375 | ) -> Option<Image> { |
376 | images::deferred_from_encoded_data(data, alpha_type) |
377 | } |
378 | |
379 | #[deprecated (since = "0.35.0" , note = "Removed without replacement" )] |
380 | pub fn decode_to_raster(_encoded: &[u8], _subset: impl Into<Option<IRect>>) -> ! { |
381 | panic!("Removed without replacement" ) |
382 | } |
383 | |
384 | /// Creates a CPU-backed [`Image`] from compressed data. |
385 | /// |
386 | /// This method will decompress the compressed data and create an image wrapping |
387 | /// it. Any mipmap levels present in the compressed data are discarded. |
388 | /// |
389 | /// - `data` compressed data to store in [`Image`] |
390 | /// - `width` width of full [`Image`] |
391 | /// - `height` height of full [`Image`] |
392 | /// - `ty` type of compression used |
393 | /// Returns: created [`Image`], or `None` |
394 | #[deprecated ( |
395 | since = "0.63.0" , |
396 | note = "use images::raster_from_compressed_texture_data()" |
397 | )] |
398 | pub fn new_raster_from_compressed( |
399 | data: impl Into<Data>, |
400 | dimensions: impl Into<ISize>, |
401 | ty: TextureCompressionType, |
402 | ) -> Option<Image> { |
403 | images::raster_from_compressed_texture_data(data, dimensions, ty) |
404 | } |
405 | |
406 | /// See [`Self::from_picture_with_props()`] |
407 | #[deprecated (since = "0.63.0" , note = "use images::deferred_from_picture()" )] |
408 | pub fn from_picture( |
409 | picture: impl Into<Picture>, |
410 | dimensions: impl Into<ISize>, |
411 | matrix: Option<&Matrix>, |
412 | paint: Option<&Paint>, |
413 | bit_depth: BitDepth, |
414 | color_space: impl Into<Option<ColorSpace>>, |
415 | ) -> Option<Image> { |
416 | images::deferred_from_picture( |
417 | picture, |
418 | dimensions, |
419 | matrix, |
420 | paint, |
421 | bit_depth, |
422 | color_space, |
423 | None, |
424 | ) |
425 | } |
426 | |
427 | /// Creates [`Image`] from picture. Returned [`Image`] width and height are set by dimensions. |
428 | /// [`Image`] draws picture with matrix and paint, set to bitDepth and colorSpace. |
429 | /// |
430 | /// If matrix is `None`, draws with identity [`Matrix`]. If paint is `None`, draws |
431 | /// with default [`Paint`]. color_space may be `None`. |
432 | /// |
433 | /// - `picture` stream of drawing commands |
434 | /// - `dimensions` width and height |
435 | /// - `matrix` [`Matrix`] to rotate, scale, translate, and so on; may be `None` |
436 | /// - `paint` [`Paint`] to apply transparency, filtering, and so on; may be `None` |
437 | /// - `bitDepth` 8-bit integer or 16-bit float: per component |
438 | /// - `color_space` range of colors; may be `None` |
439 | /// - `props` props to use when rasterizing the picture |
440 | /// Returns: created [`Image`], or `None` |
441 | #[deprecated (since = "0.63.0" , note = "use images::deferred_from_picture()" )] |
442 | pub fn from_picture_with_props( |
443 | picture: impl Into<Picture>, |
444 | dimensions: impl Into<ISize>, |
445 | matrix: Option<&Matrix>, |
446 | paint: Option<&Paint>, |
447 | bit_depth: BitDepth, |
448 | color_space: impl Into<Option<ColorSpace>>, |
449 | props: SurfaceProps, |
450 | ) -> Option<Image> { |
451 | images::deferred_from_picture( |
452 | picture, |
453 | dimensions, |
454 | matrix, |
455 | paint, |
456 | bit_depth, |
457 | color_space, |
458 | Some(props), |
459 | ) |
460 | } |
461 | |
462 | /// Creates a GPU-backed [`Image`] from compressed data. |
463 | /// |
464 | /// This method will return an [`Image`] representing the compressed data. |
465 | /// If the GPU doesn't support the specified compression method, the data |
466 | /// will be decompressed and then wrapped in a GPU-backed image. |
467 | /// |
468 | /// Note: one can query the supported compression formats via |
469 | /// [`gpu::RecordingContext::compressed_backend_format`]. |
470 | /// |
471 | /// - `context` GPU context |
472 | /// - `data` compressed data to store in [`Image`] |
473 | /// - `width` width of full [`Image`] |
474 | /// - `height` height of full [`Image`] |
475 | /// - `ty` type of compression used |
476 | /// - `mipmapped` does 'data' contain data for all the mipmap levels? |
477 | /// - `is_protected` do the contents of 'data' require DRM protection (on Vulkan)? |
478 | /// Returns: created [`Image`], or `None` |
479 | #[cfg (feature = "gpu" )] |
480 | #[deprecated ( |
481 | since = "0.63.0" , |
482 | note = "use gpu::images::texture_from_compressed_texture_data()" |
483 | )] |
484 | pub fn new_texture_from_compressed( |
485 | context: &mut gpu::DirectContext, |
486 | data: Data, |
487 | dimensions: impl Into<ISize>, |
488 | ty: TextureCompressionType, |
489 | mipmapped: impl Into<Option<gpu::Mipmapped>>, |
490 | is_protected: impl Into<Option<gpu::Protected>>, |
491 | ) -> Option<Image> { |
492 | gpu::images::texture_from_compressed_texture_data( |
493 | context, |
494 | data, |
495 | dimensions, |
496 | ty, |
497 | mipmapped, |
498 | is_protected, |
499 | ) |
500 | } |
501 | |
502 | #[cfg (feature = "gpu" )] |
503 | #[deprecated (since = "0.35.0" , note = "Removed without replacement" )] |
504 | pub fn from_compressed( |
505 | _context: &mut gpu::RecordingContext, |
506 | _data: Data, |
507 | _dimensions: impl Into<ISize>, |
508 | _ct: TextureCompressionType, |
509 | ) -> ! { |
510 | panic!("Removed without replacement." ) |
511 | } |
512 | |
513 | /// Creates [`Image`] from GPU texture associated with context. GPU texture must stay |
514 | /// valid and unchanged until `texture_release_proc` is called. `texture_release_proc` is |
515 | /// passed `release_context` when [`Image`] is deleted or no longer refers to texture. |
516 | /// |
517 | /// [`Image`] is returned if format of `backend_texture` is recognized and supported. |
518 | /// Recognized formats vary by GPU back-end. |
519 | /// |
520 | /// Note: When using a DDL recording context, `texture_release_proc` will be called on the |
521 | /// GPU thread after the DDL is played back on the direct context. |
522 | /// |
523 | /// * `context` GPU context |
524 | /// * `backend_texture` Texture residing on GPU |
525 | /// * `origin` Origin of `backend_texture` |
526 | /// * `color_type` Color type of the resulting image |
527 | /// * `alpha_type` Alpha type of the resulting image |
528 | /// * `color_space` This describes the color space of this image's contents, as |
529 | /// seen after sampling. In general, if the format of the backend |
530 | /// texture is SRGB, some linear `color_space` should be supplied |
531 | /// (e.g., [`ColorSpace::new_srgb_linear()`])). If the format of the |
532 | /// backend texture is linear, then the `color_space` should include |
533 | /// a description of the transfer function as |
534 | /// well (e.g., [`ColorSpace::MakeSRGB`]()). |
535 | /// * `texture_release_proc` Function called when texture can be released |
536 | /// * `release_context` State passed to `texture_release_proc` |
537 | /// Returns: Created [`Image`], or `None` |
538 | #[cfg (feature = "gpu" )] |
539 | pub fn from_texture( |
540 | context: &mut gpu::RecordingContext, |
541 | backend_texture: &gpu::BackendTexture, |
542 | origin: gpu::SurfaceOrigin, |
543 | color_type: ColorType, |
544 | alpha_type: AlphaType, |
545 | color_space: impl Into<Option<ColorSpace>>, |
546 | ) -> Option<Image> { |
547 | gpu::images::borrow_texture_from( |
548 | context, |
549 | backend_texture, |
550 | origin, |
551 | color_type, |
552 | alpha_type, |
553 | color_space, |
554 | ) |
555 | } |
556 | |
557 | #[deprecated (since = "0.27.0" , note = "renamed, use new_cross_context_from_pixmap" )] |
558 | #[cfg (feature = "gpu" )] |
559 | pub fn from_pixmap_cross_context( |
560 | context: &mut gpu::DirectContext, |
561 | pixmap: &Pixmap, |
562 | build_mips: bool, |
563 | limit_to_max_texture_size: impl Into<Option<bool>>, |
564 | ) -> Option<Image> { |
565 | gpu::images::cross_context_texture_from_pixmap( |
566 | context, |
567 | pixmap, |
568 | build_mips, |
569 | limit_to_max_texture_size, |
570 | ) |
571 | } |
572 | |
573 | /// Creates [`Image`] from pixmap. [`Image`] is uploaded to GPU back-end using context. |
574 | /// |
575 | /// Created [`Image`] is available to other GPU contexts, and is available across thread |
576 | /// boundaries. All contexts must be in the same GPU share group, or otherwise |
577 | /// share resources. |
578 | /// |
579 | /// When [`Image`] is no longer referenced, context releases texture memory |
580 | /// asynchronously. |
581 | /// |
582 | /// [`ColorSpace`] of [`Image`] is determined by `pixmap.color_space()`. |
583 | /// |
584 | /// [`Image`] is returned referring to GPU back-end if context is not `None`, |
585 | /// format of data is recognized and supported, and if context supports moving |
586 | /// resources between contexts. Otherwise, pixmap pixel data is copied and [`Image`] |
587 | /// as returned in raster format if possible; `None` may be returned. |
588 | /// Recognized GPU formats vary by platform and GPU back-end. |
589 | /// |
590 | /// - `context` GPU context |
591 | /// - `pixmap` [`ImageInfo`], pixel address, and row bytes |
592 | /// - `build_mips` create [`Image`] as mip map if `true` |
593 | /// - `limit_to_max_texture_size` downscale image to GPU maximum texture size, if necessary |
594 | /// Returns: created [`Image`], or `None` |
595 | #[cfg (feature = "gpu" )] |
596 | #[deprecated ( |
597 | since = "0.63.0" , |
598 | note = "use gpu::images::cross_context_texture_from_pixmap()" |
599 | )] |
600 | pub fn new_cross_context_from_pixmap( |
601 | context: &mut gpu::DirectContext, |
602 | pixmap: &Pixmap, |
603 | build_mips: bool, |
604 | limit_to_max_texture_size: impl Into<Option<bool>>, |
605 | ) -> Option<Image> { |
606 | gpu::images::cross_context_texture_from_pixmap( |
607 | context, |
608 | pixmap, |
609 | build_mips, |
610 | limit_to_max_texture_size, |
611 | ) |
612 | } |
613 | |
614 | /// Creates [`Image`] from `backend_texture` associated with context. `backend_texture` and |
615 | /// returned [`Image`] are managed internally, and are released when no longer needed. |
616 | /// |
617 | /// [`Image`] is returned if format of `backend_texture` is recognized and supported. |
618 | /// Recognized formats vary by GPU back-end. |
619 | /// |
620 | /// - `context` GPU context |
621 | /// - `backend_texture` texture residing on GPU |
622 | /// - `texture_origin` origin of `backend_texture` |
623 | /// - `color_type` color type of the resulting image |
624 | /// - `alpha_type` alpha type of the resulting image |
625 | /// - `color_space` range of colors; may be `None` |
626 | /// Returns: created [`Image`], or `None` |
627 | #[cfg (feature = "gpu" )] |
628 | #[deprecated (since = "0.63.0" , note = "use gpu::images::adopt_texture_from()" )] |
629 | pub fn from_adopted_texture( |
630 | context: &mut gpu::RecordingContext, |
631 | backend_texture: &gpu::BackendTexture, |
632 | texture_origin: gpu::SurfaceOrigin, |
633 | color_type: ColorType, |
634 | alpha_type: impl Into<Option<AlphaType>>, |
635 | color_space: impl Into<Option<ColorSpace>>, |
636 | ) -> Option<Image> { |
637 | gpu::images::adopt_texture_from( |
638 | context, |
639 | backend_texture, |
640 | texture_origin, |
641 | color_type, |
642 | alpha_type, |
643 | color_space, |
644 | ) |
645 | } |
646 | |
647 | /// Creates an [`Image`] from `YUV[A]` planar textures. This requires that the textures stay valid |
648 | /// for the lifetime of the image. The `ReleaseContext` can be used to know when it is safe to |
649 | /// either delete or overwrite the textures. If `ReleaseProc` is provided it is also called before |
650 | /// return on failure. |
651 | /// |
652 | /// - `context` GPU context |
653 | /// - `yuva_textures` A set of textures containing YUVA data and a description of the |
654 | /// data and transformation to RGBA. |
655 | /// - `image_color_space` range of colors of the resulting image after conversion to RGB; |
656 | /// may be `None` |
657 | /// - `texture_release_proc` called when the backend textures can be released |
658 | /// - `release_context` state passed to `texture_release_proc` |
659 | /// Returns: created [`Image`], or `None` |
660 | #[cfg (feature = "gpu" )] |
661 | #[deprecated ( |
662 | since = "0.63.0" , |
663 | note = "use gpu::images::texture_from_yuva_textures()" |
664 | )] |
665 | pub fn from_yuva_textures( |
666 | context: &mut gpu::RecordingContext, |
667 | yuva_textures: &gpu::YUVABackendTextures, |
668 | image_color_space: impl Into<Option<ColorSpace>>, |
669 | ) -> Option<Image> { |
670 | gpu::images::texture_from_yuva_textures(context, yuva_textures, image_color_space) |
671 | } |
672 | |
673 | /// Creates [`Image`] from [`crate::YUVAPixmaps`]. |
674 | /// |
675 | /// The image will remain planar with each plane converted to a texture using the passed |
676 | /// [`gpu::RecordingContext`]. |
677 | /// |
678 | /// [`crate::YUVAPixmaps`] has a [`crate::YUVAInfo`] which specifies the transformation from YUV to RGB. |
679 | /// The [`ColorSpace`] of the resulting RGB values is specified by `image_color_space`. This will |
680 | /// be the [`ColorSpace`] reported by the image and when drawn the RGB values will be converted |
681 | /// from this space into the destination space (if the destination is tagged). |
682 | /// |
683 | /// Currently, this is only supported using the GPU backend and will fail if context is `None`. |
684 | /// |
685 | /// [`crate::YUVAPixmaps`] does not need to remain valid after this returns. |
686 | /// |
687 | /// - `context` GPU context |
688 | /// - `pixmaps` The planes as pixmaps with supported [`crate::YUVAInfo`] that |
689 | /// specifies conversion to RGB. |
690 | /// - `build_mips` create internal YUVA textures as mip map if `Yes`. This is |
691 | /// silently ignored if the context does not support mip maps. |
692 | /// - `limit_to_max_texture_size` downscale image to GPU maximum texture size, if necessary |
693 | /// - `image_color_space` range of colors of the resulting image; may be `None` |
694 | /// Returns: created [`Image`], or `None` |
695 | #[cfg (feature = "gpu" )] |
696 | #[deprecated ( |
697 | since = "0.63.0" , |
698 | note = "use gpu::images::texture_from_yuva_pixmaps()" |
699 | )] |
700 | pub fn from_yuva_pixmaps( |
701 | context: &mut gpu::RecordingContext, |
702 | yuva_pixmaps: &crate::YUVAPixmaps, |
703 | build_mips: impl Into<Option<gpu::Mipmapped>>, |
704 | limit_to_max_texture_size: impl Into<Option<bool>>, |
705 | image_color_space: impl Into<Option<ColorSpace>>, |
706 | ) -> Option<Image> { |
707 | gpu::images::texture_from_yuva_pixmaps( |
708 | context, |
709 | yuva_pixmaps, |
710 | build_mips, |
711 | limit_to_max_texture_size, |
712 | image_color_space, |
713 | ) |
714 | } |
715 | |
716 | #[cfg (feature = "gpu" )] |
717 | #[deprecated (since = "0.37.0" , note = "Removed without replacement" )] |
718 | pub fn from_nv12_textures_copy( |
719 | _context: &mut gpu::DirectContext, |
720 | _yuv_color_space: crate::YUVColorSpace, |
721 | _nv12_textures: &[gpu::BackendTexture; 2], |
722 | _image_origin: gpu::SurfaceOrigin, |
723 | _image_color_space: impl Into<Option<ColorSpace>>, |
724 | ) -> ! { |
725 | panic!("Removed without replacement" ) |
726 | } |
727 | |
728 | /// Returns a [`ImageInfo`] describing the width, height, color type, alpha type, and color space |
729 | /// of the [`Image`]. |
730 | /// |
731 | /// Returns: image info of [`Image`]. |
732 | pub fn image_info(&self) -> &ImageInfo { |
733 | ImageInfo::from_native_ref(&self.native().fInfo) |
734 | } |
735 | |
736 | /// Returns pixel count in each row. |
737 | /// |
738 | /// Returns: pixel width in [`Image`] |
739 | pub fn width(&self) -> i32 { |
740 | self.image_info().width() |
741 | } |
742 | |
743 | /// Returns pixel row count. |
744 | /// |
745 | /// Returns: pixel height in [`Image`] |
746 | pub fn height(&self) -> i32 { |
747 | self.image_info().height() |
748 | } |
749 | |
750 | /// Returns [`ISize`] `{ width(), height() }`. |
751 | /// |
752 | /// Returns: integral size of `width()` and `height()` |
753 | pub fn dimensions(&self) -> ISize { |
754 | self.image_info().dimensions() |
755 | } |
756 | |
757 | /// Returns [`IRect`] `{ 0, 0, width(), height() }`. |
758 | /// |
759 | /// Returns: integral rectangle from origin to `width()` and `height()` |
760 | pub fn bounds(&self) -> IRect { |
761 | self.image_info().bounds() |
762 | } |
763 | |
764 | /// Returns value unique to image. [`Image`] contents cannot change after [`Image`] is |
765 | /// created. Any operation to create a new [`Image`] will receive generate a new |
766 | /// unique number. |
767 | /// |
768 | /// Returns: unique identifier |
769 | pub fn unique_id(&self) -> u32 { |
770 | self.native().fUniqueID |
771 | } |
772 | |
773 | /// Returns [`AlphaType`]. |
774 | /// |
775 | /// [`AlphaType`] returned was a parameter to an [`Image`] constructor, |
776 | /// or was parsed from encoded data. |
777 | /// |
778 | /// Returns: [`AlphaType`] in [`Image`] |
779 | /// |
780 | /// example: <https://fiddle.skia.org/c/@Image_alphaType> |
781 | pub fn alpha_type(&self) -> AlphaType { |
782 | unsafe { self.native().alphaType() } |
783 | } |
784 | |
785 | /// Returns [`ColorType`] if known; otherwise, returns [`ColorType::Unknown`]. |
786 | /// |
787 | /// Returns: [`ColorType`] of [`Image`] |
788 | /// |
789 | /// example: <https://fiddle.skia.org/c/@Image_colorType> |
790 | pub fn color_type(&self) -> ColorType { |
791 | ColorType::from_native_c(unsafe { self.native().colorType() }) |
792 | } |
793 | |
794 | /// Returns a smart pointer to [`ColorSpace`], the range of colors, associated with |
795 | /// [`Image`]. The smart pointer tracks the number of objects sharing this |
796 | /// [`ColorSpace`] reference so the memory is released when the owners destruct. |
797 | /// |
798 | /// The returned [`ColorSpace`] is immutable. |
799 | /// |
800 | /// [`ColorSpace`] returned was passed to an [`Image`] constructor, |
801 | /// or was parsed from encoded data. [`ColorSpace`] returned may be ignored when [`Image`] |
802 | /// is drawn, depending on the capabilities of the [`crate::Surface`] receiving the drawing. |
803 | /// |
804 | /// Returns: [`ColorSpace`] in [`Image`], or `None`, wrapped in a smart pointer |
805 | /// |
806 | /// example: <https://fiddle.skia.org/c/@Image_refColorSpace> |
807 | pub fn color_space(&self) -> ColorSpace { |
808 | ColorSpace::from_unshared_ptr(unsafe { self.native().colorSpace() }).unwrap() |
809 | } |
810 | |
811 | /// Returns `true` if [`Image`] pixels represent transparency only. If `true`, each pixel |
812 | /// is packed in 8 bits as defined by [`ColorType::Alpha8`]. |
813 | /// |
814 | /// Returns: `true` if pixels represent a transparency mask |
815 | /// |
816 | /// example: <https://fiddle.skia.org/c/@Image_isAlphaOnly> |
817 | pub fn is_alpha_only(&self) -> bool { |
818 | unsafe { self.native().isAlphaOnly() } |
819 | } |
820 | |
821 | /// Returns `true` if pixels ignore their alpha value and are treated as fully opaque. |
822 | /// |
823 | /// Returns: `true` if [`AlphaType`] is [`AlphaType::Opaque`] |
824 | pub fn is_opaque(&self) -> bool { |
825 | self.alpha_type().is_opaque() |
826 | } |
827 | |
828 | /// Make a shader with the specified tiling and mipmap sampling. |
829 | pub fn to_shader<'a>( |
830 | &self, |
831 | tile_modes: impl Into<Option<(TileMode, TileMode)>>, |
832 | sampling: impl Into<SamplingOptions>, |
833 | local_matrix: impl Into<Option<&'a Matrix>>, |
834 | ) -> Option<Shader> { |
835 | let tile_modes = tile_modes.into(); |
836 | let tm1 = tile_modes.map(|(tm, _)| tm).unwrap_or_default(); |
837 | let tm2 = tile_modes.map(|(_, tm)| tm).unwrap_or_default(); |
838 | let sampling = sampling.into(); |
839 | |
840 | Shader::from_ptr(unsafe { |
841 | sb::C_SkImage_makeShader( |
842 | self.native(), |
843 | tm1, |
844 | tm2, |
845 | sampling.native(), |
846 | local_matrix.into().native_ptr_or_null(), |
847 | ) |
848 | }) |
849 | } |
850 | |
851 | /// `to_raw_shader` functions like `to_shader`, but for images that contain non-color data. |
852 | /// This includes images encoding things like normals, material properties (eg, roughness), |
853 | /// heightmaps, or any other purely mathematical data that happens to be stored in an image. |
854 | /// These types of images are useful with some programmable shaders (see: [`crate::RuntimeEffect`]). |
855 | /// |
856 | /// Raw image shaders work like regular image shaders (including filtering and tiling), with |
857 | /// a few major differences: |
858 | /// - No color space transformation is ever applied (the color space of the image is ignored). |
859 | /// - Images with an alpha type of `Unpremul` are *not* automatically premultiplied. |
860 | /// - Bicubic filtering is not supported. If [`SamplingOptions::use_cubic`] is `true`, these |
861 | /// factories will return `None`. |
862 | pub fn to_raw_shader<'a>( |
863 | &self, |
864 | tile_modes: impl Into<Option<(TileMode, TileMode)>>, |
865 | sampling: impl Into<SamplingOptions>, |
866 | local_matrix: impl Into<Option<&'a Matrix>>, |
867 | ) -> Option<Shader> { |
868 | let tile_modes = tile_modes.into(); |
869 | let tm1 = tile_modes.map(|(tm, _)| tm).unwrap_or_default(); |
870 | let tm2 = tile_modes.map(|(_, tm)| tm).unwrap_or_default(); |
871 | let sampling = sampling.into(); |
872 | |
873 | Shader::from_ptr(unsafe { |
874 | sb::C_SkImage_makeRawShader( |
875 | self.native(), |
876 | tm1, |
877 | tm2, |
878 | sampling.native(), |
879 | local_matrix.into().native_ptr_or_null(), |
880 | ) |
881 | }) |
882 | } |
883 | |
884 | /// Copies [`Image`] pixel address, row bytes, and [`ImageInfo`] to pixmap, if address |
885 | /// is available, and returns `true`. If pixel address is not available, return |
886 | /// `false` and leave pixmap unchanged. |
887 | /// |
888 | /// - `pixmap` storage for pixel state if pixels are readable; otherwise, ignored |
889 | /// Returns: `true` if [`Image`] has direct access to pixels |
890 | /// |
891 | /// example: <https://fiddle.skia.org/c/@Image_peekPixels> |
892 | pub fn peek_pixels(&self) -> Option<Pixmap> { |
893 | let mut pixmap = Pixmap::default(); |
894 | unsafe { self.native().peekPixels(pixmap.native_mut()) }.if_true_some(pixmap) |
895 | } |
896 | |
897 | /// Returns `true` if the contents of [`Image`] was created on or uploaded to GPU memory, |
898 | /// and is available as a GPU texture. |
899 | /// |
900 | /// Returns: `true` if [`Image`] is a GPU texture |
901 | /// |
902 | /// example: <https://fiddle.skia.org/c/@Image_isTextureBacked> |
903 | pub fn is_texture_backed(&self) -> bool { |
904 | unsafe { sb::C_SkImage_isTextureBacked(self.native()) } |
905 | } |
906 | |
907 | /// Returns an approximation of the amount of texture memory used by the image. Returns |
908 | /// zero if the image is not texture backed or if the texture has an external format. |
909 | pub fn texture_size(&self) -> usize { |
910 | unsafe { sb::C_SkImage_textureSize(self.native()) } |
911 | } |
912 | |
913 | /// Returns `true` if [`Image`] can be drawn on either raster surface or GPU surface. |
914 | /// If context is `None`, tests if [`Image`] draws on raster surface; |
915 | /// otherwise, tests if [`Image`] draws on GPU surface associated with context. |
916 | /// |
917 | /// [`Image`] backed by GPU texture may become invalid if associated context is |
918 | /// invalid. lazy image may be invalid and may not draw to raster surface or |
919 | /// GPU surface or both. |
920 | /// |
921 | /// - `context` GPU context |
922 | /// Returns: `true` if [`Image`] can be drawn |
923 | /// |
924 | /// example: <https://fiddle.skia.org/c/@Image_isValid> |
925 | #[cfg (feature = "gpu" )] |
926 | pub fn is_valid(&self, context: &mut gpu::RecordingContext) -> bool { |
927 | unsafe { sb::C_SkImage_isValid(self.native(), context.native_mut()) } |
928 | } |
929 | |
930 | /// See [`Self::flush_with_info()`] |
931 | #[cfg (feature = "gpu" )] |
932 | #[deprecated (since = "0.63.0" , note = "use gpu::DirectContext::flush()" )] |
933 | pub fn flush<'a>( |
934 | &self, |
935 | context: &mut gpu::DirectContext, |
936 | flush_info: impl Into<Option<&'a gpu::FlushInfo>>, |
937 | ) -> gpu::SemaphoresSubmitted { |
938 | context.flush(flush_info) |
939 | } |
940 | |
941 | /// Flushes any pending uses of texture-backed images in the GPU backend. If the image is not |
942 | /// texture-backed (including promise texture images) or if the [`gpu::DirectContext`] does not |
943 | /// have the same context ID as the context backing the image then this is a no-op. |
944 | /// |
945 | /// If the image was not used in any non-culled draws in the current queue of work for the |
946 | /// passed [`gpu::DirectContext`] then this is a no-op unless the [`gpu::FlushInfo`] contains semaphores or |
947 | /// a finish proc. Those are respected even when the image has not been used. |
948 | /// |
949 | /// - `context` the context on which to flush pending usages of the image. |
950 | /// - `info` flush options |
951 | #[cfg (feature = "gpu" )] |
952 | #[deprecated (since = "0.46.0" , note = "use gpu::DirectContext::flush()" )] |
953 | pub fn flush_with_info( |
954 | &self, |
955 | context: &mut gpu::DirectContext, |
956 | flush_info: &gpu::FlushInfo, |
957 | ) -> gpu::SemaphoresSubmitted { |
958 | context.flush(flush_info) |
959 | } |
960 | |
961 | /// Version of `flush()` that uses a default [`gpu::FlushInfo`]. Also submits the flushed work to the |
962 | /// GPU. |
963 | #[cfg (feature = "gpu" )] |
964 | #[deprecated (since = "0.63.0" , note = "use gpu::DirectContext::flush_and_submit()" )] |
965 | pub fn flush_and_submit(&self, context: &mut gpu::DirectContext) { |
966 | context.flush_and_submit(); |
967 | } |
968 | |
969 | /// Retrieves the back-end texture. If [`Image`] has no back-end texture, `None`is returned. |
970 | /// |
971 | /// If `flush_pending_gr_context_io` is `true`, completes deferred I/O operations. |
972 | /// |
973 | /// If origin in not `None`, copies location of content drawn into [`Image`]. |
974 | /// |
975 | /// - `flush_pending_gr_context_io` flag to flush outstanding requests |
976 | /// Returns: back-end API texture handle; invalid on failure |
977 | #[cfg (feature = "gpu" )] |
978 | #[deprecated ( |
979 | since = "0.63.0" , |
980 | note = "use gpu::images::get_backend_texture_from_image()" |
981 | )] |
982 | pub fn backend_texture( |
983 | &self, |
984 | flush_pending_gr_context_io: bool, |
985 | ) -> Option<(gpu::BackendTexture, gpu::SurfaceOrigin)> { |
986 | gpu::images::get_backend_texture_from_image(self, flush_pending_gr_context_io) |
987 | } |
988 | |
989 | /// Copies [`crate::Rect`] of pixels from [`Image`] to `dst_pixels`. Copy starts at offset (`src_x`, `src_y`), |
990 | /// and does not exceed [`Image`] (width(), height()). |
991 | /// |
992 | /// `dst_info` specifies width, height, [`ColorType`], [`AlphaType`], and [`ColorSpace`] of |
993 | /// destination. `dst_row_bytes` specifies the gap from one destination row to the next. |
994 | /// Returns `true` if pixels are copied. Returns `false` if: |
995 | /// - `dst_info`.`addr()` equals `None` |
996 | /// - `dst_row_bytes` is less than `dst_info.min_row_bytes()` |
997 | /// - [`crate::PixelRef`] is `None` |
998 | /// |
999 | /// Pixels are copied only if pixel conversion is possible. If [`Image`] [`ColorType`] is |
1000 | /// [`ColorType::Gray8`], or [`ColorType::Alpha8`]; `dst_info.color_type()` must match. |
1001 | /// If [`Image`] [`ColorType`] is [`ColorType::Gray8`], `dst_info`.`color_space()` must match. |
1002 | /// If [`Image`] [`AlphaType`] is [`AlphaType::Opaque`], `dst_info`.`alpha_type()` must |
1003 | /// match. If [`Image`] [`ColorSpace`] is `None`, `dst_info.color_space()` must match. Returns |
1004 | /// `false` if pixel conversion is not possible. |
1005 | /// |
1006 | /// `src_x` and `src_y` may be negative to copy only top or left of source. Returns |
1007 | /// `false` if `width()` or `height()` is zero or negative. |
1008 | /// Returns `false` if abs(`src_x`) >= Image width(), or if abs(`src_y`) >= Image height(). |
1009 | /// |
1010 | /// If `caching_hint` is [`CachingHint::Allow`], pixels may be retained locally. |
1011 | /// If `caching_hint` is [`CachingHint::Disallow`], pixels are not added to the local cache. |
1012 | /// |
1013 | /// - `context` the [`gpu::DirectContext`] in play, if it exists |
1014 | /// - `dst_info` destination width, height, [`ColorType`], [`AlphaType`], [`ColorSpace`] |
1015 | /// - `dst_pixels` destination pixel storage |
1016 | /// - `dst_row_bytes` destination row length |
1017 | /// - `src_x` column index whose absolute value is less than `width()` |
1018 | /// - `src_y` row index whose absolute value is less than `height()` |
1019 | /// - `caching_hint` whether the pixels should be cached locally |
1020 | /// Returns: `true` if pixels are copied to `dst_pixels` |
1021 | #[cfg (feature = "gpu" )] |
1022 | pub fn read_pixels_with_context<'a, P>( |
1023 | &self, |
1024 | context: impl Into<Option<&'a mut gpu::DirectContext>>, |
1025 | dst_info: &ImageInfo, |
1026 | pixels: &mut [P], |
1027 | dst_row_bytes: usize, |
1028 | src: impl Into<IPoint>, |
1029 | caching_hint: CachingHint, |
1030 | ) -> bool { |
1031 | if !dst_info.valid_pixels(dst_row_bytes, pixels) { |
1032 | return false; |
1033 | } |
1034 | |
1035 | let src = src.into(); |
1036 | |
1037 | unsafe { |
1038 | self.native().readPixels( |
1039 | context.into().native_ptr_or_null_mut(), |
1040 | dst_info.native(), |
1041 | pixels.as_mut_ptr() as _, |
1042 | dst_row_bytes, |
1043 | src.x, |
1044 | src.y, |
1045 | caching_hint, |
1046 | ) |
1047 | } |
1048 | } |
1049 | |
1050 | /// Copies a [`crate::Rect`] of pixels from [`Image`] to dst. Copy starts at (`src_x`, `src_y`), and |
1051 | /// does not exceed [`Image`] (width(), height()). |
1052 | /// |
1053 | /// dst specifies width, height, [`ColorType`], [`AlphaType`], [`ColorSpace`], pixel storage, |
1054 | /// and row bytes of destination. dst.`row_bytes()` specifics the gap from one destination |
1055 | /// row to the next. Returns `true` if pixels are copied. Returns `false` if: |
1056 | /// - dst pixel storage equals `None` |
1057 | /// - dst.`row_bytes` is less than [`ImageInfo::min_row_bytes`] |
1058 | /// - [`crate::PixelRef`] is `None` |
1059 | /// |
1060 | /// Pixels are copied only if pixel conversion is possible. If [`Image`] [`ColorType`] is |
1061 | /// [`ColorType::Gray8`], or [`ColorType::Alpha8`]; dst.`color_type()` must match. |
1062 | /// If [`Image`] [`ColorType`] is [`ColorType::Gray8`], dst.`color_space()` must match. |
1063 | /// If [`Image`] [`AlphaType`] is [`AlphaType::Opaque`], dst.`alpha_type()` must |
1064 | /// match. If [`Image`] [`ColorSpace`] is `None`, dst.`color_space()` must match. Returns |
1065 | /// `false` if pixel conversion is not possible. |
1066 | /// |
1067 | /// `src_x` and `src_y` may be negative to copy only top or left of source. Returns |
1068 | /// `false` if `width()` or `height()` is zero or negative. |
1069 | /// Returns `false` if abs(`src_x`) >= Image width(), or if abs(`src_y`) >= Image height(). |
1070 | /// |
1071 | /// If `caching_hint` is [`CachingHint::Allow`], pixels may be retained locally. |
1072 | /// If `caching_hint` is [`CachingHint::Disallow`], pixels are not added to the local cache. |
1073 | /// |
1074 | /// - `context` the [`gpu::DirectContext`] in play, if it exists |
1075 | /// - `dst` destination [`Pixmap`]:[`ImageInfo`], pixels, row bytes |
1076 | /// - `src_x` column index whose absolute value is less than `width()` |
1077 | /// - `src_y` row index whose absolute value is less than `height()` |
1078 | /// - `caching_hint` whether the pixels should be cached `locally_z` |
1079 | /// Returns: `true` if pixels are copied to dst |
1080 | #[cfg (feature = "gpu" )] |
1081 | pub fn read_pixels_to_pixmap_with_context<'a>( |
1082 | &self, |
1083 | context: impl Into<Option<&'a mut gpu::DirectContext>>, |
1084 | dst: &Pixmap, |
1085 | src: impl Into<IPoint>, |
1086 | caching_hint: CachingHint, |
1087 | ) -> bool { |
1088 | let src = src.into(); |
1089 | |
1090 | unsafe { |
1091 | self.native().readPixels1( |
1092 | context.into().native_ptr_or_null_mut(), |
1093 | dst.native(), |
1094 | src.x, |
1095 | src.y, |
1096 | caching_hint, |
1097 | ) |
1098 | } |
1099 | } |
1100 | |
1101 | // _not_ deprecated, because we support separate functions in `gpu` feature builds. |
1102 | /// See [`Self::read_pixels_with_context()`] |
1103 | pub fn read_pixels<P>( |
1104 | &self, |
1105 | dst_info: &ImageInfo, |
1106 | pixels: &mut [P], |
1107 | dst_row_bytes: usize, |
1108 | src: impl Into<IPoint>, |
1109 | caching_hint: CachingHint, |
1110 | ) -> bool { |
1111 | if !dst_info.valid_pixels(dst_row_bytes, pixels) { |
1112 | return false; |
1113 | } |
1114 | |
1115 | let src = src.into(); |
1116 | |
1117 | unsafe { |
1118 | self.native().readPixels( |
1119 | ptr::null_mut(), |
1120 | dst_info.native(), |
1121 | pixels.as_mut_ptr() as _, |
1122 | dst_row_bytes, |
1123 | src.x, |
1124 | src.y, |
1125 | caching_hint, |
1126 | ) |
1127 | } |
1128 | } |
1129 | |
1130 | /// See [`Self::read_pixels_to_pixmap_with_context()`] |
1131 | #[cfg (feature = "gpu" )] |
1132 | #[allow (clippy::missing_safety_doc)] |
1133 | pub unsafe fn read_pixels_to_pixmap( |
1134 | &self, |
1135 | dst: &Pixmap, |
1136 | src: impl Into<IPoint>, |
1137 | caching_hint: CachingHint, |
1138 | ) -> bool { |
1139 | let src = src.into(); |
1140 | |
1141 | self.native() |
1142 | .readPixels1(ptr::null_mut(), dst.native(), src.x, src.y, caching_hint) |
1143 | } |
1144 | |
1145 | // TODO: |
1146 | // AsyncReadResult, |
1147 | // ReadPixelsContext, |
1148 | // ReadPixelsCallback, |
1149 | // RescaleGamma, |
1150 | // RescaleMode, |
1151 | // asyncRescaleAndReadPixels, |
1152 | // asyncRescaleAndReadPixelsYUV420, |
1153 | // asyncRescaleAndReadPixelsYUVA420 |
1154 | |
1155 | /// Copies [`Image`] to dst, scaling pixels to fit `dst.width()` and `dst.height()`, and |
1156 | /// converting pixels to match `dst.color_type()` and `dst.alpha_type()`. Returns `true` if |
1157 | /// pixels are copied. Returns `false` if `dst.addr()` is `None`, or `dst.row_bytes()` is |
1158 | /// less than dst [`ImageInfo::min_row_bytes`]. |
1159 | /// |
1160 | /// Pixels are copied only if pixel conversion is possible. If [`Image`] [`ColorType`] is |
1161 | /// [`ColorType::Gray8`], or [`ColorType::Alpha8`]; `dst.color_type()` must match. |
1162 | /// If [`Image`] [`ColorType`] is [`ColorType::Gray8`], `dst.color_space()` must match. |
1163 | /// If [`Image`] [`AlphaType`] is [`AlphaType::Opaque`], `dst.alpha_type()` must |
1164 | /// match. If [`Image`] [`ColorSpace`] is `None`, `dst.color_space()` must match. Returns |
1165 | /// `false` if pixel conversion is not possible. |
1166 | /// |
1167 | /// If `caching_hint` is [`CachingHint::Allow`], pixels may be retained locally. |
1168 | /// If `caching_hint` is [`CachingHint::Disallow`], pixels are not added to the local cache. |
1169 | /// |
1170 | /// - `dst` destination [`Pixmap`]:[`ImageInfo`], pixels, row bytes |
1171 | /// Returns: `true` if pixels are scaled to fit dst |
1172 | #[must_use ] |
1173 | pub fn scale_pixels( |
1174 | &self, |
1175 | dst: &Pixmap, |
1176 | sampling: impl Into<SamplingOptions>, |
1177 | caching_hint: impl Into<Option<CachingHint>>, |
1178 | ) -> bool { |
1179 | unsafe { |
1180 | self.native().scalePixels( |
1181 | dst.native(), |
1182 | sampling.into().native(), |
1183 | caching_hint.into().unwrap_or(CachingHint::Allow), |
1184 | ) |
1185 | } |
1186 | } |
1187 | |
1188 | /// Encodes [`Image`] pixels, returning result as [`Data`]. |
1189 | /// |
1190 | /// Returns `None` if encoding fails, or if `encoded_image_format` is not supported. |
1191 | /// |
1192 | /// [`Image`] encoding in a format requires both building with one or more of: |
1193 | /// SK_ENCODE_JPEG, SK_ENCODE_PNG, SK_ENCODE_WEBP; and platform support |
1194 | /// for the encoded format. |
1195 | /// |
1196 | /// If SK_BUILD_FOR_MAC or SK_BUILD_FOR_IOS is defined, `encoded_image_format` can |
1197 | /// additionally be one of: [`EncodedImageFormat::ICO`], [`EncodedImageFormat::BMP`], |
1198 | /// [`EncodedImageFormat::GIF`]. |
1199 | /// |
1200 | /// quality is a platform and format specific metric trading off size and encoding |
1201 | /// error. When used, quality equaling 100 encodes with the least error. quality may |
1202 | /// be ignored by the encoder. |
1203 | /// |
1204 | /// * `context` - the [`gpu::DirectContext`] in play, if it exists; can be `None` |
1205 | /// * `encoded_image_format` - one of: [`EncodedImageFormat::JPEG`], [`EncodedImageFormat::PNG`], |
1206 | /// [`EncodedImageFormat::WEBP`] |
1207 | /// * `quality` - encoder specific metric with 100 equaling best |
1208 | /// Returns: encoded [`Image`], or `None` |
1209 | /// |
1210 | /// example: <https://fiddle.skia.org/c/@Image_encodeToData> |
1211 | #[cfg (feature = "gpu" )] |
1212 | #[deprecated (since = "0.63.0" , note = "Use encode" )] |
1213 | pub fn encode_to_data_with_context( |
1214 | &self, |
1215 | context: impl Into<Option<gpu::DirectContext>>, |
1216 | image_format: EncodedImageFormat, |
1217 | quality: impl Into<Option<u32>>, |
1218 | ) -> Option<Data> { |
1219 | let mut context = context.into(); |
1220 | self.encode(context.as_mut(), image_format, quality) |
1221 | } |
1222 | |
1223 | /// See [`Self::encode_to_data_with_quality`] |
1224 | #[deprecated ( |
1225 | since = "0.63.0" , |
1226 | note = "Support for encoding GPU backed images without a context was removed, use `encode_to_data_with_context` instead" |
1227 | )] |
1228 | pub fn encode_to_data(&self, image_format: EncodedImageFormat) -> Option<Data> { |
1229 | self.encode(None, image_format, 100) |
1230 | } |
1231 | |
1232 | /// Encodes [`Image`] pixels, returning result as [`Data`]. |
1233 | /// |
1234 | /// Returns `None` if encoding fails, or if `encoded_image_format` is not supported. |
1235 | /// |
1236 | /// [`Image`] encoding in a format requires both building with one or more of: |
1237 | /// SK_ENCODE_JPEG, SK_ENCODE_PNG, SK_ENCODE_WEBP; and platform support |
1238 | /// for the encoded format. |
1239 | /// |
1240 | /// If SK_BUILD_FOR_MAC or SK_BUILD_FOR_IOS is defined, `encoded_image_format` can |
1241 | /// additionally be one of: [`EncodedImageFormat::ICO`], [`EncodedImageFormat::BMP`], |
1242 | /// [`EncodedImageFormat::GIF`]. |
1243 | /// |
1244 | /// quality is a platform and format specific metric trading off size and encoding |
1245 | /// error. When used, quality equaling 100 encodes with the least error. quality may |
1246 | /// be ignored by the encoder. |
1247 | /// |
1248 | /// - `encoded_image_format` one of: [`EncodedImageFormat::JPEG`], [`EncodedImageFormat::PNG`], |
1249 | /// [`EncodedImageFormat::WEBP`] |
1250 | /// - `quality` encoder specific metric with 100 equaling best |
1251 | /// Returns: encoded [`Image`], or `None` |
1252 | /// |
1253 | /// example: <https://fiddle.skia.org/c/@Image_encodeToData> |
1254 | #[deprecated ( |
1255 | since = "0.63.0" , |
1256 | note = "Support for encoding GPU backed images without a context was removed, use `encode_to_data_with_context` instead" |
1257 | )] |
1258 | pub fn encode_to_data_with_quality( |
1259 | &self, |
1260 | image_format: EncodedImageFormat, |
1261 | quality: u32, |
1262 | ) -> Option<Data> { |
1263 | self.encode(None, image_format, quality) |
1264 | } |
1265 | |
1266 | /// Returns encoded [`Image`] pixels as [`Data`], if [`Image`] was created from supported |
1267 | /// encoded stream format. Platform support for formats vary and may require building |
1268 | /// with one or more of: SK_ENCODE_JPEG, SK_ENCODE_PNG, SK_ENCODE_WEBP. |
1269 | /// |
1270 | /// Returns `None` if [`Image`] contents are not encoded. |
1271 | /// |
1272 | /// Returns: encoded [`Image`], or `None` |
1273 | /// |
1274 | /// example: <https://fiddle.skia.org/c/@Image_refEncodedData> |
1275 | pub fn encoded_data(&self) -> Option<Data> { |
1276 | Data::from_ptr(unsafe { sb::C_SkImage_refEncodedData(self.native()) }) |
1277 | } |
1278 | |
1279 | /// See [`Self::new_subset_with_context`] |
1280 | #[deprecated (since = "0.64.0" , note = "use make_subset()" )] |
1281 | pub fn new_subset(&self, rect: impl AsRef<IRect>) -> Option<Image> { |
1282 | self.make_subset(None, rect) |
1283 | } |
1284 | |
1285 | /// Returns subset of this image. |
1286 | /// |
1287 | /// Returns `None` if any of the following are true: |
1288 | /// - Subset is empty |
1289 | /// - Subset is not contained inside the image's bounds |
1290 | /// - Pixels in the image could not be read or copied |
1291 | /// |
1292 | /// If this image is texture-backed, the context parameter is required and must match the |
1293 | /// context of the source image. If the context parameter is provided, and the image is |
1294 | /// raster-backed, the subset will be converted to texture-backed. |
1295 | /// |
1296 | /// - `subset` bounds of returned [`Image`] |
1297 | /// - `context` the [`gpu::DirectContext`] in play, if it exists |
1298 | /// Returns: the subsetted image, or `None` |
1299 | /// |
1300 | /// example: <https://fiddle.skia.org/c/@Image_makeSubset> |
1301 | |
1302 | #[cfg (feature = "gpu" )] |
1303 | #[deprecated (since = "0.64.0" , note = "use make_subset()" )] |
1304 | pub fn new_subset_with_context<'a>( |
1305 | &self, |
1306 | rect: impl AsRef<IRect>, |
1307 | direct: impl Into<Option<&'a mut gpu::DirectContext>>, |
1308 | ) -> Option<Image> { |
1309 | self.make_subset(direct, rect) |
1310 | } |
1311 | |
1312 | /// Returns subset of this image. |
1313 | /// |
1314 | /// Returns `None` if any of the following are true: |
1315 | /// - Subset is empty - Subset is not contained inside the image's bounds |
1316 | /// - Pixels in the source image could not be read or copied |
1317 | /// - This image is texture-backed and the provided context is null or does not match the |
1318 | /// source image's context. |
1319 | /// |
1320 | /// If the source image was texture-backed, the resulting image will be texture-backed also. |
1321 | /// Otherwise, the returned image will be raster-backed. |
1322 | /// |
1323 | /// * `direct` - the [`gpu::DirectContext`] of the source image (`None` is ok if the source |
1324 | /// image is not texture-backed). |
1325 | /// * `subset` - bounds of returned [`Image`] Returns: the subsetted image, or `None` |
1326 | /// |
1327 | /// example: <https://fiddle.skia.org/c/@Image_makeSubset> |
1328 | pub fn make_subset<'a>( |
1329 | &self, |
1330 | direct: impl Into<Option<&'a mut gpu::DirectContext>>, |
1331 | subset: impl AsRef<IRect>, |
1332 | ) -> Option<Image> { |
1333 | Image::from_ptr(unsafe { |
1334 | sb::C_SkImage_makeSubset( |
1335 | self.native(), |
1336 | direct.into().native_ptr_or_null_mut(), |
1337 | subset.as_ref().native(), |
1338 | ) |
1339 | }) |
1340 | } |
1341 | |
1342 | /// Returns `true` if the image has mipmap levels. |
1343 | pub fn has_mipmaps(&self) -> bool { |
1344 | unsafe { self.native().hasMipmaps() } |
1345 | } |
1346 | |
1347 | /// Returns an image with the same "base" pixels as the this image, but with mipmap levels |
1348 | /// automatically generated and attached. |
1349 | pub fn with_default_mipmaps(&self) -> Option<Image> { |
1350 | Image::from_ptr(unsafe { sb::C_SkImage_withDefaultMipmaps(self.native()) }) |
1351 | } |
1352 | |
1353 | /// See [`Self::new_texture_image_budgeted`] |
1354 | #[cfg (feature = "gpu" )] |
1355 | pub fn new_texture_image( |
1356 | &self, |
1357 | context: &mut gpu::DirectContext, |
1358 | mipmapped: gpu::Mipmapped, |
1359 | ) -> Option<Image> { |
1360 | self.new_texture_image_budgeted(context, mipmapped, gpu::Budgeted::Yes) |
1361 | } |
1362 | |
1363 | /// Returns [`Image`] backed by GPU texture associated with context. Returned [`Image`] is |
1364 | /// compatible with [`crate::Surface`] created with `dst_color_space`. The returned [`Image`] respects |
1365 | /// mipmapped setting; if mipmapped equals [`gpu::Mipmapped::Yes`], the backing texture |
1366 | /// allocates mip map levels. |
1367 | /// |
1368 | /// The mipmapped parameter is effectively treated as `No` if MIP maps are not supported by the |
1369 | /// GPU. |
1370 | /// |
1371 | /// Returns original [`Image`] if the image is already texture-backed, the context matches, and |
1372 | /// mipmapped is compatible with the backing GPU texture. [`crate::Budgeted`] is ignored in this case. |
1373 | /// |
1374 | /// Returns `None` if context is `None`, or if [`Image`] was created with another |
1375 | /// [`gpu::DirectContext`]. |
1376 | /// |
1377 | /// - `direct_context` the [`gpu::DirectContext`] in play, if it exists |
1378 | /// - `mipmapped` whether created [`Image`] texture must allocate mip map levels |
1379 | /// - `budgeted` whether to count a newly created texture for the returned image |
1380 | /// counts against the context's budget. |
1381 | /// Returns: created [`Image`], or `None` |
1382 | #[cfg (feature = "gpu" )] |
1383 | pub fn new_texture_image_budgeted( |
1384 | &self, |
1385 | direct_context: &mut gpu::DirectContext, |
1386 | mipmapped: gpu::Mipmapped, |
1387 | budgeted: gpu::Budgeted, |
1388 | ) -> Option<Image> { |
1389 | gpu::images::texture_from_image(direct_context, self, mipmapped, budgeted) |
1390 | } |
1391 | |
1392 | /// Returns raster image or lazy image. Copies [`Image`] backed by GPU texture into |
1393 | /// CPU memory if needed. Returns original [`Image`] if decoded in raster bitmap, |
1394 | /// or if encoded in a stream. |
1395 | /// |
1396 | /// Returns `None` if backed by GPU texture and copy fails. |
1397 | /// |
1398 | /// Returns: raster image, lazy image, or `None` |
1399 | /// |
1400 | /// example: <https://fiddle.skia.org/c/@Image_makeNonTextureImage> |
1401 | #[deprecated (since = "0.64.0" , note = "use make_non_texture_image()" )] |
1402 | pub fn to_non_texture_image(&self) -> Option<Image> { |
1403 | Image::from_ptr(unsafe { |
1404 | sb::C_SkImage_makeNonTextureImage(self.native(), ptr::null_mut()) |
1405 | }) |
1406 | } |
1407 | |
1408 | /// Returns raster image or lazy image. Copies [`Image`] backed by GPU texture into |
1409 | /// CPU memory if needed. Returns original [`Image`] if decoded in raster bitmap, |
1410 | /// or if encoded in a stream. |
1411 | /// |
1412 | /// Returns `None` if backed by GPU texture and copy fails. |
1413 | /// |
1414 | /// Returns: raster image, lazy image, or `None` |
1415 | /// |
1416 | /// example: <https://fiddle.skia.org/c/@Image_makeNonTextureImage> |
1417 | pub fn make_non_texture_image<'a>( |
1418 | &self, |
1419 | context: impl Into<Option<&'a mut gpu::DirectContext>>, |
1420 | ) -> Option<Image> { |
1421 | Image::from_ptr(unsafe { |
1422 | sb::C_SkImage_makeNonTextureImage( |
1423 | self.native(), |
1424 | context.into().native_ptr_or_null_mut(), |
1425 | ) |
1426 | }) |
1427 | } |
1428 | |
1429 | /// Returns raster image. Copies [`Image`] backed by GPU texture into CPU memory, |
1430 | /// or decodes [`Image`] from lazy image. Returns original [`Image`] if decoded in |
1431 | /// raster bitmap. |
1432 | /// |
1433 | /// Returns `None` if copy, decode, or pixel read fails. |
1434 | /// |
1435 | /// If `caching_hint` is [`CachingHint::Allow`], pixels may be retained locally. |
1436 | /// If `caching_hint` is [`CachingHint::Disallow`], pixels are not added to the local cache. |
1437 | /// |
1438 | /// Returns: raster image, or `None` |
1439 | /// |
1440 | /// example: <https://fiddle.skia.org/c/@Image_makeRasterImage> |
1441 | #[deprecated (since = "0.64.0" , note = "use make_raster_image()" )] |
1442 | pub fn to_raster_image(&self, caching_hint: impl Into<Option<CachingHint>>) -> Option<Image> { |
1443 | let caching_hint = caching_hint.into().unwrap_or(CachingHint::Disallow); |
1444 | Image::from_ptr(unsafe { |
1445 | sb::C_SkImage_makeRasterImage(self.native(), ptr::null_mut(), caching_hint) |
1446 | }) |
1447 | } |
1448 | |
1449 | /// Returns raster image. Copies [`Image`] backed by GPU texture into CPU memory, |
1450 | /// or decodes [`Image`] from lazy image. Returns original [`Image`] if decoded in |
1451 | /// raster bitmap. |
1452 | /// |
1453 | /// Returns `None` if copy, decode, or pixel read fails. |
1454 | /// |
1455 | /// If `caching_hint` is [`CachingHint::Allow`], pixels may be retained locally. |
1456 | /// If `caching_hint` is [`CachingHint::Disallow`], pixels are not added to the local cache. |
1457 | /// |
1458 | /// Returns: raster image, or `None` |
1459 | /// |
1460 | /// example: <https://fiddle.skia.org/c/@Image_makeRasterImage> |
1461 | pub fn make_raster_image<'a>( |
1462 | &self, |
1463 | context: impl Into<Option<&'a mut gpu::DirectContext>>, |
1464 | caching_hint: impl Into<Option<CachingHint>>, |
1465 | ) -> Option<Image> { |
1466 | let caching_hint = caching_hint.into().unwrap_or(CachingHint::Disallow); |
1467 | Image::from_ptr(unsafe { |
1468 | sb::C_SkImage_makeRasterImage( |
1469 | self.native(), |
1470 | context.into().native_ptr_or_null_mut(), |
1471 | caching_hint, |
1472 | ) |
1473 | }) |
1474 | } |
1475 | |
1476 | /// Creates filtered [`Image`]. filter processes original [`Image`], potentially changing |
1477 | /// color, position, and size. subset is the bounds of original [`Image`] processed |
1478 | /// by filter. `clip_bounds` is the expected bounds of the filtered [`Image`]. `out_subset` |
1479 | /// is required storage for the actual bounds of the filtered [`Image`]. offset is |
1480 | /// required storage for translation of returned [`Image`]. |
1481 | /// |
1482 | /// Returns `None` if [`Image`] could not be created or if the recording context provided doesn't |
1483 | /// match the GPU context in which the image was created. If `None` is returned, `out_subset` |
1484 | /// and offset are undefined. |
1485 | /// |
1486 | /// Useful for animation of [`ImageFilter`] that varies size from frame to frame. |
1487 | /// Returned [`Image`] is created larger than required by filter so that GPU texture |
1488 | /// can be reused with different sized effects. `out_subset` describes the valid bounds |
1489 | /// of GPU texture returned. offset translates the returned [`Image`] to keep subsequent |
1490 | /// animation frames aligned with respect to each other. |
1491 | /// |
1492 | /// - `context` the [`gpu::RecordingContext`] in play - if it exists |
1493 | /// - `filter` how [`Image`] is sampled when transformed |
1494 | /// - `subset` bounds of [`Image`] processed by filter |
1495 | /// - `clip_bounds` expected bounds of filtered [`Image`] |
1496 | /// - `out_subset` storage for returned [`Image`] bounds |
1497 | /// - `offset` storage for returned [`Image`] translation |
1498 | /// Returns: filtered [`Image`], or `None` |
1499 | #[deprecated (since = "0.67.0" , note = "use images::make_with_filter()" )] |
1500 | pub fn new_with_filter( |
1501 | &self, |
1502 | _context: Option<&mut gpu::RecordingContext>, |
1503 | filter: &ImageFilter, |
1504 | clip_bounds: impl Into<IRect>, |
1505 | subset: impl Into<IRect>, |
1506 | ) -> Option<(Image, IRect, IPoint)> { |
1507 | images::make_with_filter(self, filter, subset.into(), clip_bounds.into()) |
1508 | } |
1509 | |
1510 | // TODO: MakeBackendTextureFromSkImage() |
1511 | |
1512 | /// Returns `true` if [`Image`] is backed by an image-generator or other service that creates |
1513 | /// and caches its pixels or texture on-demand. |
1514 | /// |
1515 | /// Returns: `true` if [`Image`] is created as needed |
1516 | /// |
1517 | /// example: <https://fiddle.skia.org/c/@Image_isLazyGenerated_a> |
1518 | /// example: <https://fiddle.skia.org/c/@Image_isLazyGenerated_b> |
1519 | pub fn is_lazy_generated(&self) -> bool { |
1520 | unsafe { sb::C_SkImage_isLazyGenerated(self.native()) } |
1521 | } |
1522 | |
1523 | /// See [`Self::new_color_space_with_context`] |
1524 | #[deprecated (since = "0.64.0" , note = "use make_color_space()" )] |
1525 | pub fn new_color_space(&self, color_space: impl Into<Option<ColorSpace>>) -> Option<Image> { |
1526 | self.make_color_space(None, color_space) |
1527 | } |
1528 | |
1529 | /// Creates [`Image`] in target [`ColorSpace`]. |
1530 | /// Returns `None` if [`Image`] could not be created. |
1531 | /// |
1532 | /// Returns original [`Image`] if it is in target [`ColorSpace`]. |
1533 | /// Otherwise, converts pixels from [`Image`] [`ColorSpace`] to target [`ColorSpace`]. |
1534 | /// If [`Image`] `color_space()` returns `None`, [`Image`] [`ColorSpace`] is assumed to be `s_rgb`. |
1535 | /// |
1536 | /// If this image is texture-backed, the context parameter is required and must match the |
1537 | /// context of the source image. |
1538 | /// |
1539 | /// - `target` [`ColorSpace`] describing color range of returned [`Image`] |
1540 | /// - `direct` The [`gpu::DirectContext`] in play, if it exists |
1541 | /// Returns: created [`Image`] in target [`ColorSpace`] |
1542 | /// |
1543 | /// example: <https://fiddle.skia.org/c/@Image_makeColorSpace> |
1544 | #[deprecated (since = "0.64.0" , note = "use make_color_space()" )] |
1545 | pub fn new_color_space_with_context<'a>( |
1546 | &self, |
1547 | color_space: impl Into<Option<ColorSpace>>, |
1548 | direct: impl Into<Option<&'a mut gpu::DirectContext>>, |
1549 | ) -> Option<Image> { |
1550 | self.make_color_space(direct, color_space) |
1551 | } |
1552 | |
1553 | /// Creates [`Image`] in target [`ColorSpace`]. |
1554 | /// Returns `None` if [`Image`] could not be created. |
1555 | /// |
1556 | /// Returns original [`Image`] if it is in target [`ColorSpace`]. |
1557 | /// Otherwise, converts pixels from [`Image`] [`ColorSpace`] to target [`ColorSpace`]. |
1558 | /// If [`Image`] `color_space()` returns `None`, [`Image`] [`ColorSpace`] is assumed to be `s_rgb`. |
1559 | /// |
1560 | /// If this image is texture-backed, the context parameter is required and must match the |
1561 | /// context of the source image. |
1562 | /// |
1563 | /// - `direct` The [`gpu::DirectContext`] in play, if it exists |
1564 | /// - `target` [`ColorSpace`] describing color range of returned [`Image`] |
1565 | /// Returns: created [`Image`] in target [`ColorSpace`] |
1566 | /// |
1567 | /// example: <https://fiddle.skia.org/c/@Image_makeColorSpace> |
1568 | pub fn make_color_space<'a>( |
1569 | &self, |
1570 | direct: impl Into<Option<&'a mut gpu::DirectContext>>, |
1571 | color_space: impl Into<Option<ColorSpace>>, |
1572 | ) -> Option<Image> { |
1573 | Image::from_ptr(unsafe { |
1574 | sb::C_SkImage_makeColorSpace( |
1575 | self.native(), |
1576 | direct.into().native_ptr_or_null_mut(), |
1577 | color_space.into().into_ptr_or_null(), |
1578 | ) |
1579 | }) |
1580 | } |
1581 | |
1582 | /// Creates a new [`Image`] identical to this one, but with a different [`ColorSpace`]. |
1583 | /// This does not convert the underlying pixel data, so the resulting image will draw |
1584 | /// differently. |
1585 | pub fn reinterpret_color_space(&self, new_color_space: impl Into<ColorSpace>) -> Option<Image> { |
1586 | Image::from_ptr(unsafe { |
1587 | sb::C_SkImage_reinterpretColorSpace(self.native(), new_color_space.into().into_ptr()) |
1588 | }) |
1589 | } |
1590 | } |
1591 | |