Files
Graphite/node-graph/gstd/src/quantization.rs
Dennis Kobert 4bd9fbd073 Make the dynamic node graph execution asynchronous (#1218)
* Make node graph execution async

Make node macro generate async node implementations

Start propagating async through the node system

Async checkpoint

Make Any<'i> Send + Sync

Determine node io type using panic node

Fix types for raster_node macro

Finish porting node registry?

Fix lifetime errors

Remove Send + Sync requirements and start making node construction async

Async MVP

Fix tests

Clippy fix

* Fix nodes

* Simplify lifetims for node macro + make node macro more modular

* Reenable more nodes

* Fix pasting images

* Remove http test from brush node

* Fix output type for cache node

* Fix types for let scope

* Fix formatting
2023-05-27 11:48:57 +02:00

60 lines
2.0 KiB
Rust

use dyn_any::{DynAny, StaticType};
use graphene_core::quantization::*;
use graphene_core::raster::{Color, ImageFrame};
use graphene_core::Node;
/// The `GenerateQuantizationNode` encodes the brightness of each channel of the image as an integer number
/// signified by the samples parameter. This node is used to asses the loss of visual information when
/// quantizing the image using different fit functions.
pub struct GenerateQuantizationNode<N, M> {
samples: N,
function: M,
}
#[node_macro::node_fn(GenerateQuantizationNode)]
fn generate_quantization_fn(image_frame: ImageFrame<Color>, samples: u32, function: u32) -> [Quantization; 4] {
let image = image_frame.image;
let len = image.data.len().min(10000);
let mut channels: Vec<_> = (0..4).map(|_| Vec::with_capacity(image.data.len())).collect();
image
.data
.iter()
.enumerate()
.filter(|(i, _)| i % (image.data.len() / len) == 0)
.map(|(_, x)| vec![x.r() as f64, x.g() as f64, x.b() as f64, x.a() as f64])
.for_each(|x| x.into_iter().enumerate().for_each(|(i, value)| channels[i].push(value)));
let quantization: Vec<Quantization> = channels.into_iter().map(|x| generate_quantization_per_channel(x, samples)).collect();
core::array::from_fn(|i| quantization[i].clone())
}
fn generate_quantization_per_channel(data: Vec<f64>, samples: u32) -> Quantization {
let mut dist = autoquant::integrate_distribution(data);
autoquant::drop_duplicates(&mut dist);
let dist = autoquant::normalize_distribution(dist.as_slice());
let max = dist.last().unwrap().0;
/*let linear = Box::new(autoquant::SimpleFitFn {
function: move |x| x / max,
inverse: move |x| x * max,
name: "identity",
});*/
let linear = Quantization {
fn_index: 0,
a: max as f32,
b: 0.,
c: 0.,
d: 0.,
};
let log_fit = autoquant::models::OptimizedLog::new(dist, samples as u64);
let parameters = log_fit.parameters();
let log_fit = Quantization {
fn_index: 1,
a: parameters[0] as f32,
b: parameters[1] as f32,
c: parameters[2] as f32,
d: parameters[3] as f32,
};
log_fit
}