mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-14 14:22:39 +00:00
Use shared image codecs for CLI previews
This commit is contained in:
3 files changed
+13
-10
No files matched your search
Generated
+1
@@ -1719,6 +1719,7 @@ name = "designcraft-cli"
|
||||
version = "0.20.1"
|
||||
dependencies = [
|
||||
"craft-file-formats",
|
||||
"craft-image-codecs",
|
||||
"designcraft-color",
|
||||
"designcraft-compose",
|
||||
"designcraft-doc",
|
||||
|
||||
@@ -23,5 +23,6 @@ designcraft-format = { workspace = true }
|
||||
designcraft-pdf = { workspace = true }
|
||||
designcraft-mcp = { workspace = true }
|
||||
craft-file-formats = { workspace = true }
|
||||
craft-image-codecs = { workspace = true }
|
||||
image = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
@@ -319,16 +319,17 @@ fn names_the_same_file(input: &std::path::Path, out: &std::path::Path) -> bool {
|
||||
/// as it is; it is decoded anyway, so a broken one is an error rather than an unreadable thumbnail.
|
||||
fn fit_png(png: Vec<u8>, size: Option<u32>) -> Result<Vec<u8>, String> {
|
||||
// The preview comes from the file: it may claim any size.
|
||||
let mut limits = image::Limits::default();
|
||||
limits.max_image_width = Some(4096);
|
||||
limits.max_image_height = Some(4096);
|
||||
let mut reader = image::ImageReader::with_format(std::io::Cursor::new(&png), image::ImageFormat::Png);
|
||||
reader.limits(limits);
|
||||
let img = reader.decode().map_err(|e| e.to_string())?;
|
||||
let Some(size) = size.filter(|s| img.width().max(img.height()) > *s) else { return Ok(png) };
|
||||
let mut out = std::io::Cursor::new(Vec::new());
|
||||
img.resize(size, size, image::imageops::FilterType::Triangle).write_to(&mut out, image::ImageFormat::Png).map_err(|e| e.to_string())?;
|
||||
Ok(out.into_inner())
|
||||
let info = craft_image_codecs::inspect_raster(&png).map_err(|e| e.to_string())?.ok_or("invalid PNG preview")?;
|
||||
if info.width > 4096 || info.height > 4096 {
|
||||
return Err("preview is larger than 4096 pixels".into());
|
||||
}
|
||||
let decoded = craft_image_codecs::decode(&png).map_err(|e| e.to_string())?;
|
||||
let Some(size) = size.filter(|s| decoded.width().max(decoded.height()) > *s) else { return Ok(png) };
|
||||
let rgba = image::RgbaImage::from_raw(decoded.width(), decoded.height(), decoded.to_rgba8()).ok_or("invalid PNG pixel data")?;
|
||||
let resized = image::DynamicImage::ImageRgba8(rgba).resize(size, size, image::imageops::FilterType::Triangle).to_rgba8();
|
||||
let encoded = craft_image_codecs::Image::from_u8(resized.width(), resized.height(), craft_image_codecs::ChannelLayout::Rgba, resized.into_raw())
|
||||
.map_err(|e| e.to_string())?;
|
||||
craft_image_codecs::encode(&encoded, craft_image_codecs::Format::Png, &Default::default()).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// `mcp` (headless, in-process engine) or `mcp --connect PORT|HOST:PORT` (drive a running app
|
||||
|
||||
Reference in new issue
Block a user