brightness adjustment; find closest palette colour; tests
This commit is contained in:
parent
03588c4c55
commit
4bd896f05a
|
@ -6,6 +6,7 @@ import init, {
|
|||
load_game,
|
||||
load_default_game,
|
||||
output,
|
||||
set_brightness,
|
||||
set_dither,
|
||||
set_room_name,
|
||||
} from './pkg/pixsy.js';
|
||||
|
@ -70,6 +71,7 @@ async function run() {
|
|||
const buttonNewGame = el("new");
|
||||
const buttonReset = el("reset");
|
||||
const checkboxDither = el("dither");
|
||||
const inputBrightness = el("brightness");
|
||||
const inputRoomName = el("room-name");
|
||||
const selectPalette = el("palette");
|
||||
const textareaGameDataInput = el("game-data");
|
||||
|
@ -171,12 +173,18 @@ async function run() {
|
|||
|
||||
checkboxDither.addEventListener("change", () => {
|
||||
set_dither(checkboxDither.checked);
|
||||
loadPreview();
|
||||
});
|
||||
|
||||
inputRoomName.addEventListener("change", () => {
|
||||
set_room_name(inputRoomName.value);
|
||||
});
|
||||
|
||||
inputBrightness.addEventListener("input", () => {
|
||||
set_brightness(inputBrightness.value);
|
||||
loadPreview();
|
||||
});
|
||||
|
||||
function addRoom() {
|
||||
console.log(add_room());
|
||||
textareaGameDataOutput.value = output();
|
||||
|
|
124
src/lib.rs
124
src/lib.rs
|
@ -1,3 +1,5 @@
|
|||
#![feature(clamp)]
|
||||
|
||||
use bitsy_parser::game::Game;
|
||||
use bitsy_parser::image::Image;
|
||||
use bitsy_parser::tile::Tile;
|
||||
|
@ -15,6 +17,7 @@ struct State {
|
|||
room_name: Option<String>,
|
||||
palette: Option<String>,
|
||||
dither: bool,
|
||||
brightness: i32,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
|
@ -25,6 +28,7 @@ lazy_static! {
|
|||
room_name: None,
|
||||
palette: None,
|
||||
dither: true,
|
||||
brightness: 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -117,6 +121,12 @@ pub fn set_room_name(room_name: String) {
|
|||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn set_brightness(brightness: i32) {
|
||||
let mut state = STATE.lock().unwrap();
|
||||
state.brightness = brightness;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_palettes() -> String {
|
||||
let state = STATE.lock().unwrap();
|
||||
|
@ -146,15 +156,54 @@ fn image_to_base64(image: &DynamicImage) -> String {
|
|||
format!("data:image/png;base64,{}", base64::encode(&bytes))
|
||||
}
|
||||
|
||||
fn render_preview(image: &DynamicImage) -> DynamicImage {
|
||||
let image = image.clone();
|
||||
let image = image.grayscale();
|
||||
fn colour_difference(compare: image::Rgba<u8>, other: &bitsy_parser::Colour) -> u32 {
|
||||
let diff_red = (compare[0] as i16 - other.red as i16).abs();
|
||||
let diff_green= (compare[1] as i16 - other.green as i16).abs();
|
||||
let diff_blue = (compare[2] as i16 - other.blue as i16).abs();
|
||||
|
||||
(diff_red + diff_green + diff_blue) as u32
|
||||
}
|
||||
|
||||
fn closest_colour(compare: image::Rgba<u8>, colours: &[bitsy_parser::Colour]) -> image::Rgba<u8> {
|
||||
let diff_background = colour_difference(compare, &colours[0]);
|
||||
let diff_foreground = colour_difference(compare, &colours[1]);
|
||||
|
||||
if diff_foreground <= diff_background {
|
||||
image::Rgba::from([colours[1].red, colours[1].green, colours[1].blue, 255])
|
||||
} else {
|
||||
image::Rgba::from([colours[0].red, colours[0].green, colours[0].blue, 255])
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_brightness(pixel: &mut image::Rgba<u8>, state: &State) -> image::Rgba<u8> {
|
||||
pixel[0] = (pixel[0] as i32 + state.brightness).clamp(0, 255) as u8;
|
||||
pixel[1] = (pixel[1] as i32 + state.brightness).clamp(0, 255) as u8;
|
||||
pixel[2] = (pixel[2] as i32 + state.brightness).clamp(0, 255) as u8;
|
||||
|
||||
*pixel
|
||||
}
|
||||
|
||||
fn render_preview(state: &State) -> DynamicImage {
|
||||
let image = state.image.as_ref().unwrap().clone();
|
||||
let mut preview = image.clone();
|
||||
|
||||
// todo dither
|
||||
|
||||
// todo convert to palette colours
|
||||
|
||||
image
|
||||
// get background and foreground colours from palette
|
||||
let colours = &state.game.as_ref().unwrap().palettes
|
||||
.iter()
|
||||
.find(|palette| &palette.id == state.palette.as_ref().unwrap())
|
||||
.unwrap()
|
||||
.colours[0..2];
|
||||
|
||||
for (x, y, mut pixel) in image.pixels() {
|
||||
// is pixel closer to background or foreground?
|
||||
preview.put_pixel(x, y, closest_colour(adjust_brightness(&mut pixel, &state), colours));
|
||||
}
|
||||
|
||||
preview
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
@ -162,7 +211,7 @@ pub fn get_preview() -> String {
|
|||
let state = STATE.lock().unwrap();
|
||||
|
||||
match &state.image.is_some() {
|
||||
true => image_to_base64(&render_preview(state.image.as_ref().unwrap())),
|
||||
true => image_to_base64(&render_preview(&state)),
|
||||
false => "".to_string(),
|
||||
}
|
||||
}
|
||||
|
@ -238,6 +287,7 @@ pub fn output() -> String {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{add_room, load_image, load_default_game, output, get_preview};
|
||||
use image::Rgba;
|
||||
|
||||
#[test]
|
||||
fn image_to_base64() {
|
||||
|
@ -247,6 +297,70 @@ mod test {
|
|||
assert_eq!(output, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colour_difference_none() {
|
||||
let output = crate::colour_difference(
|
||||
Rgba::from([255; 4]),
|
||||
&bitsy_parser::Colour {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
}
|
||||
);
|
||||
assert_eq!(output, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colour_difference_some() {
|
||||
let output = crate::colour_difference(
|
||||
Rgba::from([255; 4]),
|
||||
&bitsy_parser::Colour {
|
||||
red: 254,
|
||||
green: 255,
|
||||
blue: 255
|
||||
}
|
||||
);
|
||||
assert_eq!(output, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colour_difference_some_2() {
|
||||
let output = crate::colour_difference(
|
||||
Rgba::from([254; 4]),
|
||||
&bitsy_parser::Colour {
|
||||
red: 254,
|
||||
green: 255,
|
||||
blue: 254
|
||||
}
|
||||
);
|
||||
assert_eq!(output, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colour_difference_max() {
|
||||
let expected = 255 * 3;
|
||||
|
||||
let output = crate::colour_difference(
|
||||
Rgba::from([0; 4]),
|
||||
&bitsy_parser::Colour {
|
||||
red: 255,
|
||||
green: 255,
|
||||
blue: 255
|
||||
}
|
||||
);
|
||||
assert_eq!(output, expected);
|
||||
|
||||
let output = crate::colour_difference(
|
||||
Rgba::from([255; 4]),
|
||||
&bitsy_parser::Colour {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 0
|
||||
}
|
||||
);
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_palettes() {
|
||||
load_default_game();
|
||||
|
|
Loading…
Reference in New Issue