Skip to content

Commit 66a8063

Browse files
authored
paa: add generate to wasm (#1199)
* paa: add generate to wasm * remove commented line
1 parent 6c11530 commit 66a8063

File tree

6 files changed

+78
-33
lines changed

6 files changed

+78
-33
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

browser/background.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import init, { ImageResult } from './hemtt_paa.js';
1+
import init, { FromPaaResult } from './hemtt_paa.js';
22

33
async function run() {
44
// Firefox linter has trouble with 'import', so import directly here
55
let app = await init();
66
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
77
if (request.contentScriptQuery == "fetch_blob") {
88
let b = new Uint8Array(request.ab);
9-
let result = new ImageResult(b);
9+
let result = new FromPaaResult(b);
1010
let arr = new Uint8Array(app.memory.buffer, result.data_ptr(), result.data_len());
1111
let blob = new Blob([arr], { type: 'image/png' });
1212
let reader = new FileReader();

libs/lzo/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ license = "GPL-2.0"
99
workspace = true
1010

1111
[dependencies]
12-
libc = "0.2.177"
1312
thiserror = { workspace = true }
1413

1514
[dev-dependencies]

libs/lzo/src/lzss/mod.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
mod compress;
2-
mod decompress;
1+
use std::alloc::{Layout, alloc, dealloc};
32
use std::mem;
43
use std::slice;
54

5+
mod compress;
6+
mod decompress;
7+
68
use thiserror::Error;
79

810
#[must_use]
@@ -49,9 +51,16 @@ pub enum LzoError {
4951
///
5052
/// # Errors
5153
/// [`LzoError`] if an error occurs
54+
///
55+
/// # Panics
56+
/// If the layout creation fails
5257
pub fn compress(input: &[u8], output: &mut Vec<u8>) -> Result<(), LzoError> {
5358
unsafe {
54-
let wrkmem = libc::malloc(LZO1X_MEM_COMPRESS);
59+
use std::ffi::c_void;
60+
61+
let layout = Layout::from_size_align(LZO1X_MEM_COMPRESS, std::mem::align_of::<u8>())
62+
.expect("Failed to create layout");
63+
let wrkmem = alloc(layout).cast::<c_void>();
5564
let mut out_len = output.capacity();
5665
let err = compress::lzo1x_1_compress(
5766
input.as_ptr(),
@@ -62,7 +71,7 @@ pub fn compress(input: &[u8], output: &mut Vec<u8>) -> Result<(), LzoError> {
6271
);
6372

6473
output.set_len(out_len);
65-
libc::free(wrkmem);
74+
dealloc(wrkmem.cast::<u8>(), layout);
6675
let res = mem::transmute::<i32, LzoError>(err);
6776
if res == LzoError::Ok {
6877
Ok(())
@@ -77,9 +86,14 @@ pub fn compress(input: &[u8], output: &mut Vec<u8>) -> Result<(), LzoError> {
7786
///
7887
/// # Errors
7988
/// [`LzoError`] if an error occurs
89+
///
90+
/// # Panics
91+
/// If the layout creation fails
8092
pub fn compress_to_slice<'a>(in_: &[u8], out: &'a mut [u8]) -> Result<&'a mut [u8], LzoError> {
8193
unsafe {
82-
let wrkmem = libc::malloc(LZO1X_MEM_COMPRESS);
94+
let layout = Layout::from_size_align(LZO1X_MEM_COMPRESS, std::mem::align_of::<u8>())
95+
.expect("Failed to create layout");
96+
let wrkmem = alloc(layout).cast::<std::ffi::c_void>();
8397
let mut out_len = out.len();
8498
let err = compress::lzo1x_1_compress(
8599
in_.as_ptr(),
@@ -88,7 +102,7 @@ pub fn compress_to_slice<'a>(in_: &[u8], out: &'a mut [u8]) -> Result<&'a mut [u
88102
&raw mut out_len,
89103
wrkmem,
90104
);
91-
libc::free(wrkmem);
105+
dealloc(wrkmem.cast::<u8>(), layout);
92106
let res = mem::transmute::<i32, LzoError>(err);
93107
if res == LzoError::Ok {
94108
Ok(slice::from_raw_parts_mut(out.as_mut_ptr(), out_len))
@@ -143,12 +157,12 @@ fn compress_and_back() {
143157
let size = mem::size_of_val(&data[0]) * data.len();
144158
let dst_len: usize = worst_compress(size);
145159
let mut v = Vec::with_capacity(dst_len);
146-
let dst = libc::malloc(dst_len);
160+
let dst = alloc(Layout::from_size_align(dst_len, mem::align_of::<u8>()).unwrap());
147161
let dst = slice::from_raw_parts_mut(dst.cast::<u8>(), dst_len);
148162
let dst = compress_to_slice(&data, dst).unwrap();
149163
compress(&data, &mut v).unwrap();
150164

151-
let dec_dst = libc::malloc(size);
165+
let dec_dst = alloc(Layout::from_size_align(size, mem::align_of::<u8>()).unwrap());
152166
let dec_dst = slice::from_raw_parts_mut(dec_dst.cast::<u8>(), size);
153167
let result = decompress_to_slice(dst, dec_dst).unwrap();
154168
assert!(result.len() == size);

libs/paa/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "hemtt-paa"
33
version = "1.0.1"
44
edition = "2024"
5-
description = "An PAA library for hemtt"
5+
description = "A PAA library for hemtt"
66
license = "GPL-2.0"
77

88
[lints]

libs/paa/src/wasm.rs

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,12 @@ use js_sys::Uint8Array;
44
use wasm_bindgen::prelude::*;
55

66
#[wasm_bindgen]
7-
extern "C" {
8-
// Use `js_namespace` here to bind `console.log(..)` instead of just
9-
// `log(..)`
10-
#[wasm_bindgen(js_namespace = console)]
11-
fn log(s: &str);
12-
13-
// The `console.log` is quite polymorphic, so we can bind it with multiple
14-
// signatures. Note that we need to use `js_name` to ensure we always call
15-
// `log` in JS.
16-
#[wasm_bindgen(js_namespace = console, js_name = log)]
17-
fn log_u32(a: u32);
18-
19-
// Multiple arguments too!
20-
#[wasm_bindgen(js_namespace = console, js_name = log)]
21-
fn log_many(a: &str, b: &str);
22-
}
23-
24-
#[wasm_bindgen]
25-
pub struct ImageResult {
7+
pub struct FromPaaResult {
268
data: std::rc::Rc<std::cell::RefCell<Vec<u8>>>,
279
}
2810

2911
#[wasm_bindgen]
30-
impl ImageResult {
12+
impl FromPaaResult {
3113
#[wasm_bindgen(constructor)]
3214
pub fn new(s: &Uint8Array) -> Self {
3315
let bytes = s.to_vec();
@@ -53,3 +35,54 @@ impl ImageResult {
5335
self.data.clone().borrow().len() as u32
5436
}
5537
}
38+
39+
#[cfg(feature = "generate")]
40+
use image::GenericImageView;
41+
42+
#[cfg(feature = "generate")]
43+
#[wasm_bindgen]
44+
pub struct ToPaaResult {
45+
data: std::rc::Rc<std::cell::RefCell<Vec<u8>>>,
46+
format: String,
47+
}
48+
49+
#[cfg(feature = "generate")]
50+
#[wasm_bindgen]
51+
impl ToPaaResult {
52+
#[wasm_bindgen(constructor)]
53+
pub fn new(s: &Uint8Array) -> Self {
54+
let bytes = s.to_vec();
55+
let img = image::load_from_memory(&bytes).expect("Failed to load image from memory");
56+
let (width, height) = img.dimensions();
57+
let format = if !height.is_power_of_two() || !width.is_power_of_two() {
58+
crate::PaXType::ARGB8
59+
} else {
60+
let has_transparency = img.pixels().any(|p| p.2[3] < 255);
61+
if has_transparency {
62+
crate::PaXType::DXT5
63+
} else {
64+
crate::PaXType::DXT1
65+
}
66+
};
67+
let paa = crate::Paa::from_dynamic(&img, format).expect("Failed to create PAA from image");
68+
let mut buffer = Cursor::new(Vec::new());
69+
paa.write(&mut buffer).expect("Failed to write PAA");
70+
Self {
71+
data: std::rc::Rc::new(std::cell::RefCell::from(buffer.into_inner())),
72+
format: format.to_string(),
73+
}
74+
}
75+
76+
pub fn data_ptr(&self) -> *const u8 {
77+
self.data.clone().borrow().as_ptr()
78+
}
79+
80+
#[allow(clippy::cast_possible_truncation)]
81+
pub fn data_len(&self) -> u32 {
82+
self.data.clone().borrow().len() as u32
83+
}
84+
85+
pub fn format(&self) -> String {
86+
self.format.clone()
87+
}
88+
}

0 commit comments

Comments
 (0)