首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用图像::ImageBuffer作为成员创建一个Rust结构?

如何使用图像::ImageBuffer作为成员创建一个Rust结构?
EN

Stack Overflow用户
提问于 2016-02-18 17:51:06
回答 1查看 4.7K关注 0票数 6

我正在使用图像机箱进行图片处理,并希望创建一个小包装器,以使我的代码更加美观。

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

const BLACK: [u8; 4] = [0, 0, 0, 255];
const WHITE: [u8; 4] = [255, 255, 255, 255];
const RED: [u8; 4] = [255, 0, 0, 255];

pub struct Picture {
    buffer: image::ImageBuffer,
    width: u32,
    height: u32
}

impl Picture {
    // My functions like fill(), line() etc.
}

但是,当我编译它时,我有一个错误:

代码语言:javascript
复制
src\pic.rs:11:13: 11:31 error: wrong number of type arguments: expected 2, found 0 [E0243]
src\pic.rs:11     buffer: image::ImageBuffer,
                          ^~~~~~~~~~~~~~~~~~

在源代码中,我看到ImageBuffer接受两个参数:

代码语言:javascript
复制
pub struct ImageBuffer<P: Pixel, Container> {
    width: u32,
    height: u32,
    _phantom: PhantomData<P>,
    data: Container,
}

因此,我决定将这些参数放在Picture声明中:

代码语言:javascript
复制
pub struct Picture {
    buffer: image::ImageBuffer<image::Pixel>,
}

又犯了一个错误:

代码语言:javascript
复制
src\pic.rs:11:32: 11:44 error: the value of the associated type `Subpixel` (from the trait `pic::image::buffer::Pixel`) must be specified [E0191]
src\pic.rs:11     buffer: image::ImageBuffer<image::Pixel>,
                                             ^~~~~~~~~~~~

这意味着我必须为Subpixel类型指定一些值,但我没有得到它。我不知道如何声明Container类型,我在源代码中找不到任何有用的东西。我试着重读“锈书”、“示例”、“rustc --explain E0191”,但我还是迷失了方向.

最新情况:

在下一份声明中找到的资料来源:

代码语言:javascript
复制
impl<P, Container> ImageBuffer<P, Container>
where P: Pixel + 'static,
      P::Subpixel: 'static,
      Container: Deref<Target=[P::Subpixel]>

Subpixel是:

代码语言:javascript
复制
/// Primitive trait from old stdlib
pub trait Primitive: Copy + NumCast + Num + PartialOrd<Self> + Clone + Bounded {
}

但对我的箱子来说不是公开的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-18 20:37:34

查看ImageBuffer,我们可以看到类型参数的特性要求:

代码语言:javascript
复制
impl<P, Container> ImageBuffer<P, Container>
    where P: Pixel + 'static,
          P::Subpixel: 'static,
          Container: Deref<Target=[P::Subpixel]>

因此,重要的是,第二种类型的参数可以取消对子像素片的引用。Subpixel是由特性决定的,它有几个实现:

  • Rgb<T>
  • Luma<T>
  • Rgba<T>
  • LumaA<T>

其中T是亚像素类型。

这一切都是相当复杂的,但应该提供一个良好的权力和一般性。

请注意,我只显示了其中一个实现块。还有一些需要DerefMut或要求亚像素为u8

你到底是怎么用的?首先,您需要选择特定的颜色和亚像素类型。根据您的颜色,它看起来您想使用4通道,8位的颜色类型.那将是Rgba

有许多类型可以取消对&[u8]&mut [u8]的引用。显而易见的(但不仅仅是!)选择将是一个Vec<u8>

将这两者结合起来,您的结构需要如下所示:

代码语言:javascript
复制
buffer: image::ImageBuffer<Rgba<u8>, Vec<u8>>,

然后,这只是一个创建结构和做事情的问题:

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

use image::{ImageBuffer, Pixel, Rgba};

pub struct Picture {
    buffer: ImageBuffer<Rgba<u8>, Vec<u8>>,
}

impl Picture {
    fn new(width: u32, height: u32) -> Self {
        // There's probably a cleaner way to figure out the right size
        let storage = vec![0; 4 * width as usize * height as usize];
        let buf = ImageBuffer::from_raw(width, height, storage).unwrap();

        Picture {
            buffer: buf,
        }
    }

    fn fill_red(&mut self) {
        let color = Rgba::from_channels(255, 0, 0, 255);

        for p in self.buffer.pixels_mut() {
            *p = color;
        }
    }
}

fn main() {
    let mut pic = Picture::new(256, 256);
    pic.fill_red();
}

请注意,ImageBuffer已经跟踪了宽度和高度,因此没有真正的理由再次跟踪它们。

然而,所有这一切都是困难的。有一些像new这样的方便函数将为您分配存储:

代码语言:javascript
复制
buffer: ImageBuffer::new(width, height),

这些函数是硬编码的,以返回一个Vec作为Container。如果您没有在文档中看到这一点,您可以尝试类似于打印类型的方法

代码语言:javascript
复制
let () = ImageBuffer::new(width, height);

这将告诉您错误消息中的类型:

代码语言:javascript
复制
expected `image::buffer::ImageBuffer<_, collections::vec::Vec<_>>`,
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35488820

复制
相关文章

相似问题

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