Rust翻译计划——image库

本文目录:

  1. 简介
  2. 快速通道
  3. 翻译--image库

1. 简介

Rust这门编程语言魅力非常。奈何在国内风名不显,对于一些已经造好的轮子,却也还是晦涩的英文版。本着学习的目的,加深自身的理解,将逐步将一些使用的Rust库进行自己理解后翻译至此。(ps:名义上是翻译,实际上是自己阅读后的理解,并非逐字翻译,关心原文者,请前往英文原文Orz)

2. 快速通道

所有的翻译文章将集中导航于:Rust常用库翻译计划

3.翻译——image库

Image库github快速通道

库简介

image库是Rust的一个处理图片的库,提供了基础的图片处理以及格式转换等等的对应函数实现。

该库提供的函数的处理对象全是"GenericImage" trait 的实例,并且返回一个ImageBuffer。

关于"GenericImage" trait(待翻译)

关于ImageBuffer(待翻译)

使用方法

在项目的Cargo.toml中加入以下依赖:

[dependencies]
image = "*"

然后在你的代码中引用该库:

extern crate image;

支持的格式

目前该库基本支持市面上大部分的图片格式

  • PNG (encode & decode)
  • JPEG (encode & decode)
  • GIF (encode & decode)
  • BMP (encode & decode)
  • ICO (encode & decode)
  • TIFF (just decode)
  • webp (just decode)
  • PPM (encode & decode)

关于ImageDecoder Trait

所有的deocoder全部实现于ImageDecoder Trait中的定义。文档传送门

具体定义:

pub trait ImageDecoder: Sized {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)>;
    fn colortype(&mut self) -> ImageResult<ColorType>;
    fn row_len(&mut self) -> ImageResult<usize>;
    fn read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>;
    fn read_image(&mut self) -> ImageResult<DecodingResult>;

    fn is_animated(&mut self) -> ImageResult<bool> { ... }
    fn into_frames(self) -> ImageResult<Frames> { ... }
    fn load_rect(
        &mut self, 
        x: u32, 
        y: u32, 
        length: u32, 
        width: u32
    ) -> ImageResult<Vec<u8>> { ... }
}

可以看出,该trait定义了八个函数,其中六个是所有该库中实现该trait的实例中都实现了的函数:

  • dimensions:返回泛型T为(u32,u32)的imageResult,具体实现时,是返回宽度和高度的元组
  • colorType:返回泛型为colorType的imageResult,其中colorType为图片对应的色彩类型,定义如下:
pub enum ColorType {
    Gray(u8),
    RGB(u8),
    Palette(u8),
    GrayA(u8),
    RGBA(u8),
}
  • row_len 返回T为usize的imageResult,实现时为返回decode后每行的字节数
  • read_scanline:返回T为u32的imageResult,实现时为读取一行图片数据到传入的buf中,然后返回index索引
  • read_image: 读取全部图片数据,以vector形式返回imageResult
  • load_ract: 读取特定矩形区域内的数据,返回vector数组

关于“GenericImage” Trait

"GenericImage" Trait 提供了一系列的处理image的方法,最常见的,当我们使用image库提供的open函数时,成功会返回一个DynamicImage的枚举,而枚举就实现了"GenericImage" Trait。先看看"GenericImage" Trait的定义:

pub trait GenericImage: Sized {
    type Pixel: Pixel;
    fn dimensions(&self) -> (u32, u32);
    fn bounds(&self) -> (u32, u32, u32, u32);
    fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel;
    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel;
    fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
    fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);

    fn width(&self) -> u32 { ... }
    fn height(&self) -> u32 { ... }
    fn in_bounds(&self, x: u32, y: u32) -> bool { ... }
    unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel { ... }
    unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) { ... }
    fn pixels(&self) -> Pixels<Self> { ... }
    fn pixels_mut(&mut self) -> MutPixels<Self> { ... }
    fn copy_from<O>(&mut self, other: &O, x: u32, y: u32) -> bool
    where
        O: GenericImage<Pixel = Self::Pixel>,
    { ... }
    fn sub_image<'a>(
        &'a mut self, 
        x: u32, 
        y: u32, 
        width: u32, 
        height: u32
    ) -> SubImage<'a, Self>
    where
        Self: 'static,
        Self::Pixel::Subpixel: 'static,
        Self::Pixel: 'static,
    { ... }
}

其中六个函数是必须实现的:

  • dimensions: 同上文的dimensions
  • bounds: 测试后发现是返回左上坐标和右下坐标(求指正)
  • get_pixel: 返回传入坐标位置的像素信息,定义上是返回一个"pixel" trait实例,在实际运行中其实就是返回结构体RGB,RGBA,Luma,LumaA之一,这几个实例都实现了"pixel" trait。同时包含了了data属性,为一个vector数组,包含十进制的色彩信息
  • get_pixel_mut:见名知其意,返回的是一个可写的"pixel" trait实例
  • put_pixel: 将对应位置的像素替换为传入的pixel实例
  • blend_pixel: 即将废弃,就不说明了

关于图片内容的表示

文档中表示image库提供了两种方式来表示图片内容。其一就是直接操作struct “imageBuffer”来实现,其二就是“DynamicImage”

imageBuffer

imageBuffer同样见名知其意,就是直接操纵buffer中的像素信息,一般用于新建一张已知类型的图片。同样,在其上实现了“GenericImage” Trait,可以使用其中的函数。
示例(官方示例,小生改了注释):

extern crate image;
use image::{
    GenericImage,
    ImageBuffer
};
//利用imageBuffer的new函数构建一个新的buffer,传入的参数是新建图像的宽高
let img = ImageBuffer::new(512, 512);

//利用imageBuffer的from_fn函数构建一个新的buffer,传入参数为新建图像的宽高,然后图像中的每个像素都会被第三个参数所处理
let img = ImageBuffer::from_fn(512, 512, |x, y| {
    if x % 2 == 0 {
        image::Luma([0u8])
    } else {
        image::Luma([255u8])
    }
});

//由于实例化了“GenericImage” Trait,所以可以直接使用dimensions
let (width, height) = img.dimensions();

//可以类似于数组一样,传入xy元组索引获取对应位置像素
let pixel = img[(100, 100)];

//当然,也可以使用“GenericImage” Trait中的get_pixel函数来获取对应位置的像素
let pixel = img.get_pixel(100, 100);

//替换像素也是同样的
img.put_pixel(100, 100, pixel);

//pixels函数可以返回所有像素的位置以及像素信息,并且由于pixel实现了iterator,所以可以直接使用for循环进行遍历
for pixel in img.pixels() {
    //pixel此时为(x,y,RGBA{data:[0,0,0,0]}),RGBA可能为其他任何该库中定义的色彩类型,data值为对应通道的十进制值
}

DynamicImage

DynamicImage其实和imageBuffer差不太多,只是DynamicImage中像素的色彩类型是不定的,在运行时才确定,所以当使用open函数打开一个图片时,便是返回的这个类型的句柄,同样,它也是实现了“GenericImage” Trait(仅在像素类型为RGBA时),当然,他也自身实现了大量的函数,快速传送门

示例(这下是小生献丑写的了):

 extern crate image;
 use std::path::Path;
 use image::GenericImage;
  fn main() {
     let img=image::open(&Path::new("1.png")).unwrap();
     println!("dimonsions:{:?}",img.dimensions());
     println!("width:{:?}",img.width());
     println!("bounds:{:?}",img.bounds());
     println!("(10,10)'s pixel:{:?}",img.get_pixel(10,10))
 }

关于图像处理的一些函数

ps:这些函数位于“imageops” module中,操作对象皆为“GenericImage” Trait 的实例,快速传送门

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容