我刚开始学习“锈”,我真的很喜欢通过建立“真实”来学习。因此,我阅读了书,安装了Rust,在语言中游玩,并使cargo run工作起来。
然后,我决定尝试从磁盘读取一个映像,并将该映像转换为Vec。在这种情况下,我想检测像素的颜色并以某种方式存储它。
为了学习Rust及其语法,我将其分解为多个部分:
首先:
这导致我使用影像箱编写了下面的代码
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());
}尽管我很自豪,但我看到一些信息在冒出来:
* 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数组如下所示:
$a = [
0 => [ Color, Color, Color, Color],
1 => [ Color, Color, Color, Color]
];因此,我的假设是使用read_scanline。在这里,阅读和理解文档完全失败了。
我认为我需要做的是:
read_scanline但是怎么做?!
代码如下:
read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>我将此细分如下:
ImageDecoder对象。ImageResult对象。因此,我尝试稍微修改代码:
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());
}正如你可能已经猜到的那样,这很不幸地失败了。
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。我也不明白我应该如何发起这一行动。
我希望有人能解释我错过了什么,把我引向正确的方向。
发布于 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_len和ImageDecoder::dimensions分别对此进行了寻址。加在一起,我们得到了这样的东西:
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:
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个字节,但是我没有看到任何明显的东西。
https://stackoverflow.com/questions/35316163
复制相似问题