Add more dithering options

This commit is contained in:
Joscha 2025-03-18 20:05:23 +01:00
parent 618f298cc6
commit c4c6887603
4 changed files with 47 additions and 15 deletions

View file

@ -7,12 +7,16 @@ const { disabled, error, makeRequest } = useApiRequest();
const form = useTemplateRef<HTMLFormElement>("form"); const form = useTemplateRef<HTMLFormElement>("form");
const number = ref<number>(); const number = ref<number>();
const dither = ref(true);
const bright = ref(false);
const feed = ref(true); const feed = ref(true);
function submit() { function submit() {
const data = new URLSearchParams(); const data = new URLSearchParams();
if (typeof number.value === "number") if (typeof number.value === "number")
data.append("number", number.value.toFixed()); data.append("number", number.value.toFixed());
data.append("dither", String(dither.value));
data.append("bright", String(bright.value));
data.append("feed", String(feed.value)); data.append("feed", String(feed.value));
void makeRequest("api/xkcd", data); void makeRequest("api/xkcd", data);
} }
@ -33,7 +37,18 @@ function submit() {
/> />
</label> </label>
<div class="wide">
<label><input v-model="dither" type="checkbox" :disabled /> Dither</label>
<label
><input
v-model="bright"
type="checkbox"
:disabled="disabled || !dither"
/>
Bright</label
>
<label><input v-model="feed" type="checkbox" :disabled /> Feed</label> <label><input v-model="feed" type="checkbox" :disabled /> Feed</label>
</div>
<button :disabled>Print</button> <button :disabled>Print</button>
<CError :message="error" /> <CError :message="error" />

View file

@ -2,5 +2,6 @@
"number": 3064, "number": 3064,
"title": "Lungfish", "title": "Lungfish",
"alt": "I know having so many base pairs makes rebasing complicated, but you're in Bilateria, so shouldn't you at LEAST be better at using git head?", "alt": "I know having so many base pairs makes rebasing complicated, but you're in Bilateria, so shouldn't you at LEAST be better at using git head?",
"dither": false,
"feed": false "feed": false
} }

View file

@ -9,14 +9,18 @@
#text(size: 32pt, data.title) #text(size: 32pt, data.title)
] ]
// If the image is an odd number of pixels wide, we need to add an extra row of #if data.dither {
// pixels (in this case, on the right) to ensure that the image pixels fall on // If the image is an odd number of pixels wide, we need to add an extra row
// screen pixels. // of pixels (in this case, on the right) to ensure that the image pixels fall
#context { // on screen pixels.
context {
let img = image("image.png") let img = image("image.png")
let width = measure(img).width let width = measure(img).width
let additional = 2pt * calc.fract(width.pt() / 2) let additional = 2pt * calc.fract(width.pt() / 2)
align(center, stack(dir: ltr, img, h(additional))) align(center, stack(dir: ltr, img, h(additional)))
}
} else {
image("image.png", width: lib.width)
} }
#align(center, data.alt) #align(center, data.alt)

View file

@ -24,12 +24,15 @@ struct Data {
number: u32, number: u32,
title: String, title: String,
alt: String, alt: String,
dither: bool,
feed: bool, feed: bool,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct FormData { pub struct FormData {
pub number: Option<u32>, pub number: Option<u32>,
pub dither: Option<bool>,
pub bright: Option<bool>,
pub feed: Option<bool>, pub feed: Option<bool>,
} }
@ -46,20 +49,29 @@ pub async fn post(server: State<Server>, Form(form): Form<FormData>) -> somehow:
let info = client.get(url).send().await?.json::<ComicInfo>().await?; let info = client.get(url).send().await?.json::<ComicInfo>().await?;
let image_data = client.get(&info.img).send().await?.bytes().await?; let image_data = client.get(&info.img).send().await?.bytes().await?;
let image = image::load_from_memory(&image_data)?.into_rgba8(); let mut image = image::load_from_memory(&image_data)?.into_rgba8();
let max_width = Some(384);
let max_height = Some(1024);
let image = super::image::dither(image, max_width, max_height, false, "stucki")
.map_err(somehow::Error)?;
let data = Data { let data = Data {
number: info.num, number: info.num,
title: info.title, title: info.title,
alt: info.alt, alt: info.alt,
dither: form.dither.unwrap_or(true),
feed: form.feed.unwrap_or(true), feed: form.feed.unwrap_or(true),
}; };
if data.dither {
let max_width = Some(384);
let max_height = Some(1024);
image = super::image::dither(
image,
max_width,
max_height,
form.bright.unwrap_or(false),
"stucki",
)
.map_err(somehow::Error)?;
}
let mut bytes: Vec<u8> = Vec::new(); let mut bytes: Vec<u8> = Vec::new();
image image
.write_to(&mut Cursor::new(&mut bytes), ImageFormat::Png) .write_to(&mut Cursor::new(&mut bytes), ImageFormat::Png)