| 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 | |