#图像处理 #图像 #像素 #处理 #图像格式 #成像 #绘画

picture

一个快速灵活的图像处理库

2 个不稳定版本

0.2.0 2023年3月16日
0.1.0 2022年11月4日

#338 in 图像

Apache-2.0

110KB
2.5K SLoC

picture

一个快速灵活的图像处理库。

警告:wip

这个库仍然是一个 wip。虽然它的基础已经存在(但并不稳定),但它还缺少许多便利性和生活质量的特性——主要与格式相关。

它还需要测试™(非常少)。

待办事项

  • 更好的 & 扩展的图像格式支持(目前非常简陋,仅支持 png 和 qoi)
  • 添加更多的测试
  • 尝试减少不安全块的使用

分形示例

基于 image 库的分形示例

use picture::{formats::png::PngEncoder, prelude::*};
use std::io::Write;

fn main() {
    let (width, height) = (1024, 1024);
    let mut img = Rgb8Img::new(width, height);

    let scalex = 3.0 / width as f32;
    let scaley = 3.0 / height as f32;

    for ((x, y), pixel) in img.pixels_with_coords_mut() {
        let cx = y as f32 * scalex - 1.5;
        let cy = x as f32 * scaley - 1.5;

        let c = num_complex::Complex::new(-0.4, 0.6);
        let mut z = num_complex::Complex::new(cx, cy);

        let mut g = 0;
        while g < 255 && z.norm() <= 2.0 {
            z = z * z + c;
            g += 1;
        }

        *pixel = RGB8 {
            r: ((x * 255) / width) as u8,
            g,
            b: ((y * 255) / height) as u8,
        };
    }

    let encoded = PngEncoder::default().encode(img).unwrap();
    let mut f = std::fs::File::create("frac.png").unwrap();
    f.write_all(&encoded[..]).unwrap();
}

(你可以在 这里 找到这段代码)

不连续可变视图示例

picture 最酷的特性之一是能够对视图有不相交的可变视图。以下示例交换了 ImgBuf 的两个水平半部分,然后保存了结果。

use picture::{
    formats::png::{PngDecoder, PngEncoder, PngImage},
    prelude::*,
};
use std::io::Write;

fn swap<I1, I2, P>(a: &mut I1, b: &mut I2)
where
    I1: ImgViewMut<Pixel = P>,
    I2: ImgViewMut<Pixel = P>,
{
    assert!(a.dimensions() == b.dimensions());
    a.pixels_mut()
        .zip(b.pixels_mut())
        .for_each(|(a, b)| std::mem::swap(a, b));
}

fn main() {
    let colorful = PngDecoder
        .decode_from_path("examples/images/colorful.png")
        .unwrap();

    let PngImage::Rgb(mut colorful) = colorful else {
        unreachable!()
    };

    let (mut a, mut b) = colorful.split_x_at_mut(colorful.width() / 2).unwrap();
    swap(&mut a, &mut b);

    let encoded = PngEncoder::default().encode(colorful).unwrap();
    let mut f = std::fs::File::create("swapped.png").unwrap();
    f.write_all(&encoded[..]).unwrap();
}

(你可以在 这里 也找到这段代码!)

ImgViewMut 特质有许多方法可以获得不相交的可变视图: split_x_at_mutsplit_y_at_mutview_mut_multiple

性能

我编写了一些 基准测试 来比较 pictureimage,但我不是写这些测试的专家——所以请对这些结果持保留态度。基准测试是在我的 ryzen 5 1600 上执行的,使用 lto = "thin"

基准测试 时间
Diff 256x256/Picture/ [377.45 µs 379.36 µs 381.44 µs]
Diff 256x256/Image/ [735.66 µs 744.57 µs 753.50 µs]
Fractal 256x256/Picture/ [8.2667 ms 8.3979 ms 8.5334 ms]
Fractal 256x256/Image/ [9.0005 ms 9.1315 ms 9.2613 ms]
Match 16x16 in 256x256/Picture/ [183.25 ms 184.11 ms 185.00 ms]
Match 16x16 in 256x256/Image/ [188.99 毫秒 190.29 毫秒 191.65 毫秒]
Lancoz 降采样/图片/ [54.864 毫秒 55.451 毫秒 56.069 毫秒]
Lancoz 降采样/图像/ [55.418 毫秒 56.024 毫秒 56.655 毫秒]
Lancoz 上采样/图片/ [396.48 毫秒 401.48 毫秒 406.81 毫秒]
Lancoz 上采样/图像/ [861.12 毫秒 863.81 毫秒 866.49 毫秒]

您可以尝试自己运行这些命令,使用简单的 cargo bench

不安全

这个crate在许多地方使用了unsafe,但我已经尽力让所有代码听起来都很安全——包括在每个unsafe块上方添加SAFETY:注释。然而,这是我第一个包含大量unsafe的大项目,所以如果您发现任何安全性漏洞,请告诉我!

依赖关系

~1.6–2.3MB
~46K SLoC