Rust翻译计划——image库

作者: 被叫做逸轩的可儿 | 来源:发表于2017-06-09 00:10 被阅读76次

    本文目录:

    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 的实例,快速传送门

    相关文章

      网友评论

        本文标题:Rust翻译计划——image库

        本文链接:https://www.haomeiwen.com/subject/jkkxqxtx.html