1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#[cfg(feature = "img")]
use image::DynamicImage;
use libwebp_sys::*;
use crate::shared::*;
pub struct Encoder<'a> {
image: &'a [u8],
layout: PixelLayout,
width: u32,
height: u32,
}
impl<'a> Encoder<'a> {
pub fn new(image: &'a [u8], layout: PixelLayout, width: u32, height: u32) -> Self {
Self { image, layout, width, height }
}
#[cfg(feature = "img")]
pub fn from_image(image: &'a DynamicImage) -> Result<Self, &str> {
match image {
DynamicImage::ImageLuma8(_) => { Err("Unimplemented") }
DynamicImage::ImageLumaA8(_) => { Err("Unimplemented") }
DynamicImage::ImageRgb8(image) => {
Ok(Self::from_rgb(image.as_ref(), image.width(), image.height()))
}
DynamicImage::ImageRgba8(image) => {
Ok(Self::from_rgba(image.as_ref(), image.width(), image.height()))
}
_ => { Err("Unimplemented") }
}
}
pub fn from_rgb(image: &'a [u8], width: u32, height: u32) -> Self {
Self { image, layout: PixelLayout::Rgb, width, height }
}
pub fn from_rgba(image: &'a [u8], width: u32, height: u32) -> Self {
Self { image, layout: PixelLayout::Rgba, width, height }
}
pub fn encode(&self, quality: f32) -> WebPMemory {
unsafe { encode(self.image, self.layout, self.width, self.height, quality) }
}
pub fn encode_lossless(&self) -> WebPMemory {
unsafe { encode(self.image, self.layout, self.width, self.height, -1.0) }
}
}
unsafe fn encode(image: &[u8], color: PixelLayout, width: u32, height: u32, quality: f32) -> WebPMemory {
let width = width as _;
let height = height as _;
let mut buffer = std::ptr::null_mut::<u8>();
let len = match color {
PixelLayout::Rgb if quality < 0.0 => {
let stride = width * 3;
WebPEncodeLosslessRGB(image.as_ptr(), width, height, stride, &mut buffer as *mut _)
}
PixelLayout::Rgb => {
let stride = width * 3;
WebPEncodeRGB(image.as_ptr(), width, height, stride, quality, &mut buffer as *mut _)
}
PixelLayout::Rgba if quality < 0.0 => {
let stride = width * 4;
WebPEncodeLosslessRGBA(image.as_ptr(), width, height, stride, &mut buffer as *mut _)
}
PixelLayout::Rgba => {
let stride = width * 4;
WebPEncodeRGBA(image.as_ptr(), width, height, stride, quality, &mut buffer as *mut _)
}
};
WebPMemory(buffer, len)
}