mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-07-14 19:10:28 +03:00
refactor(core): use the image crate (#9132)
This commit is contained in:
parent
26f0f71a40
commit
db0a24a973
5
.changes/image-crate.md
Normal file
5
.changes/image-crate.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch:breaking
|
||||
---
|
||||
|
||||
Use the image crate for `tauri::image::Image` and remove the `from_png_bytes` and `from_ico_bytes` APIs.
|
5
.changes/remove-from-format-image.md
Normal file
5
.changes/remove-from-format-image.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tauri-apps/api": patch:breaking
|
||||
---
|
||||
|
||||
Remove the `Image.fromPngBytes` and `Image.fromIcoBytes` APIs. Use `Image.fromBytes` instead.
|
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -1591,6 +1591,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"num-traits",
|
||||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3610,8 +3611,7 @@ dependencies = [
|
||||
"heck",
|
||||
"http",
|
||||
"http-range",
|
||||
"ico",
|
||||
"infer",
|
||||
"image",
|
||||
"jni",
|
||||
"libc",
|
||||
"log",
|
||||
@ -3619,7 +3619,6 @@ dependencies = [
|
||||
"muda",
|
||||
"objc",
|
||||
"percent-encoding",
|
||||
"png",
|
||||
"proptest",
|
||||
"quickcheck",
|
||||
"quickcheck_macros",
|
||||
|
@ -68,9 +68,7 @@ urlpattern = "0.2"
|
||||
mime = "0.3"
|
||||
data-url = { version = "0.3", optional = true }
|
||||
serialize-to-javascript = "=0.1.1"
|
||||
infer = { version = "0.15", optional = true }
|
||||
png = { version = "0.17", optional = true }
|
||||
ico = { version = "0.3.0", optional = true }
|
||||
image = { version = "0.24", default-features = false, optional = true }
|
||||
http-range = { version = "0.1.5", optional = true }
|
||||
tracing = { version = "0.1", optional = true }
|
||||
heck = "0.4"
|
||||
@ -154,8 +152,8 @@ webview-data-url = [ "data-url" ]
|
||||
protocol-asset = [ "http-range" ]
|
||||
config-json5 = [ "tauri-macros/config-json5" ]
|
||||
config-toml = [ "tauri-macros/config-toml" ]
|
||||
image-ico = [ "ico", "infer" ]
|
||||
image-png = [ "png", "infer" ]
|
||||
image-ico = [ "image/ico" ]
|
||||
image-png = [ "image/png" ]
|
||||
macos-proxy = [ "tauri-runtime-wry/macos-proxy" ]
|
||||
|
||||
[[example]]
|
||||
|
@ -142,8 +142,6 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
|
||||
&[
|
||||
("new", true),
|
||||
("from_bytes", true),
|
||||
("from_png_bytes", true),
|
||||
("from_ico_bytes", true),
|
||||
("from_path", true),
|
||||
("rgba", true),
|
||||
("width", true),
|
||||
|
@ -2,12 +2,8 @@
|
||||
|------|-----|
|
||||
|`allow-from-bytes`|Enables the from_bytes command without any pre-configured scope.|
|
||||
|`deny-from-bytes`|Denies the from_bytes command without any pre-configured scope.|
|
||||
|`allow-from-ico-bytes`|Enables the from_ico_bytes command without any pre-configured scope.|
|
||||
|`deny-from-ico-bytes`|Denies the from_ico_bytes command without any pre-configured scope.|
|
||||
|`allow-from-path`|Enables the from_path command without any pre-configured scope.|
|
||||
|`deny-from-path`|Denies the from_path command without any pre-configured scope.|
|
||||
|`allow-from-png-bytes`|Enables the from_png_bytes command without any pre-configured scope.|
|
||||
|`deny-from-png-bytes`|Denies the from_png_bytes command without any pre-configured scope.|
|
||||
|`allow-height`|Enables the height command without any pre-configured scope.|
|
||||
|`deny-height`|Denies the height command without any pre-configured scope.|
|
||||
|`allow-new`|Enables the new command without any pre-configured scope.|
|
||||
|
File diff suppressed because one or more lines are too long
@ -81,10 +81,10 @@ pub enum Error {
|
||||
/// Invalid glob pattern.
|
||||
#[error("invalid glob pattern: {0}")]
|
||||
GlobPattern(#[from] glob::PatternError),
|
||||
/// Error decoding PNG image.
|
||||
#[cfg(feature = "image-png")]
|
||||
#[error("failed to decode PNG: {0}")]
|
||||
PngDecode(#[from] png::DecodingError),
|
||||
/// Image error.
|
||||
#[cfg(any(feature = "image-png", feature = "image-ico"))]
|
||||
#[error("failed to process image: {0}")]
|
||||
Image(#[from] image::error::ImageError),
|
||||
/// The Window's raw handle is invalid for the platform.
|
||||
#[error("Unexpected `raw_window_handle` for the current platform")]
|
||||
InvalidWindowHandle,
|
||||
|
@ -7,7 +7,6 @@
|
||||
pub(crate) mod plugin;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{Manager, Resource, ResourceId, Runtime};
|
||||
@ -45,80 +44,24 @@ impl<'a> Image<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new image using the provided png bytes.
|
||||
#[cfg(feature = "image-png")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "image-png")))]
|
||||
pub fn from_png_bytes(bytes: &[u8]) -> std::io::Result<Self> {
|
||||
let decoder = png::Decoder::new(std::io::Cursor::new(bytes));
|
||||
let mut reader = decoder.read_info()?;
|
||||
let mut buffer = Vec::new();
|
||||
while let Ok(Some(row)) = reader.next_row() {
|
||||
buffer.extend(row.data());
|
||||
}
|
||||
Ok(Self {
|
||||
rgba: Cow::Owned(buffer),
|
||||
width: reader.info().width,
|
||||
height: reader.info().height,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new image using the provided ico bytes.
|
||||
#[cfg(feature = "image-ico")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "image-ico")))]
|
||||
pub fn from_ico_bytes(bytes: &[u8]) -> std::io::Result<Self> {
|
||||
let icon_dir = ico::IconDir::read(std::io::Cursor::new(&bytes))?;
|
||||
let first = icon_dir.entries().first().ok_or_else(|| {
|
||||
Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"Couldn't find any icons inside provided ico bytes",
|
||||
)
|
||||
})?;
|
||||
|
||||
let rgba = first.decode()?.rgba_data().to_vec();
|
||||
|
||||
Ok(Self {
|
||||
rgba: Cow::Owned(rgba),
|
||||
width: first.width(),
|
||||
height: first.height(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new image using the provided bytes.
|
||||
///
|
||||
/// Only `ico` and `png` are supported (based on activated feature flag).
|
||||
#[cfg(any(feature = "image-ico", feature = "image-png"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "image-ico", feature = "image-png"))))]
|
||||
pub fn from_bytes(bytes: &[u8]) -> std::io::Result<Self> {
|
||||
let extension = infer::get(bytes)
|
||||
.expect("could not determine icon extension")
|
||||
.extension();
|
||||
pub fn from_bytes(bytes: &[u8]) -> crate::Result<Self> {
|
||||
use image::GenericImageView;
|
||||
|
||||
match extension {
|
||||
#[cfg(feature = "image-ico")]
|
||||
"ico" => Self::from_ico_bytes(bytes),
|
||||
#[cfg(feature = "image-png")]
|
||||
"png" => Self::from_png_bytes(bytes),
|
||||
_ => {
|
||||
let supported = [
|
||||
#[cfg(feature = "image-png")]
|
||||
"'png'",
|
||||
#[cfg(feature = "image-ico")]
|
||||
"'ico'",
|
||||
];
|
||||
|
||||
Err(Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
format!(
|
||||
"Unexpected image format, expected {}, found '{extension}'. Please check the `image-*` Cargo features on the tauri crate to see if Tauri has optional support for this format.",
|
||||
if supported.is_empty() {
|
||||
"''".to_string()
|
||||
} else {
|
||||
supported.join(" or ")
|
||||
}
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
let img = image::load_from_memory(bytes)?;
|
||||
let pixels = img
|
||||
.pixels()
|
||||
.flat_map(|(_, _, pixel)| pixel.0)
|
||||
.collect::<Vec<_>>();
|
||||
Ok(Self {
|
||||
rgba: Cow::Owned(pixels),
|
||||
width: img.width(),
|
||||
height: img.height(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new image using the provided path.
|
||||
@ -126,7 +69,7 @@ impl<'a> Image<'a> {
|
||||
/// Only `ico` and `png` are supported (based on activated feature flag).
|
||||
#[cfg(any(feature = "image-ico", feature = "image-png"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "image-ico", feature = "image-png"))))]
|
||||
pub fn from_path<P: AsRef<std::path::Path>>(path: P) -> std::io::Result<Self> {
|
||||
pub fn from_path<P: AsRef<std::path::Path>>(path: P) -> crate::Result<Self> {
|
||||
let bytes = std::fs::read(path)?;
|
||||
Self::from_bytes(&bytes)
|
||||
}
|
||||
@ -242,8 +185,8 @@ impl JsImage {
|
||||
|
||||
#[cfg(not(any(feature = "image-ico", feature = "image-png")))]
|
||||
_ => Err(
|
||||
Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
format!(
|
||||
"expected RGBA image data, found {}",
|
||||
match self {
|
||||
|
@ -33,36 +33,6 @@ fn from_bytes() -> std::result::Result<(), &'static str> {
|
||||
Err("from_bytes is only supported if the `image-ico` or `image-png` Cargo features are enabled")
|
||||
}
|
||||
|
||||
#[cfg(feature = "image-ico")]
|
||||
#[command(root = "crate")]
|
||||
fn from_ico_bytes<R: Runtime>(app: AppHandle<R>, bytes: Vec<u8>) -> crate::Result<ResourceId> {
|
||||
let image = Image::from_ico_bytes(&bytes)?.to_owned();
|
||||
let mut resources_table = app.resources_table();
|
||||
let rid = resources_table.add(image);
|
||||
Ok(rid)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "image-ico"))]
|
||||
#[command(root = "crate")]
|
||||
fn from_ico_bytes() -> std::result::Result<(), &'static str> {
|
||||
Err("from_ico_bytes is only supported if the `image-ico` Cargo feature is enabled")
|
||||
}
|
||||
|
||||
#[cfg(feature = "image-png")]
|
||||
#[command(root = "crate")]
|
||||
fn from_png_bytes<R: Runtime>(app: AppHandle<R>, bytes: Vec<u8>) -> crate::Result<ResourceId> {
|
||||
let image = Image::from_png_bytes(&bytes)?.to_owned();
|
||||
let mut resources_table = app.resources_table();
|
||||
let rid = resources_table.add(image);
|
||||
Ok(rid)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "image-png"))]
|
||||
#[command(root = "crate")]
|
||||
fn from_png_bytes() -> std::result::Result<(), &'static str> {
|
||||
Err("from_png_bytes is only supported if the `image-ico` Cargo feature is enabled")
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "image-ico", feature = "image-png"))]
|
||||
#[command(root = "crate")]
|
||||
fn from_path<R: Runtime>(app: AppHandle<R>, path: std::path::PathBuf) -> crate::Result<ResourceId> {
|
||||
@ -103,14 +73,7 @@ fn height<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> crate::Result<u32>
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("image")
|
||||
.invoke_handler(crate::generate_handler![
|
||||
new,
|
||||
from_bytes,
|
||||
from_ico_bytes,
|
||||
from_png_bytes,
|
||||
from_path,
|
||||
rgba,
|
||||
width,
|
||||
height
|
||||
new, from_bytes, from_path, rgba, width, height
|
||||
])
|
||||
.build()
|
||||
}
|
||||
|
5
examples/api/src-tauri/Cargo.lock
generated
5
examples/api/src-tauri/Cargo.lock
generated
@ -1516,6 +1516,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"num-traits",
|
||||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3165,8 +3166,7 @@ dependencies = [
|
||||
"heck",
|
||||
"http",
|
||||
"http-range",
|
||||
"ico",
|
||||
"infer",
|
||||
"image",
|
||||
"jni",
|
||||
"libc",
|
||||
"log",
|
||||
@ -3174,7 +3174,6 @@ dependencies = [
|
||||
"muda",
|
||||
"objc",
|
||||
"percent-encoding",
|
||||
"png",
|
||||
"raw-window-handle 0.6.0",
|
||||
"reqwest",
|
||||
"serde",
|
||||
|
@ -44,42 +44,6 @@ export class Image extends Resource {
|
||||
}).then((rid) => new Image(rid))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new image using the provided png bytes.
|
||||
*
|
||||
* Note that you need the `image-png` Cargo features to use this API.
|
||||
* To enable it, change your Cargo.toml file:
|
||||
* ```toml
|
||||
* [dependencies]
|
||||
* tauri = { version = "...", features = ["...", "image-png"] }
|
||||
* ```
|
||||
*/
|
||||
static async fromPngBytes(
|
||||
bytes: number[] | Uint8Array | ArrayBuffer
|
||||
): Promise<Image> {
|
||||
return invoke<number>('plugin:image|from_png_bytes', {
|
||||
bytes: transformImage(bytes)
|
||||
}).then((rid) => new Image(rid))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new image using the provided ico bytes.
|
||||
*
|
||||
* Note that you need the `image-ico` Cargo features to use this API.
|
||||
* To enable it, change your Cargo.toml file:
|
||||
* ```toml
|
||||
* [dependencies]
|
||||
* tauri = { version = "...", features = ["...", "image-ico"] }
|
||||
* ```
|
||||
*/
|
||||
static async fromIcoBytes(
|
||||
bytes: number[] | Uint8Array | ArrayBuffer
|
||||
): Promise<Image> {
|
||||
return invoke<number>('plugin:image|from_ico_bytes', {
|
||||
bytes: transformImage(bytes)
|
||||
}).then((rid) => new Image(rid))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new image using the provided path.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user