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

@@ -69,6 +69,7 @@ impl DocumentNode {
(ProtoNodeInput::Node(node_id, lambda), ConstructionArgs::Nodes(vec![]))
}
NodeInput::Network(ty) => (ProtoNodeInput::Network(ty), ConstructionArgs::Nodes(vec![])),
NodeInput::ShortCircut(ty) => (ProtoNodeInput::ShortCircut(ty), ConstructionArgs::Nodes(vec![])),
};
assert!(!self.inputs.iter().any(|input| matches!(input, NodeInput::Network(_))), "recieved non resolved parameter");
assert!(
@@ -121,12 +122,52 @@ impl DocumentNode {
}
}
/// Represents the possible inputs to a node.
/// # ShortCircuting
/// In Graphite nodes are functions and by default, these are composed into a single function
/// by inserting Compose nodes.
///
///
///
///
/// ┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐
/// │ │◄──────────────┤ │◄───────────────┤ │
/// │ A │ │ B │ │ C │
/// │ ├──────────────►│ ├───────────────►│ │
/// └─────────────────┘ └──────────────────┘ └──────────────────┘
///
///
///
/// This is equivalent to calling c(b(a(input))) when evaluating c with input ( `c.eval(input)`)
/// But sometimes we might want to have a little more control over the order of execution.
/// This is why we allow nodes to opt out of the input forwarding by consuming the input directly.
///
///
///
/// ┌─────────────────────┐ ┌─────────────┐
/// │ │◄───────────────┤ │
/// │ Cache Node │ │ C │
/// │ ├───────────────►│ │
/// ┌──────────────────┐ ├─────────────────────┤ └─────────────┘
/// │ │◄──────────────┤ │
/// │ A │ │ * Cached Node │
/// │ ├──────────────►│ │
/// └──────────────────┘ └─────────────────────┘
///
///
///
///
/// In this case the Cache node actually consumes it's input and then manually forwards it to it's parameter
/// Node. This is necessary because the Cache Node needs to short-circut the actual node evaluation
#[derive(Debug, Clone, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum NodeInput {
Node { node_id: NodeId, output_index: usize, lambda: bool },
Value { tagged_value: crate::document::value::TaggedValue, exposed: bool },
Network(Type),
// A short circuting input represents an input that is not resolved through function composition but
// actually consuming the provided input instead of passing it to its predecessor
ShortCircut(Type),
}
impl NodeInput {
@@ -153,6 +194,7 @@ impl NodeInput {
NodeInput::Node { .. } => true,
NodeInput::Value { exposed, .. } => *exposed,
NodeInput::Network(_) => false,
NodeInput::ShortCircut(_) => false,
}
}
pub fn ty(&self) -> Type {
@@ -160,6 +202,7 @@ impl NodeInput {
NodeInput::Node { .. } => unreachable!("ty() called on NodeInput::Node"),
NodeInput::Value { tagged_value, .. } => tagged_value.ty(),
NodeInput::Network(ty) => ty.clone(),
NodeInput::ShortCircut(ty) => ty.clone(),
}
}
}
@@ -397,6 +440,7 @@ impl NodeNetwork {
self.inputs[index] = *network_input;
}
}
NodeInput::ShortCircut(_) => (),
}
}
node.implementation = DocumentNodeImplementation::Unresolved("graphene_core::ops::IdNode".into());