Add the GeglOperation code with Bloom and Cartoon to begin with.

This commit is contained in:
Bauke 2024-01-23 13:53:15 +01:00
parent 036bbfb697
commit deba03b83f
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558
3 changed files with 118 additions and 0 deletions

45
gegl/source/lib.rs Normal file
View File

@ -0,0 +1,45 @@
//! # GEGL
//!
//! > **Ad-hoc GEGL data structure library for Rust.**
mod operations;
pub use operations::*;
pub use indexmap::indexmap;
/// Type alias for a [`indexmap::IndexMap`] with static [`str`] keys and
/// [`String`] values. The reason for [`indexmap`] is to preserve insertion
/// order for simpler testing.
pub type GeglData = indexmap::IndexMap<&'static str, String>;
/// The [`GeglOperation`] trait defines a set of common functions for the
/// individual operations to implement so they can be used with the GEGL CLI.
pub trait GeglOperation: Default + std::fmt::Debug {
/// Some GEGL operations will run infinitely unless you limit the buffer in
/// some way, so all operations must indicate whether or not they should be
/// followed by a crop operation.
fn append_crop_operation(&self) -> bool;
/// Creates the parameters for the graph to be used with the GEGL CLI.
fn graph(&self, include_default_values: bool) -> Vec<String> {
let mut graph = vec![self.name().to_string()];
let defaults = Self::default().values();
for (key, value) in self.values() {
if !include_default_values && defaults.get(key) == Some(&value) {
continue;
}
graph.push(format!("{key}={value}"));
}
graph
}
/// Returns the name of the operation, starting with `gegl:`.
fn name(&self) -> &'static str;
/// Returns the set of configured values for this operation.
fn values(&self) -> GeglData;
}

View File

@ -0,0 +1,45 @@
//! Macro-based [`crate::GeglOperation`] struct generator.
/// A macro to generate a struct that implements [`crate::GeglOperation`].
#[macro_export]
macro_rules! gegl_operation {
(
struct_name: $struct_name:ident,
gegl_name: $gegl_name:expr,
append_crop: $append_crop:expr,
values: ($($key:ident: $key_type:ty, $key_default:expr, $key_doc:expr),*,),
) => {
#[doc = concat!(" The `gegl:", $gegl_name, "` operation.")]
#[derive(Debug)]
pub struct $struct_name {
$(
#[doc = concat!(" ", $key_doc)]
pub $key: $key_type,
)*
}
impl Default for $struct_name {
fn default() -> $struct_name {
$struct_name {
$($key: $key_default,)*
}
}
}
impl $crate::GeglOperation for $struct_name {
fn append_crop_operation(&self) -> bool {
$append_crop
}
fn name(&self) -> &'static str {
concat!("gegl:", $gegl_name)
}
fn values(&self) -> $crate::GeglData {
$crate::indexmap! {
$(stringify!($key) => self.$key.to_string(),)*
}
}
}
};
}

View File

@ -0,0 +1,28 @@
//! All supported GEGL operations.
mod generator;
pub use crate::gegl_operation;
gegl_operation!(
struct_name: Bloom,
gegl_name: "bloom",
append_crop: false,
values: (
limit_exposure: bool, false, "Don't over-expose highlights.",
radius: f64, 10.0, "Glow radius.",
softness: f64, 25.0, "Glow-area edge softness.",
strength: f64, 50.0, "Glow strength.",
threshold: f64, 50.0, "Glow-area brightness threshold.",
),
);
gegl_operation!(
struct_name: Cartoon,
gegl_name: "cartoon",
append_crop: true,
values: (
mask_radius: f64, 7.0, "The mask radius.",
pct_black: f64, 0.2, "The percentage of black.",
),
);