| Crates.io | plutofilter-rs |
| lib.rs | plutofilter-rs |
| version | 0.4.1 |
| created_at | 2025-11-27 16:56:48.848214+00 |
| updated_at | 2025-12-23 08:49:36.586739+00 |
| description | Port of https://github.com/sammycage/plutofilter to rust |
| homepage | https://docs.rs/plutofilter-rs/0.2.0/plutofilter_rs/ |
| repository | https://github.com/mimanshu-maheshwari/plutofilter-rs.git |
| max_upload_size | |
| id | 1954102 |
| size | 179,285 |
PlutoFilter is a zero-allocation image filter library. A Rust port of the original C library that applies fast, chainable image effects without any dynamic memory allocation. Compatible with SVG and CSS filter semantics, it makes it easy to reproduce visual effects consistently across platforms.
✓ Have a better interface to interact with API. (Design pattern like Builder | Partially Done)
Seeing more usage in older versions;exposed the Surface API's again as in 1st version. Using the
ColorChannelyou can specify how to deserialize the pixel, either asARGB32or asRGBA32use image::ImageResult; #[cfg(feature = "image")] fn main() -> ImageResult<()> { use plutofilter_rs::{ImageEditor, get_resource_path}; let base_file = get_resource_path(&["original_images"], "test-image.jpg"); let editor = ImageEditor::open(&base_file); let output_path = get_resource_path(&["test_output_images", "example"], "test-image.jpg"); editor .color_transform_contrast_inplace(0.97) .color_transform_hue_rotate_inplace(330.0) .color_transform_saturate_inplace(1.11) .save_to(&output_path) } #[cfg(not(feature = "image"))] fn main() -> Result<(), SurfaceError> { use plutofilter_rs::ColorChannel; use plutofilter_rs::Surface; use plutofilter_rs::SurfaceError; let (width, height) = (100, 100); let mut input_image_vec = vec![0xFFAA22; (width * height) as usize]; let mut output_image_vec = vec![0xAAFF22; (width * height) as usize]; let mut input_surface = Surface::make(&mut input_image_vec, width, height, width, Some(ColorChannel::ARGB32))?; // ColorChannel::ARGB32 is default so no need to mention it. let mut output_surface = Surface::make(&mut output_image_vec, width, height, width, None)?; Surface::color_transform_opacity(&mut input_surface, &mut output_surface, 0.5); Ok(()) }
✓ Introduce examples
use image::ImageResult;
use plutofilter_rs::{ImageEditor, get_resource_path};
fn main() -> ImageResult<()> {
let base_file = get_resource_path(&["original_images"], "test-image.jpg");
let editor = ImageEditor::open(&base_file);
let output_path = get_resource_path(&["test_output_images", "example"], "test-image.jpg");
editor
.color_transform_contrast_inplace(0.97)
.color_transform_hue_rotate_inplace(330.0)
.color_transform_saturate_inplace(1.11)
.save_to(&output_path)
}
input.jpg |
output.jpg |
|---|---|
![]() |
![]() |
Applies a Gaussian blur to the input surface using separable convolution. The amount of blur is controlled by the standard deviation along the horizontal and vertical axes. A value of 0 applies no blur.
0x0 |
5x5 |
10x10 |
|---|---|---|
![]() |
![]() |
![]() |
Applies a 5×4 color transformation matrix to each pixel in the input surface. The matrix operates on color and alpha channels, allowing both isolated and cross-channel transformations. The input and output surfaces may be the same for in-place filtering.
const ORIGINAL: [f32;20] = [
1.0, 0.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0
];
const GRAYSCALE: [f32;20] = [
0.2126, 0.7152, 0.0722, 0.0, 0.0,
0.2126, 0.7152, 0.0722, 0.0, 0.0,
0.2126, 0.7152, 0.0722, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0
];
const SEPIA: [f32;20] = [
0.393, 0.769, 0.189, 0.0, 0.0,
0.349, 0.686, 0.168, 0.0, 0.0,
0.272, 0.534, 0.131, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0
];
const CONTRAST: [f32;20] = [
1.75, 0.0, 0.0, 0.0, -0.375,
0.0, 1.75, 0.0, 0.0, -0.375,
0.0, 0.0, 1.75, 0.0, -0.375,
0.0, 0.0, 0.0, 1.0, 0.0
];
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
const ORIGINAL: [f32; 20] = [
1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0,
];
let base_file = get_resource_path(&["original_images"], "zhang-hanyun.jpg");
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform(ORIGINAL);
let output_path =
get_resource_path(&["test_output_images", "color_transform"], "original.png");
editor.save_to(output_path)
}
original |
grayscale |
sepia |
contrast |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Applies a grayscale effect to the input surface, controlled by a blending amount between the original color and fully desaturated grayscale. A value of 0 preserves the original image, while 1 results in complete grayscale.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_grayscale(0.25);
let output_path = "output.png";
editor.save_to(output_path)
}
0 |
0.25 |
0.5 |
0.75 |
1 |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
Applies a sepia tone to the input surface, blending between the original image and a warm, brownish tone. The amount controls the intensity, where 0 leaves the image unchanged and 1 applies full sepia coloration.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_sepia(0.25);
let output_path = "output.png";
editor.save_to(output_path)
}
0 |
0.25 |
0.5 |
0.75 |
1 |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
Adjusts the color saturation of the input surface. The amount controls how vivid or muted the colors become: 1 leaves the image unchanged, values less than 1 reduce saturation toward grayscale, and values greater than 1 enhance the intensity of colors.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_saturate(0.25);
let output_path = "output.png";
editor.save_to(output_path)
}
0 |
0.5 |
1 |
4 |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Adjusts the contrast of the input surface. An amount of 1 leaves the image unchanged, values below 1 reduce contrast, and values above 1 increase it. The image is scaled around the midpoint of the color range.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_contrast(0.25);
let output_path = "output.png";
editor.save_to(output_path)
}
0 |
1 |
1.75 |
|---|---|---|
![]() |
![]() |
![]() |
Adjusts the brightness of the input surface. An amount of 1 preserves the original brightness, values below 1 darken the image, and values above 1 brighten it uniformly across all color channels.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_brightness(0.25);
let output_path = "output.png";
editor.save_to(output_path)
}
0 |
0.5 |
1 |
1.75 |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Adjusts the opacity (alpha) of the input surface. An amount of 1 leaves opacity unchanged, while values between 0 and 1 scale the alpha channel linearly. A value of 0 makes the image fully transparent.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_opacity(0.25);
let output_path = "output.png";
editor.save_to(output_path)
}
0 |
0.25 |
0.5 |
0.75 |
1 |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
Applies a color inversion effect to the input surface. The amount controls the strength of the inversion: 0 leaves the image unchanged, 1 fully inverts the RGB channels, and intermediate values blend between the original and inverted colors.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_invert(0.25);
let output_path = "output.png";
editor.save_to(output_path)
}
0 |
0.25 |
0.5 |
0.75 |
1 |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
Rotates the hue of each pixel in the input surface by the given angle in degrees. The rotation is applied in the RGB color space, preserving luminance and alpha. A value of 0 leaves colors unchanged, while 360 completes a full rotation back to the original.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.color_transform_hue_rotate(180.0);
let output_path = "output.png";
editor.save_to(output_path)
}
0° |
30° |
90° |
180° |
270° |
360° |
|---|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Blends two surfaces using the specified blend mode. The source surface is blended over the backdrop, and the result is written to the output.
use plutofilter_rs::{ImageEditor, get_resource_path, BlendMode};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let blend_image = "blend.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.blend(blend_image, BlendMode::Normal);
let output_path = "output.png";
editor.save_to(output_path)
}
use plutofilter_rs::{CompositeOperator, ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let composite_image = "composite.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.composite(composite_image, CompositeOperator::In);
let output_path = "output.png";
editor.save_to(output_path)
}
Composites two surfaces using a Porter-Duff compositing operator. The source surface is composited over the backdrop using the specified operator. The result is written to the output.
Blends two input surfaces using a flexible arithmetic combination of their color values. The output is based on the colors from both inputs, combined according to the four constants: k1, k2, k3, and k4.
use plutofilter_rs::{ImageEditor, get_resource_path};
use image::ImageResult
fn main() -> ImageResult<()> {
let base_file = "input.png";
let composite_image = "composite.png";
let mut editor = ImageEditor::open(base_file);
editor = editor.composite_arithmatic(composite_image, 0.0, 1.0, 0.0, 1.0);
let output_path = "output.png";
editor.save_to(output_path)
}
| Test 1 | Test 2 | Test 3 | Test 4 |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |