mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 23:38:06 +08:00
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:
@@ -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.);
|
||||
|
||||
|
||||
@@ -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(),
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user