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