webp_encoder/
lib.rs

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