28 个版本
0.6.1 | 2023 年 11 月 3 日 |
---|---|
0.5.4 | 2023 年 6 月 6 日 |
0.5.3 | 2023 年 3 月 7 日 |
0.5.1 | 2022 年 6 月 28 日 |
0.1.0 | 2019 年 12 月 23 日 |
在 图像 中排名第 22
每月下载量 6,933
在 7 个 crate 中使用(直接使用 2 个)
375KB
7.5K SLoC
DCV Color Primitives - dcp
DCV Color Primitives 是一个执行图像颜色模型转换的库。
设计指南
- 了解底层硬件和补充 CPU 扩展集(最高 avx2)
- 支持来自单个缓冲区或多个图像平面的数据
- 支持非紧密打包数据
- 支持大于 4GB 的图像(64 位)
- 支持 ARM(aarch64)[*]
- 支持 WebAssembly[*]
[*]: 补充 CPU 扩展集尚未支持。
图像格式转换
该库目前能够转换以下像素格式
源像素格式 | 目标像素格式 |
---|---|
ARGB | I420, I444, NV12 |
BGR | I420, I444, NV12, RGB |
BGRA | I420, I444, NV12, RGB |
I420 | BGRA, RGBA |
I444 | BGRA, RGBA |
NV12 | BGRA, RGB, RGBA |
RGB | BGRA |
颜色模型
支持的颜色模型包括
- YCbCr,ITU-R 建议BT.601(标准视频系统)
- YCbCr,ITU-R 建议BT.709(CSC 系统)
支持标准范围(0-235)和全范围(0-255)。
要求
- Rust 1.70 及更高版本
Windows
- 安装 rustup: https://rust-lang.net.cn/tools/install
Linux
- 安装 rustup(见 https://forge.rust-lang.org/infra/other-installation-methods.html)
curl https://sh.rustup.rs -sSf | sh
可能需要管理员权限。
构建
在库根目录内打开终端。
为调试体验构建
cargo build
构建优化库
cargo build --release
运行单元测试
cargo test
运行基准测试
cargo bench
高级基准模式。有两个基准脚本
run-bench.ps1
用于 Windowsrun-bench.sh
用于 Linux 和 MacOS
它们通过减少由于以下因素引起的方差,可以获得比cargo bench
更稳定的结果:
- CPU迁移
- 文件系统缓存
- 进程优先级
此外,Linux脚本支持硬件性能计数器,例如,可以输出消耗的CPU周期而不是经过的时间。
Linux示例
./run-bench -c 1 # runs cargo bench and outputs CPU cycles
./run.bench -c 1 -p "/i420" # runs cargo bench, output CPU cycles, filtering tests that contains '/i420'
WebAssembly
安装所需的依赖项
rustup target add wasm32-unknown-unknown
为调试体验构建
cargo build --target wasm32-unknown-unknown
要测试,请确保您已安装wasm-pack。然后
wasm-pack test --node
用法
图像转换
将图像从bgra转换为包含bt601 yuv的单平面nv12格式
use dcv_color_primitives as dcp;
use dcp::{convert_image, ColorSpace, ImageFormat, PixelFormat};
fn main() {
const WIDTH: u32 = 640;
const HEIGHT: u32 = 480;
let src_data = Box::new([0u8; 4 * (WIDTH as usize) * (HEIGHT as usize)]);
let mut dst_data = Box::new([0u8; 3 * (WIDTH as usize) * (HEIGHT as usize) / 2]);
let src_format = ImageFormat {
pixel_format: PixelFormat::Bgra,
color_space: ColorSpace::Rgb,
num_planes: 1,
};
let dst_format = ImageFormat {
pixel_format: PixelFormat::Nv12,
color_space: ColorSpace::Bt601,
num_planes: 1,
};
convert_image(
WIDTH,
HEIGHT,
&src_format,
None,
&[&*src_data],
&dst_format,
None,
&mut [&mut *dst_data],
);
}
错误处理
库函数返回一个描述操作结果的Result
结果 | 描述 |
---|---|
Ok(()) |
操作成功 |
Err(ErrorKind::InvalidValue) |
一个或多个参数对调用函数无效 |
Err(ErrorKind::InvalidOperation) |
调用函数不支持参数组合 |
Err(ErrorKind::NotEnoughData) |
一个或多个缓冲区大小不正确 |
在以下示例中,result
将匹配Err(ErrorKind::InvalidValue)
,因为ColorSpace::Bt709
颜色空间与PixelFormat::Bgra
不兼容
use dcv_color_primitives as dcp;
use dcp::{convert_image, ColorSpace, ErrorKind, ImageFormat, PixelFormat};
fn main() {
const WIDTH: u32 = 640;
const HEIGHT: u32 = 480;
let src_data = Box::new([0u8; 4 * (WIDTH as usize) * (HEIGHT as usize)]);
let mut dst_data = Box::new([0u8; 3 * (WIDTH as usize) * (HEIGHT as usize) / 2]);
let src_format = ImageFormat {
pixel_format: PixelFormat::Bgra,
color_space: ColorSpace::Bt709,
num_planes: 1,
};
let dst_format = ImageFormat {
pixel_format: PixelFormat::Nv12,
color_space: ColorSpace::Bt601,
num_planes: 1,
};
let status = convert_image(
WIDTH,
HEIGHT,
&src_format,
None,
&[&*src_data],
&dst_format,
None,
&mut [&mut *dst_data],
);
match status {
Err(ErrorKind::InvalidValue) => (),
_ => panic!("Expected ErrorKind::InvalidValue"),
}
}
更好的是,您可能希望将错误传播到调用函数或与其他错误类型混合
use dcv_color_primitives as dcp;
use dcp::{convert_image, ColorSpace, ImageFormat, PixelFormat};
use std::error;
fn main() -> Result<(), Box<dyn error::Error>> {
const WIDTH: u32 = 640;
const HEIGHT: u32 = 480;
let src_data = Box::new([0u8; 4 * (WIDTH as usize) * (HEIGHT as usize)]);
let mut dst_data = Box::new([0u8; 3 * (WIDTH as usize) * (HEIGHT as usize) / 2]);
let src_format = ImageFormat {
pixel_format: PixelFormat::Bgra,
color_space: ColorSpace::Bt709,
num_planes: 1,
};
let dst_format = ImageFormat {
pixel_format: PixelFormat::Nv12,
color_space: ColorSpace::Bt601,
num_planes: 1,
};
convert_image(
WIDTH,
HEIGHT,
&src_format,
None,
&[&*src_data],
&dst_format,
None,
&mut [&mut *dst_data],
)?;
Ok(())
}
缓冲区大小计算
到目前为止,缓冲区的大小是根据图像像素格式和尺寸来确定的;然而,您可以使用一个函数来计算存储给定格式和尺寸的图像所需的字节数
use dcv_color_primitives as dcp;
use dcp::{get_buffers_size, ColorSpace, ImageFormat, PixelFormat};
use std::error;
fn main() -> Result<(), Box<dyn error::Error>> {
const WIDTH: u32 = 640;
const HEIGHT: u32 = 480;
const NUM_PLANES: u32 = 1;
let format = ImageFormat {
pixel_format: PixelFormat::Bgra,
color_space: ColorSpace::Rgb,
num_planes: NUM_PLANES,
};
let sizes: &mut [usize] = &mut [0usize; NUM_PLANES as usize];
get_buffers_size(WIDTH, HEIGHT, &format, None, sizes)?;
let buffer: Vec<_> = vec![0u8; sizes[0]];
// Do something with buffer
// --snip--
Ok(())
}
图像平面
如果您的数据分散在多个缓冲区中,这些缓冲区不一定连续,您可以提供图像平面
use dcv_color_primitives as dcp;
use dcp::{convert_image, get_buffers_size, ColorSpace, ImageFormat, PixelFormat};
use std::error;
fn main() -> Result<(), Box<dyn error::Error>> {
const WIDTH: u32 = 640;
const HEIGHT: u32 = 480;
const NUM_SRC_PLANES: u32 = 2;
const NUM_DST_PLANES: u32 = 1;
let src_format = ImageFormat {
pixel_format: PixelFormat::Nv12,
color_space: ColorSpace::Bt709,
num_planes: NUM_SRC_PLANES,
};
let src_sizes: &mut [usize] = &mut [0usize; NUM_SRC_PLANES as usize];
get_buffers_size(WIDTH, HEIGHT, &src_format, None, src_sizes)?;
let src_y: Vec<_> = vec![0u8; src_sizes[0]];
let src_uv: Vec<_> = vec![0u8; src_sizes[1]];
let dst_format = ImageFormat {
pixel_format: PixelFormat::Bgra,
color_space: ColorSpace::Rgb,
num_planes: NUM_DST_PLANES,
};
let dst_sizes: &mut [usize] = &mut [0usize; NUM_DST_PLANES as usize];
get_buffers_size(WIDTH, HEIGHT, &dst_format, None, dst_sizes)?;
let mut dst_rgba: Vec<_> = vec![0u8; dst_sizes[0]];
convert_image(
WIDTH,
HEIGHT,
&src_format,
None,
&[&src_y[..], &src_uv[..]],
&dst_format,
None,
&mut [&mut dst_rgba[..]],
)?;
Ok(())
}
Stride支持
为了考虑非紧密打包的数据,您可以提供图像Stride
use dcv_color_primitives as dcp;
use dcp::{convert_image, get_buffers_size, ColorSpace, ImageFormat, PixelFormat};
use std::error;
fn main() -> Result<(), Box<dyn error::Error>> {
const WIDTH: u32 = 640;
const HEIGHT: u32 = 480;
const NUM_SRC_PLANES: u32 = 1;
const NUM_DST_PLANES: u32 = 2;
const RGB_STRIDE: usize = 4 * (((3 * (WIDTH as usize)) + 3) / 4);
let src_format = ImageFormat {
pixel_format: PixelFormat::Bgr,
color_space: ColorSpace::Rgb,
num_planes: NUM_SRC_PLANES,
};
let src_strides: &[usize] = &[RGB_STRIDE];
let src_sizes: &mut [usize] = &mut [0usize; NUM_SRC_PLANES as usize];
get_buffers_size(WIDTH, HEIGHT, &src_format, Some(src_strides), src_sizes)?;
let src_rgba: Vec<_> = vec![0u8; src_sizes[0]];
let dst_format = ImageFormat {
pixel_format: PixelFormat::Nv12,
color_space: ColorSpace::Bt709,
num_planes: NUM_DST_PLANES,
};
let dst_sizes: &mut [usize] = &mut [0usize; NUM_DST_PLANES as usize];
get_buffers_size(WIDTH, HEIGHT, &dst_format, None, dst_sizes)?;
let mut dst_y: Vec<_> = vec![0u8; dst_sizes[0]];
let mut dst_uv: Vec<_> = vec![0u8; dst_sizes[1]];
convert_image(
WIDTH,
HEIGHT,
&src_format,
Some(src_strides),
&[&src_rgba[..]],
&dst_format,
None,
&mut [&mut dst_y[..], &mut dst_uv[..]],
)?;
Ok(())
}
有关更多信息,请参阅文档。
C绑定
DCV颜色原语提供C绑定。默认构建将自动生成静态库。
为了在您的应用程序库中包含DCV颜色原语,您需要
- 静态链接到dcv_color_primitives
- 对于Windows,链接到ws2_32.lib、userenv.lib、bcrypt.lib和ntdll.lib
- 对于Linux,链接到libdl和libm
API与Rust略有不同。请检查dcv_color_primitives.h以获取示例和更多信息。
提供了一个meson构建系统,用于构建静态库并将其与包含文件和pkgconfig文件一起安装。还有一些用C编写的单元测试,以添加一些绑定覆盖率。以下提供了最小指令,有关更多信息,请参阅meson的帮助文档
-
Windows 需要Visual Studio。至少需要以下包:
- MSBuild
- MSVC - C++构建工具
- Windows 10 SDK
安装meson,您可以选择以下方法之一
- 使用meson msi安装程序
- 从https://github.com/mesonbuild/meson/releases下载
- 安装Meson和Ninja
- 通过pip安装meson
- 下载并安装python3: https://pythonlang.cn/downloads/
- 安装meson和ninja
pip install meson ninja
注意:最低要求的meson版本是1.0.0。
所有构建命令都必须在VS(x86或x64取决于您要构建的平台)的本地工具命令提示符中发出
-
Linux 以下示例针对Ubuntu
#install python3 apt install python3 #install meson. See https://mesonbuild.com/Getting-meson.html for details or if you want to install through pip. apt install meson #install ninja apt install ninja-build
可能需要管理员权限。
-
构建 将目录移动到库根目录
cd `dcv_color_primitives_root_dir`
然后
meson setup --buildtype release builddir ninja -C builddir
-
运行测试
cd builddir meson test -t 10
需要10倍的超时时间因子,因为一些测试的完成时间超过了默认的30秒。
-
安装
ninja -C builddir install
许可证
此库受MIT-0许可证的许可。请参阅LICENSE文件。
依赖项
~220KB