首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用活塞图像箱的read_scanline?

如何使用活塞图像箱的read_scanline?
EN

Stack Overflow用户
提问于 2016-02-10 13:06:49
回答 1查看 505关注 0票数 3

我刚开始学习“锈”,我真的很喜欢通过建立“真实”来学习。因此,我阅读了,安装了Rust,在语言中游玩,并使cargo run工作起来。

然后,我决定尝试从磁盘读取一个映像,并将该映像转换为Vec。在这种情况下,我想检测像素的颜色并以某种方式存储它。

为了学习Rust及其语法,我将其分解为多个部分:

首先:

  1. 从磁盘读取图像
  2. 获取图像的像素
  3. 显示颜色代码

这导致我使用影像箱编写了下面的代码

代码语言:javascript
复制
extern crate image;

use std::path::Path;
use image::GenericImage;

fn main() {

    let img = image::open(&Path::new("src/maze.gif")).unwrap();

    let pixels = img.pixels();

    for e in pixels {
        let (_, _, color) = e;

        println!("Pixel colour {:?}", color);
    }

    println!("Dimensions {:?}", img.dimensions());
}

尽管我很自豪,但我看到一些信息在冒出来:

代码语言:javascript
复制
* snip *
Pixel colour Rgba { data: [255, 255, 255, 255] }
Pixel colour Rgba { data: [0, 0, 0, 255] }
Pixel colour Rgba { data: [255, 255, 255, 255] }
* snip *

现在我想为图像的每一行存储其像素信息。我想要一个Vec (对吗?)带着信息。PHP数组如下所示:

代码语言:javascript
复制
$a = [
   0 => [ Color, Color, Color, Color],
   1 => [ Color, Color, Color, Color]
];

因此,我的假设是使用read_scanline。在这里,阅读和理解文档完全失败了。

我认为我需要做的是:

  1. 获取当前打开图像的解码器。
  2. 调用解码器上的read_scanline
  3. 迭代结果

但是怎么做?!

代码如下:

代码语言:javascript
复制
read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>

我将此细分如下:

  • 第一个参数是ImageDecoder对象。
  • 第二个参数是可变的8位值。
  • 它返回一个ImageResult对象。

因此,我尝试稍微修改代码:

代码语言:javascript
复制
extern crate image;

use std::path::Path;
use image::GenericImage;
use image::ImageDecoder;

fn main() {

    let img = image::open(&Path::new("src/maze.gif")).unwrap();

    let pixels = img.pixels();
    let something: &mut [u8];
    let result = image::ImageDecoder::read_scanline(img, something);

    for e in pixels {
        let (_, _, color) = e;

        println!("Pixel colour {:?}", color);
    }

    println!("Dimensions {:?}", img.dimensions());
}

正如你可能已经猜到的那样,这很不幸地失败了。

代码语言:javascript
复制
error: mismatched types:
 expected `&mut _`,
    found `image::dynimage::DynamicImage`
(expected &-ptr,
    found enum `image::dynimage::DynamicImage`) [E0308]
src/main.rs:13     let result = image::ImageDecoder::read_scanline(img, something);

显然,这是因为我没有传递ImageDecoder对象。但我怎么能呢?我应该如何阅读和理解文档。我认为这是由于不理解&mut self。我也不明白我应该如何发起这一行动。

我希望有人能解释我错过了什么,把我引向正确的方向。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-10 15:28:15

Note我在打开GIF时遇到困难,因为每行都说它是0字节,所以有可能我错过了一些重要的东西.我将使用JPEG来演示。

ImageDecoder一个特点。您需要使用该特性的具体实现。文档列出了该特性的所有已知实现者,其中一个是image::gif::Decoder,另一个是image::jpeg::JPEGDecoder

read_scanline接受一个可变的self,这意味着您通常会使用方法语法:object.method(arg1)调用它。第一个非self参数是一个可变的字节片.这些文件指出:

将图像中的一行读入buf并返回行索引

因此像素数据将存储在缓冲区中。下一个诀窍是计算出一行所需的字节数和行数。ImageDecoder::row_lenImageDecoder::dimensions分别对此进行了寻址。加在一起,我们得到了这样的东西:

代码语言:javascript
复制
extern crate image;

use std::fs::File;

use image::jpeg;
use image::{GenericImage, ImageDecoder};
use image::{ColorType, Rgb, Pixel};

fn main() {
    let f = File::open("/tmp/cat.jpg").unwrap();
    let mut decoder = jpeg::JPEGDecoder::new(f);

    let (width, height) = decoder.dimensions().unwrap();
    let row_len = decoder.row_len().unwrap();

    println!("{} x {}, {}", width, height, row_len);

    let rows: Vec<_> = (0..height).map(|_| {
        let mut row = vec![0; row_len];
        decoder.read_scanline(&mut row).unwrap();
        row
    }).collect();
}

这会将JPEG逐行加载到一个Vec<Vec<u8>> --一个字节向量的向量中.

要将原始数据转换为像素,我们可以使用Pixel::from_slice,另一种特性方法。在这种情况下,我只处理一种像素类型-8位RGB:

代码语言:javascript
复制
let colortype = decoder.colortype().unwrap();
assert_eq!(colortype, ColorType::RGB(8)); // Others are left to you!

let row_colors: Vec<Vec<_>> = rows.iter().map(|r| {
    r.chunks(3).map(|p| Rgb::from_slice(p)).collect()
}).collect();

我不喜欢这个,因为硬编码的3。应该有一些方法可以知道这个像素类型只需要3个字节,但是我没有看到任何明显的东西。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35316163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档