1use std::ffi::{c_int, c_void};
2
3use anyhow::{ensure, Result};
4
5#[link(name = "webp", kind = "dylib")]
6extern "C" {
7 fn WebPEncodeLosslessRGBA(
8 rgba: *const u8,
9 width: c_int,
10 height: c_int,
11 stride: c_int,
12 output: *mut *mut u8,
13 ) -> usize;
14
15 fn WebPFree(ptr: *mut c_void);
16}
17
18pub fn webp_encode_lossless_rgba(rgba: &[u8], width: usize, height: usize) -> Result<EncodedImage> {
19 unsafe {
20 ensure!(width < 16384 && height < 16384);
21 ensure!(width > 0 && height > 0);
22 ensure!(rgba.len() == width * height * 4);
23 let mut ptr = std::ptr::null_mut();
24 let len = WebPEncodeLosslessRGBA(
25 rgba.as_ptr(),
26 width as c_int,
27 height as c_int,
28 (width * 4) as c_int,
29 &mut ptr,
30 );
31 ensure!(len != 0);
32 ensure!(!ptr.is_null());
33 Ok(EncodedImage { ptr, len })
34 }
35}
36
37pub struct EncodedImage {
38 ptr: *mut u8,
39 len: usize,
40}
41
42impl EncodedImage {
43 pub fn webp_file(&self) -> &[u8] {
44 unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
45 }
46}
47
48impl Drop for EncodedImage {
49 fn drop(&mut self) {
50 unsafe {
51 WebPFree(self.ptr as *mut c_void);
52 }
53 }
54}
55
56unsafe impl Send for EncodedImage {}
57unsafe impl Sync for EncodedImage {}