Skip to content

Commit

Permalink
basic wasm processing working
Browse files Browse the repository at this point in the history
  • Loading branch information
knzai committed Jul 17, 2024
1 parent 2685985 commit 34947d4
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 11 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Including terminal or wasm produces the corresponding binary
### Priority
- [x] ~~gif or png output (half the point of the whole library).~~
- [x] ~~If I use image::DynamicImage there are additional encoders/decoders that will be free~~
- [ ] wasm web based processing app - basic happy path with no options works
- [ ] Zooming/scaling (for png and gui output)
- [ ] Additional EGA planar encodings
- [ ] Map viewing (the other half): using the tile/spritesheets as palettes for larger images in psuedo CGA/EGA form (common in 80s games)
Expand Down
15 changes: 15 additions & 0 deletions src/png.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,18 @@ pub fn output(

img.save(path)
}

pub fn write_to(
bytes: &mut Vec<u8>,
image_data: RawGrid,
palette: ColorPalette,
) -> Result<(), image::ImageError> {
let mut img = RgbImage::new(image_data[0].len() as u32, image_data.len() as u32);

for (x, row) in image_data.iter().enumerate() {
for (y, index) in row.iter().enumerate() {
img.put_pixel(y as u32, x as u32, palette[*index as usize].to_rgb());
}
}
img.write_to(&mut Cursor::new(bytes), image::ImageFormat::Png)
}
34 changes: 23 additions & 11 deletions src/wasm/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
extern crate base64;
use std::collections::HashMap;


use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use gloo::file::callbacks::FileReader;
Expand All @@ -11,6 +10,11 @@ use web_sys::{DragEvent, Event, FileList, HtmlInputElement};
use yew::html::TargetCast;
use yew::{html, Callback, Component, Context, Html};

use cega::color::palette::palette_from_abbr;
use cega::image::Image;
use cega::parser::ParserType;
use cega::png;

struct FileDetails {
name: String,
file_type: String,
Expand Down Expand Up @@ -76,7 +80,7 @@ impl Component for App {
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div id="wrapper">
<p id="title">{ "Upload Your Files To The Cloud" }</p>
<p id="title">{ "Process your image files" }</p>
<label for="file-upload">
<div
id="drop-container"
Expand All @@ -99,7 +103,7 @@ impl Component for App {
<input
id="file-upload"
type="file"
accept="image/*,video/*"
accept="image/*,.bin,.cga,.ega"
multiple={true}
onchange={ctx.link().callback(move |e: Event| {
let input: HtmlInputElement = e.target_unchecked_into();
Expand All @@ -116,17 +120,25 @@ impl Component for App {

impl App {
fn view_file(file: &FileDetails) -> Html {
let src = if file.file_type.contains("image") {
format!(
"data:{};base64,{}",
file.file_type,
STANDARD.encode(&file.data)
)
} else {
let image = Image::new(&file.data, 320, ParserType::CGA);
let palette = palette_from_abbr("cga0");
let mut bytes: Vec<u8> = Vec::new();
let _ = png::write_to(&mut bytes, image.data(), palette.clone());
format!("data:image/png;base64,{}", STANDARD.encode(bytes))
};

html! {
<div class="preview-tile">
<p class="preview-name">{ format!("{}", file.name) }</p>
<div class="preview-media">
if file.file_type.contains("image") {
<img src={format!("data:{};base64,{}", file.file_type, STANDARD.encode(&file.data))} />
} else if file.file_type.contains("video") {
<video controls={true}>
<source src={format!("data:{};base64,{}", file.file_type, STANDARD.encode(&file.data))} type={file.file_type.clone()}/>
</video>
}
<img src={src} />
</div>
</div>
}
Expand All @@ -149,4 +161,4 @@ impl App {

fn main() {
yew::Renderer::<App>::new().render();
}
}

0 comments on commit 34947d4

Please sign in to comment.