pub mod animation;
pub mod blur;
pub mod brightness;
pub mod color;
pub mod contrast;
pub mod crop;
pub mod diff;
pub mod draw;
pub mod edge_detect;
pub mod emboss;
pub mod flip;
pub mod grayscale;
pub mod hue_rotate;
pub mod invert;
pub mod orient;
pub mod overlay;
pub mod position;
pub mod resize;
pub mod rotate;
pub mod sharpen;
pub mod smart_crop;
pub mod tilt_shift;
pub mod trim;
#[cfg(feature = "text")]
pub mod text;
use crate::error::Result;
use crate::schema::CommandSchema;
use image::{DynamicImage, Rgba};
use serde::Serialize;
pub(crate) fn blend_pixel(base: &Rgba<u8>, color: &Rgba<u8>, coverage: f32) -> Rgba<u8> {
let ca = (color[3] as f32 / 255.0) * coverage;
let ba = base[3] as f32 / 255.0;
let out_a = ca + ba * (1.0 - ca);
if out_a == 0.0 {
return Rgba([0, 0, 0, 0]);
}
let blend = |cc: u8, bc: u8| -> u8 {
let c = (cc as f32 / 255.0 * ca + bc as f32 / 255.0 * ba * (1.0 - ca)) / out_a;
(c * 255.0).round().clamp(0.0, 255.0) as u8
};
Rgba([
blend(color[0], base[0]),
blend(color[1], base[1]),
blend(color[2], base[2]),
(out_a * 255.0).round().clamp(0.0, 255.0) as u8,
])
}
#[derive(Debug, Clone, Serialize)]
pub struct OperationDescription {
pub operation: String,
pub params: serde_json::Value,
pub description: String,
}
pub trait Operation: Send + Sync {
fn name(&self) -> &str;
fn apply(&self, img: DynamicImage) -> Result<DynamicImage>;
fn describe(&self) -> OperationDescription;
fn schema() -> CommandSchema
where
Self: Sized;
}