Skip to content

Commit 6237fb4

Browse files
committed
communicate with web assembly
1 parent 4a739a1 commit 6237fb4

3 files changed

Lines changed: 65 additions & 20 deletions

File tree

index.html

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,15 @@ <h1>Offline Image Converter</h1>
9292

9393
<input type="file" id="fileInput" accept="image/*" />
9494

95-
<button id="convertBtn" onclick="convert"></button>
95+
<select id="outputType">
96+
<option value="png">PNG</option>
97+
<option value="jpeg">JPEG</option>
98+
<option value="image/webp">WEBP</option>
99+
<option value="image/bmp">BMP</option>
100+
<option value="image/tiff">TIFF</option>
101+
</select>
102+
103+
<button id="convertBtn" onclick="convert()">Convert</button>
96104

97105
<div id="loader" style="display: none;">
98106
<span class="loader"></span>
@@ -153,7 +161,7 @@ <h1>Offline Image Converter</h1>
153161

154162
let workerReady = false;
155163
worker.onmessage = (event) => {
156-
const { type, pdf, message, fileName} = event.data;
164+
const { type, imageData, message, fileName, outputType} = event.data;
157165
if (type === "ready") {
158166
workerReady = true;
159167
return;
@@ -165,13 +173,45 @@ <h1>Offline Image Converter</h1>
165173
}
166174

167175
if (type === "done") {
168-
downloadPdf(pdf, fileName);
176+
downloadPdf(imageData, fileName, outputType);
169177
} else if (type === "error") {
170178
showError(message);
171179
}
172180
hideLoader();
173181
};
174182

183+
const fileInput = document.getElementById('fileInput');
184+
const outputTypeElement = document.getElementById("outputType");
185+
async function convert() {
186+
const file = fileInput.files[0];
187+
if (!file) {
188+
showError("Select a file before continueing.");
189+
return;
190+
}
191+
192+
if (!workerReady) {
193+
showError("Worker is not ready yet, please wait a moment and try again.");
194+
return;
195+
}
196+
197+
const outputType = outputTypeElement.value;
198+
if (!outputType) {
199+
showError("Select an output type before continueing.");
200+
return;
201+
}
202+
203+
showLoader();
204+
hideError();
205+
206+
// TODO remove dot from filename if present
207+
const fileName = file.name;
208+
const inputType = "png";
209+
const imageData = await file.arrayBuffer();
210+
211+
worker.postMessage({ imageData, fileName, inputType, outputType });
212+
}
213+
window.convert = convert;
214+
175215
</script>
176216
</body>
177217
</html>

src/lib.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,34 @@ fn map_image_err(err: ImageError) -> String {
88
format!("Image processing error: {}", err)
99
}
1010

11-
fn convert(image_data: Vec<u8>, output: ImageFormat) -> Result<Vec<u8>, String> {
11+
fn convert(image_data: Vec<u8>, input: ImageFormat, output: ImageFormat) -> Result<Vec<u8>, String> {
1212
report_progress("Loading image...");
13-
let img = image::load_from_memory(&image_data).map_err(map_image_err)?;
13+
let img = image::load_from_memory_with_format(&image_data, input).map_err(map_image_err)?;
1414
let mut output_data: Vec<u8> = Vec::new();
1515
report_progress("Converting to new format...");
1616
img.write_to(&mut Cursor::new(&mut output_data), output).map_err(map_image_err)?;
1717
report_progress("Completed conversion.");
1818
Ok(output_data)
1919
}
2020

21+
fn str_to_type(s: &str) -> Option<ImageFormat> {
22+
match s.to_lowercase().as_str() {
23+
"png" => Some(ImageFormat::Png),
24+
"jpeg" | "jpg" => Some(ImageFormat::Jpeg),
25+
"gif" => Some(ImageFormat::Gif),
26+
"bmp" => Some(ImageFormat::Bmp),
27+
"ico" => Some(ImageFormat::Ico),
28+
"tiff" => Some(ImageFormat::Tiff),
29+
"webp" => Some(ImageFormat::WebP),
30+
_ => None,
31+
}
32+
}
33+
2134
#[wasm_bindgen]
22-
pub fn convert_exposed(image_data: Vec<u8>, output: String) -> Result<Vec<u8>, String> {
23-
let output = match output.to_lowercase().as_str() {
24-
"png" => ImageFormat::Png,
25-
"jpeg" | "jpg" => ImageFormat::Jpeg,
26-
"gif" => ImageFormat::Gif,
27-
"bmp" => ImageFormat::Bmp,
28-
"ico" => ImageFormat::Ico,
29-
"tiff" => ImageFormat::Tiff,
30-
"webp" => ImageFormat::WebP,
31-
_ => return Err("Unsupported output format".to_string()),
32-
} ;
33-
convert(image_data, output)
35+
pub fn convert_exposed(image_data: Vec<u8>, input: String, output: String) -> Result<Vec<u8>, String> {
36+
let input = str_to_type(&input).ok_or_else(|| format!("Unsupported input format: {}", input))?;
37+
let output = str_to_type(&output).ok_or_else(|| format!("Unsupported output format: {}", output))?;
38+
convert(image_data, input, output)
3439
}
3540

3641
fn report_progress(message: &str) {

worker.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ onmessage = async (event) => {
1616
return;
1717
}
1818

19-
const { imageData, fileName, outputType } = event.data;
19+
const { imageData, fileName, inputType, outputType } = event.data;
2020

2121
try {
22-
const convertedImage = convert_exposed(imageData, outputType);
22+
const convertedImage = convert_exposed(imageData, inputType, outputType);
2323

24-
postMessage({ type: "done", imageData: convertedImage, fileName }, [mergedPdf.buffer]);
24+
postMessage({ type: "done", imageData: convertedImage, fileName, outputType }, [mergedPdf.buffer]);
2525
} catch (err) {
2626
if (err instanceof WebAssembly.RuntimeError) {
2727
postMessage({ type: "error", message: "Unexpected WASM exception: " + err.message });

0 commit comments

Comments
 (0)