Downscale Images to document resolution (#1077)

* Add DownscaleNode

* Add lambda (call argument) input type + fix caching

* Add comment explaining Lambda input

* Automatically insert cache node after downscale node

* Implement sparse hashing of images
This commit is contained in:
Dennis Kobert
2023-03-15 12:49:56 +01:00
committed by GitHub
parent a14af91031
commit d8de17b96f
13 changed files with 209 additions and 224 deletions

View File

@@ -12,7 +12,10 @@ license = "Apache-2.0"
[features]
gpu = ["interpreted-executor/gpu", "graphene-std/gpu", "graphene-core/gpu"]
quantization = ["graphene-std/quantization", "interpreted-executor/quantization"]
quantization = [
"graphene-std/quantization",
"interpreted-executor/quantization",
]
[dependencies]
log = "0.4"
@@ -22,7 +25,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
graphite-proc-macros = { path = "../proc-macros" }
bezier-rs = { path = "../libraries/bezier-rs" }
glam = { version="0.22", features = ["serde"] }
glam = { version = "0.22", features = ["serde"] }
kurbo = { git = "https://github.com/linebender/kurbo.git", features = [
"serde",
] }
@@ -32,7 +35,10 @@ once_cell = "1.13.0" # Remove when `core::cell::OnceCell` is stabilized (<https:
specta.workspace = true
# Node graph
image = { version = "0.24", default-features = false, features = ["bmp"] }
image = { version = "0.24", default-features = false, features = [
"bmp",
"png",
] }
graph-craft = { path = "../node-graph/graph-craft" }
interpreted-executor = { path = "../node-graph/interpreted-executor" }
borrow_stack = { path = "../node-graph/borrow_stack" }

View File

@@ -612,6 +612,9 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
let center_in_viewport = DAffine2::from_translation(viewport_location - ipp.viewport_bounds.top_left);
let center_in_viewport_layerspace = to_parent_folder.inverse() * center_in_viewport;
// Scale the image to fit into a 512x512 box
let image_size = image_size / DVec2::splat((image_size.max_element() / 512.).max(1.));
// Make layer the size of the image
let fit_image_size = DAffine2::from_scale_angle_translation(image_size, 0., image_size / -2.);

View File

@@ -107,7 +107,35 @@ fn static_nodes() -> Vec<DocumentNodeType> {
DocumentNodeType {
name: "Image",
category: "Ignore",
identifier: NodeImplementation::proto("graphene_core::ops::IdNode"),
identifier: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0],
outputs: vec![NodeOutput::new(2, 0)],
nodes: [
DocumentNode {
name: "Downscale".to_string(),
inputs: vec![NodeInput::Network(concrete!(ImageFrame))],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::raster::DownscaleNode")),
metadata: Default::default(),
},
DocumentNode {
name: "Cache".to_string(),
inputs: vec![NodeInput::ShortCircut(concrete!(())), NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::CacheNode")),
metadata: Default::default(),
},
DocumentNode {
name: "Clone".to_string(),
inputs: vec![NodeInput::node(1, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::CloneNode<_>")),
metadata: Default::default(),
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (id as NodeId, node))
.collect(),
..Default::default()
}),
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false)],
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
properties: |_document_node, _node_id, _context| node_properties::string_properties("A bitmap image embedded in this node"),
@@ -422,7 +450,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
0,
DocumentNode {
name: "CacheNode".to_string(),
inputs: vec![NodeInput::Network(concrete!(Image))],
inputs: vec![NodeInput::ShortCircut(concrete!(())), NodeInput::Network(concrete!(ImageFrame))],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::CacheNode")),
metadata: Default::default(),
},

View File

@@ -81,6 +81,7 @@ impl NodeGraphExecutor {
inner_network.outputs[0] = NodeOutput::new(*node_id, *output_index);
break 'outer;
}
NodeInput::ShortCircut(_) => (),
}
}
@@ -92,7 +93,7 @@ impl NodeGraphExecutor {
use image::{ImageBuffer, Rgba};
use std::io::Cursor;
let (result_bytes, width, height) = image.as_flat_u8();
let (result_bytes, width, height) = image.into_flat_u8();
let mut output: ImageBuffer<Rgba<u8>, _> = image::ImageBuffer::from_raw(width, height, result_bytes).ok_or_else(|| "Invalid image size".to_string())?;
if let Some(size) = resize {