mirror of https://github.com/ChillFish8/lust.git
Fix more encoding bugs
This commit is contained in:
parent
465aeb0265
commit
8ca8094d8d
|
@ -417,16 +417,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "deflate"
|
|
||||||
version = "0.8.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
|
|
||||||
dependencies = [
|
|
||||||
"adler32",
|
|
||||||
"byteorder",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deflate"
|
name = "deflate"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -494,7 +484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4badb9489a465cb2c555af1f00f0bfd8cecd6fc12ac11da9d5b40c5dd5f0200"
|
checksum = "d4badb9489a465cb2c555af1f00f0bfd8cecd6fc12ac11da9d5b40c5dd5f0200"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"deflate 1.0.0",
|
"deflate",
|
||||||
"flume",
|
"flume",
|
||||||
"half",
|
"half",
|
||||||
"inflate",
|
"inflate",
|
||||||
|
@ -870,25 +860,6 @@ dependencies = [
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "image"
|
|
||||||
version = "0.23.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
|
|
||||||
dependencies = [
|
|
||||||
"bytemuck",
|
|
||||||
"byteorder",
|
|
||||||
"color_quant",
|
|
||||||
"gif",
|
|
||||||
"jpeg-decoder 0.1.22",
|
|
||||||
"num-iter",
|
|
||||||
"num-rational 0.3.2",
|
|
||||||
"num-traits",
|
|
||||||
"png 0.16.8",
|
|
||||||
"scoped_threadpool",
|
|
||||||
"tiff 0.6.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.24.1"
|
version = "0.24.1"
|
||||||
|
@ -902,11 +873,11 @@ dependencies = [
|
||||||
"gif",
|
"gif",
|
||||||
"jpeg-decoder 0.2.2",
|
"jpeg-decoder 0.2.2",
|
||||||
"num-iter",
|
"num-iter",
|
||||||
"num-rational 0.4.0",
|
"num-rational",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"png 0.17.5",
|
"png",
|
||||||
"scoped_threadpool",
|
"scoped_threadpool",
|
||||||
"tiff 0.7.1",
|
"tiff",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -957,9 +928,6 @@ name = "jpeg-decoder"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
||||||
dependencies = [
|
|
||||||
"rayon",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jpeg-decoder"
|
name = "jpeg-decoder"
|
||||||
|
@ -1053,7 +1021,7 @@ dependencies = [
|
||||||
"enum_dispatch",
|
"enum_dispatch",
|
||||||
"futures",
|
"futures",
|
||||||
"hashbrown 0.12.0",
|
"hashbrown 0.12.0",
|
||||||
"image 0.24.1",
|
"image",
|
||||||
"mimalloc",
|
"mimalloc",
|
||||||
"mime",
|
"mime",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -1108,15 +1076,6 @@ version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miniz_oxide"
|
|
||||||
version = "0.3.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
|
||||||
dependencies = [
|
|
||||||
"adler32",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
|
@ -1217,17 +1176,6 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-rational"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"num-integer",
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-rational"
|
name = "num-rational"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -1369,18 +1317,6 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "png"
|
|
||||||
version = "0.16.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"crc32fast",
|
|
||||||
"deflate 0.8.6",
|
|
||||||
"miniz_oxide 0.3.7",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.5"
|
version = "0.17.5"
|
||||||
|
@ -1389,7 +1325,7 @@ checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"deflate 1.0.0",
|
"deflate",
|
||||||
"miniz_oxide 0.5.1",
|
"miniz_oxide 0.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1932,17 +1868,6 @@ dependencies = [
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tiff"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
|
|
||||||
dependencies = [
|
|
||||||
"jpeg-decoder 0.1.22",
|
|
||||||
"miniz_oxide 0.4.4",
|
|
||||||
"weezl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiff"
|
name = "tiff"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -2308,9 +2233,9 @@ checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
|
||||||
name = "webp"
|
name = "webp"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"image 0.23.14",
|
"anyhow",
|
||||||
|
"image",
|
||||||
"libwebp-sys",
|
"libwebp-sys",
|
||||||
"once_cell",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -32,7 +32,7 @@ crossbeam = "0.8.1"
|
||||||
tracing = "0.1.30"
|
tracing = "0.1.30"
|
||||||
tracing-futures = "0.2.5"
|
tracing-futures = "0.2.5"
|
||||||
tracing-subscriber = "0.3.8"
|
tracing-subscriber = "0.3.8"
|
||||||
image = "0.24.1"
|
image = "0.24"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|
|
@ -23,7 +23,13 @@ impl JustInTimePipeline {
|
||||||
|
|
||||||
impl Pipeline for JustInTimePipeline {
|
impl Pipeline for JustInTimePipeline {
|
||||||
fn on_upload(&self, kind: ImageKind, data: Vec<u8>) -> anyhow::Result<PipelineResult> {
|
fn on_upload(&self, kind: ImageKind, data: Vec<u8>) -> anyhow::Result<PipelineResult> {
|
||||||
let img = processor::encoder::encode_once(self.formats.original_image_store_format, kind, data.into())?;
|
let webp_config = webp::config(
|
||||||
|
self.formats.webp_config.quality.is_none(),
|
||||||
|
self.formats.webp_config.quality.unwrap_or(50f32),
|
||||||
|
self.formats.webp_config.method.unwrap_or(4) as i32,
|
||||||
|
self.formats.webp_config.threading,
|
||||||
|
);
|
||||||
|
let img = processor::encoder::encode_once(webp_config, self.formats.original_image_store_format, kind, data.into())?;
|
||||||
|
|
||||||
Ok(PipelineResult {
|
Ok(PipelineResult {
|
||||||
response: None,
|
response: None,
|
||||||
|
@ -39,7 +45,13 @@ impl Pipeline for JustInTimePipeline {
|
||||||
sizing_id: u32,
|
sizing_id: u32,
|
||||||
_custom_size: Option<(u32, u32)>,
|
_custom_size: Option<(u32, u32)>,
|
||||||
) -> anyhow::Result<PipelineResult> {
|
) -> anyhow::Result<PipelineResult> {
|
||||||
let img = processor::encoder::encode_once(desired_kind, data_kind, data)?;
|
let webp_config = webp::config(
|
||||||
|
self.formats.webp_config.quality.is_none(),
|
||||||
|
self.formats.webp_config.quality.unwrap_or(50f32),
|
||||||
|
self.formats.webp_config.method.unwrap_or(4) as i32,
|
||||||
|
self.formats.webp_config.threading,
|
||||||
|
);
|
||||||
|
let img = processor::encoder::encode_once(webp_config, desired_kind, data_kind, data)?;
|
||||||
|
|
||||||
let (buff, sizing_id) = if sizing_id != 0 {
|
let (buff, sizing_id) = if sizing_id != 0 {
|
||||||
if let Some(cfg) = self.presets.get(&sizing_id) {
|
if let Some(cfg) = self.presets.get(&sizing_id) {
|
||||||
|
|
|
@ -23,7 +23,13 @@ impl RealtimePipeline {
|
||||||
|
|
||||||
impl Pipeline for RealtimePipeline {
|
impl Pipeline for RealtimePipeline {
|
||||||
fn on_upload(&self, kind: ImageKind, data: Vec<u8>) -> anyhow::Result<PipelineResult> {
|
fn on_upload(&self, kind: ImageKind, data: Vec<u8>) -> anyhow::Result<PipelineResult> {
|
||||||
let img = processor::encoder::encode_once(self.formats.original_image_store_format, kind, data.into())?;
|
let webp_config = webp::config(
|
||||||
|
self.formats.webp_config.quality.is_none(),
|
||||||
|
self.formats.webp_config.quality.unwrap_or(50f32),
|
||||||
|
self.formats.webp_config.method.unwrap_or(4) as i32,
|
||||||
|
self.formats.webp_config.threading,
|
||||||
|
);
|
||||||
|
let img = processor::encoder::encode_once(webp_config, self.formats.original_image_store_format, kind, data.into())?;
|
||||||
|
|
||||||
Ok(PipelineResult {
|
Ok(PipelineResult {
|
||||||
response: None,
|
response: None,
|
||||||
|
@ -39,7 +45,13 @@ impl Pipeline for RealtimePipeline {
|
||||||
sizing_id: u32,
|
sizing_id: u32,
|
||||||
custom_size: Option<(u32, u32)>,
|
custom_size: Option<(u32, u32)>,
|
||||||
) -> anyhow::Result<PipelineResult> {
|
) -> anyhow::Result<PipelineResult> {
|
||||||
let img = processor::encoder::encode_once(desired_kind, data_kind, data)?;
|
let webp_config = webp::config(
|
||||||
|
self.formats.webp_config.quality.is_none(),
|
||||||
|
self.formats.webp_config.quality.unwrap_or(50f32),
|
||||||
|
self.formats.webp_config.method.unwrap_or(4) as i32,
|
||||||
|
self.formats.webp_config.threading,
|
||||||
|
);
|
||||||
|
let img = processor::encoder::encode_once(webp_config, desired_kind, data_kind, data)?;
|
||||||
|
|
||||||
let (buff, sizing_id) = if sizing_id != 0 {
|
let (buff, sizing_id) = if sizing_id != 0 {
|
||||||
let maybe_resize = match self.presets.get(&sizing_id) {
|
let maybe_resize = match self.presets.get(&sizing_id) {
|
||||||
|
|
|
@ -16,6 +16,12 @@ pub fn encode_following_config(
|
||||||
data: Bytes,
|
data: Bytes,
|
||||||
) -> anyhow::Result<Vec<EncodedImage>> {
|
) -> anyhow::Result<Vec<EncodedImage>> {
|
||||||
let original_image = Arc::new(load_from_memory_with_format(data.as_ref(), kind.into())?);
|
let original_image = Arc::new(load_from_memory_with_format(data.as_ref(), kind.into())?);
|
||||||
|
let webp_config = webp::config(
|
||||||
|
cfg.webp_config.quality.is_none(),
|
||||||
|
cfg.webp_config.quality.unwrap_or(50f32),
|
||||||
|
cfg.webp_config.method.unwrap_or(4) as i32,
|
||||||
|
cfg.webp_config.threading,
|
||||||
|
);
|
||||||
|
|
||||||
let (tx, rx) = crossbeam::channel::bounded(4);
|
let (tx, rx) = crossbeam::channel::bounded(4);
|
||||||
|
|
||||||
|
@ -24,9 +30,9 @@ pub fn encode_following_config(
|
||||||
let tx_local = tx.clone();
|
let tx_local = tx.clone();
|
||||||
let local = original_image.clone();
|
let local = original_image.clone();
|
||||||
rayon::spawn(move || {
|
rayon::spawn(move || {
|
||||||
let result = encode_to(&local, ImageFormat::Png);
|
let result = encode_to(webp_config, &local, (*variant).into());
|
||||||
tx_local
|
tx_local
|
||||||
.send(result.map(|v| EncodedImage { kind: ImageKind::Png, buff: v }))
|
.send(result.map(|v| EncodedImage { kind: *variant, buff: v }))
|
||||||
.expect("Failed to respond to encoding request. Sender already closed.");
|
.expect("Failed to respond to encoding request. Sender already closed.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -54,6 +60,7 @@ pub fn encode_following_config(
|
||||||
|
|
||||||
|
|
||||||
pub fn encode_once(
|
pub fn encode_once(
|
||||||
|
webp_cfg: webp::WebPConfig,
|
||||||
to: ImageKind,
|
to: ImageKind,
|
||||||
from: ImageKind,
|
from: ImageKind,
|
||||||
data: Bytes,
|
data: Bytes,
|
||||||
|
@ -64,7 +71,7 @@ pub fn encode_once(
|
||||||
|
|
||||||
let encoded = if from != to {
|
let encoded = if from != to {
|
||||||
rayon::spawn(move || {
|
rayon::spawn(move || {
|
||||||
let result = encode_to(&original_image, to.into());
|
let result = encode_to(webp_cfg, &original_image, to.into());
|
||||||
tx.send(result.map(|v| EncodedImage { kind: to, buff: v }))
|
tx.send(result.map(|v| EncodedImage { kind: to, buff: v }))
|
||||||
.expect("Failed to respond to encoding request. Sender already closed.");
|
.expect("Failed to respond to encoding request. Sender already closed.");
|
||||||
});
|
});
|
||||||
|
@ -82,7 +89,15 @@ pub fn encode_once(
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn encode_to(img: &DynamicImage, format: ImageFormat) -> anyhow::Result<Bytes> {
|
pub fn encode_to(webp_cfg: webp::WebPConfig, img: &DynamicImage, format: ImageFormat) -> anyhow::Result<Bytes> {
|
||||||
|
if let ImageFormat::WebP = format {
|
||||||
|
let webp_image = webp::Encoder::from_image(webp_cfg, img);
|
||||||
|
let encoded = webp_image.encode();
|
||||||
|
|
||||||
|
return Ok(Bytes::from(encoded?.to_vec()))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let mut buff = Cursor::new(Vec::new());
|
let mut buff = Cursor::new(Vec::new());
|
||||||
img.write_to(&mut buff, format)?;
|
img.write_to(&mut buff, format)?;
|
||||||
Ok(Bytes::from(buff.into_inner()))
|
Ok(Bytes::from(buff.into_inner()))
|
||||||
|
|
|
@ -8,5 +8,5 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libwebp-sys = "0.3.2"
|
libwebp-sys = "0.3.2"
|
||||||
image = "0.23"
|
image = "0.24"
|
||||||
once_cell = "1.8.0"
|
anyhow = "1"
|
|
@ -1,13 +1,13 @@
|
||||||
use std::fmt::{Debug, Error, Formatter};
|
use std::fmt::{Debug, Error, Formatter};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use image::{DynamicImage, GenericImageView, RgbaImage};
|
use anyhow::{Result, anyhow};
|
||||||
|
use image::{DynamicImage, RgbaImage};
|
||||||
use libwebp_sys::WebPEncodingError::VP8_ENC_OK;
|
use libwebp_sys::WebPEncodingError::VP8_ENC_OK;
|
||||||
use libwebp_sys::WebPPreset::WEBP_PRESET_DEFAULT;
|
use libwebp_sys::WebPPreset::WEBP_PRESET_DEFAULT;
|
||||||
use libwebp_sys::*;
|
use libwebp_sys::*;
|
||||||
use once_cell::sync::OnceCell;
|
pub use libwebp_sys::WebPConfig;
|
||||||
|
|
||||||
static CONFIG: OnceCell<WebPConfig> = OnceCell::new();
|
|
||||||
|
|
||||||
/// Inits the global encoder config.
|
/// Inits the global encoder config.
|
||||||
///
|
///
|
||||||
|
@ -21,8 +21,8 @@ static CONFIG: OnceCell<WebPConfig> = OnceCell::new();
|
||||||
///
|
///
|
||||||
/// - multi_threading:
|
/// - multi_threading:
|
||||||
/// If the system should to attempt to use in multi-threaded encoding.
|
/// If the system should to attempt to use in multi-threaded encoding.
|
||||||
pub fn init_global(lossless: bool, quality: f32, method: i32, multi_threading: bool) {
|
pub fn config(lossless: bool, quality: f32, method: i32, multi_threading: bool) -> WebPConfig {
|
||||||
let cfg = WebPConfig {
|
WebPConfig {
|
||||||
lossless: if lossless { 1 } else { 0 },
|
lossless: if lossless { 1 } else { 0 },
|
||||||
quality,
|
quality,
|
||||||
method,
|
method,
|
||||||
|
@ -51,9 +51,7 @@ pub fn init_global(lossless: bool, quality: f32, method: i32, multi_threading: b
|
||||||
use_delta_palette: 0,
|
use_delta_palette: 0,
|
||||||
use_sharp_yuv: 0,
|
use_sharp_yuv: 0,
|
||||||
pad: [100, 100],
|
pad: [100, 100],
|
||||||
};
|
}
|
||||||
|
|
||||||
let _ = CONFIG.set(cfg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Picture is uninitialized.
|
/// Picture is uninitialized.
|
||||||
|
@ -118,6 +116,7 @@ pub enum PixelLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Encoder<'a> {
|
pub struct Encoder<'a> {
|
||||||
|
cfg: WebPConfig,
|
||||||
layout: PixelLayout,
|
layout: PixelLayout,
|
||||||
image: &'a [u8],
|
image: &'a [u8],
|
||||||
width: u32,
|
width: u32,
|
||||||
|
@ -126,30 +125,25 @@ pub struct Encoder<'a> {
|
||||||
|
|
||||||
impl<'a> Encoder<'a> {
|
impl<'a> Encoder<'a> {
|
||||||
/// Creates a new encoder from the given image.
|
/// Creates a new encoder from the given image.
|
||||||
pub fn from_image(image: &'a DynamicImage) -> Self {
|
pub fn from_image(cfg: WebPConfig, image: &'a DynamicImage) -> Self {
|
||||||
match image {
|
match image {
|
||||||
DynamicImage::ImageRgb8(image) => {
|
DynamicImage::ImageRgb8(image) => {
|
||||||
Self::from_rgb(image.as_ref(), image.width(), image.height())
|
Self::from_rgb(cfg, image.as_ref(), image.width(), image.height())
|
||||||
},
|
},
|
||||||
DynamicImage::ImageRgba8(image) => {
|
DynamicImage::ImageRgba8(image) => {
|
||||||
Self::from_rgba(image.as_ref(), image.width(), image.height())
|
Self::from_rgba(cfg,image.as_ref(), image.width(), image.height())
|
||||||
},
|
|
||||||
DynamicImage::ImageBgr8(image) => {
|
|
||||||
Self::from_bgr(image.as_ref(), image.width(), image.height())
|
|
||||||
},
|
|
||||||
DynamicImage::ImageBgra8(image) => {
|
|
||||||
Self::from_bgra(image.as_ref(), image.width(), image.height())
|
|
||||||
},
|
},
|
||||||
other => {
|
other => {
|
||||||
let image = other.to_rgba8();
|
let image = other.to_rgba8();
|
||||||
Self::from_other(other.as_bytes(), other.width(), other.height(), image)
|
Self::from_other(cfg,other.as_bytes(), other.width(), other.height(), image)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new encoder from the given image data in the RGB pixel layout.
|
/// Creates a new encoder from the given image data in the RGB pixel layout.
|
||||||
pub fn from_rgb(image: &'a [u8], width: u32, height: u32) -> Self {
|
pub fn from_rgb(cfg: WebPConfig, image: &'a [u8], width: u32, height: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
cfg,
|
||||||
image,
|
image,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
@ -158,8 +152,9 @@ impl<'a> Encoder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new encoder from the given image data in the RGBA pixel layout.
|
/// Creates a new encoder from the given image data in the RGBA pixel layout.
|
||||||
pub fn from_rgba(image: &'a [u8], width: u32, height: u32) -> Self {
|
pub fn from_rgba(cfg: WebPConfig, image: &'a [u8], width: u32, height: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
cfg,
|
||||||
image,
|
image,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
@ -167,30 +162,11 @@ impl<'a> Encoder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new encoder from the given image data in the BGR pixel layout.
|
|
||||||
pub fn from_bgr(image: &'a [u8], width: u32, height: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
image,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
layout: PixelLayout::BGR,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new encoder from the given image data in the BGRA pixel layout.
|
|
||||||
pub fn from_bgra(image: &'a [u8], width: u32, height: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
image,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
layout: PixelLayout::BGRA,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new encoder from the given image data in the Other layout,
|
/// Creates a new encoder from the given image data in the Other layout,
|
||||||
/// this creates a copy of the data to convert it to RGBA.
|
/// this creates a copy of the data to convert it to RGBA.
|
||||||
pub fn from_other(image: &'a [u8], width: u32, height: u32, other: RgbaImage) -> Self {
|
pub fn from_other(cfg: WebPConfig, image: &'a [u8], width: u32, height: u32, other: RgbaImage) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
cfg,
|
||||||
image,
|
image,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
@ -199,28 +175,26 @@ impl<'a> Encoder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode the image with the given global config.
|
/// Encode the image with the given global config.
|
||||||
pub fn encode(&self) -> WebPMemory {
|
pub fn encode(self) -> Result<WebPMemory> {
|
||||||
let (img, layout) = if let PixelLayout::Other(img) = &self.layout {
|
let (img, layout) = if let PixelLayout::Other(img) = &self.layout {
|
||||||
(img.as_ref(), &PixelLayout::RGBA)
|
(img.as_ref(), &PixelLayout::RGBA)
|
||||||
} else {
|
} else {
|
||||||
(self.image.as_ref(), &self.layout)
|
(self.image.as_ref(), &self.layout)
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe { encode(img, layout, self.width, self.height) }
|
unsafe { encode(self.cfg, img, layout, self.width, self.height) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! check_ok {
|
macro_rules! check_ok {
|
||||||
( $e:expr, $msg:expr ) => {{
|
( $e:expr, $msg:expr ) => {{
|
||||||
if $e == 0 {
|
if $e == 0 {
|
||||||
panic!("{}", $msg);
|
return Err(anyhow!("{}", $msg));
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn encode(image: &[u8], layout: &PixelLayout, width: u32, height: u32) -> WebPMemory {
|
unsafe fn encode(cfg: WebPConfig, image: &[u8], layout: &PixelLayout, width: u32, height: u32) -> Result<WebPMemory> {
|
||||||
let cfg = CONFIG.get().expect("config un-initialised.").clone();
|
|
||||||
|
|
||||||
let picture = empty_webp_picture();
|
let picture = empty_webp_picture();
|
||||||
let writer = WebPMemoryWriter {
|
let writer = WebPMemoryWriter {
|
||||||
mem: std::ptr::null_mut::<u8>(),
|
mem: std::ptr::null_mut::<u8>(),
|
||||||
|
@ -283,13 +257,13 @@ unsafe fn encode(image: &[u8], layout: &PixelLayout, width: u32, height: u32) ->
|
||||||
WebPPictureFree(picture_ptr);
|
WebPPictureFree(picture_ptr);
|
||||||
if ok == 0 {
|
if ok == 0 {
|
||||||
WebPMemoryWriterClear(writer_ptr);
|
WebPMemoryWriterClear(writer_ptr);
|
||||||
panic!(
|
return Err(anyhow!(
|
||||||
"memory error. libwebp error code: {:?}",
|
"memory error. libwebp error code: {:?}",
|
||||||
(*picture_ptr).error_code
|
(*picture_ptr).error_code
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
WebPMemory((*writer_ptr).mem, (*writer_ptr).size)
|
Ok(WebPMemory((*writer_ptr).mem, (*writer_ptr).size))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This struct represents a safe wrapper around memory owned by libwebp.
|
/// This struct represents a safe wrapper around memory owned by libwebp.
|
||||||
|
@ -329,7 +303,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn ensure_global() {
|
fn ensure_global() {
|
||||||
init_global(true, 50.0, 6, true)
|
config(true, 50.0, 6, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue