5

我正在使用Pistonimage生成图像。

fn get_image() -> image::DynamicImage {
    image::DynamicImage::ImageRgba8(image::ImageBuffer::new(512, 512))
}

我有一个hyper网络服务器,我想从中提供动态生成的图像。

基于如何在 Rust 中创建可用作 Reader 或 Writer 的内存对象的答案?,我想我也许可以使用 aCursor<Vec<u8>>作为目的地。但是,image似乎只提供了一种写入文件名的方法,而不是Writer像我的光标。

在查看了image的文档后,我希望可能有一些方法可以直接使用image::png::PNGEncoder结构。它提供了一个公共方法encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> Result<()>。但是,我不确定该data论点应该是什么,并且我找不到ColorType. 使用的 s 的任何公开声明ImageBuffer

(&Get, "/image.png") => {
    let v = {
        let generated = get_image();
        let mut encoded_image = Cursor::new(Vec::new());
        let (width, heigth) = generated.dimensions();
        {
            let encoder = image::png::PNGEncoder::new(&encoded_image);
            encoder.encode(unimplemented!("what goes here?"));
        }
        encoded_image.get_mut()
    };

    Box::new(futures::future::ok(
        Response::new()
            .with_header(ContentLength(v.len() as u64))
            .with_body(v.clone()),
    ))
}

如何将活塞编码为GenericImagePNG 等格式并将结果存储在内存中?

4

3 回答 3

3
fn getImage() -> image::DynamicImage 

你有一个DynamicImage.

图像似乎只提供了一种写入文件名的方法

我假设你的意思是DynamicImage::save

之前的方法savewrite_to

pub fn write_to<W: Write, F: Into<ImageOutputFormat>>(
    &self, 
    w: &mut W, 
    format: F
) -> ImageResult<()>

这接受任何通用作家:

let mut buf = Vec::new();

get_image()
    .write_to(&mut buf, image::ImageOutputFormat::PNG)
    .expect("Unable to write");

不需要Cursor.


如何将活塞编码为GenericImagePNG 等格式?

我不知道最好的方法来做到这一点。我可能会将通用图像复制到 a 中DynamicImage,然后按照上述说明进行操作。

于 2018-06-07T03:09:38.483 回答
2

我已经根据imagecrate 文档改编了 OP 的代码。看起来可以使原始代码工作。不需要,但需要为实现Cursor的实例创建一个“引用”适配器。WriteVec

// This code have not been tested or even compiled
let v = {
    let generated = get_image();
    let mut encoded_image = Vec::new();
    let (width, height) = generated.dimensions();
    {
        image::png::PNGEncoder::new(encoded_image.by_ref())
            .encode(
                generated.raw_pixels(), 
                width, 
                height,
                generated.color()
            ).expected("error encoding pixels as PNG");
    }
    encoded_image
};

这是我在项目中实际使用的代码。我得到了对作为&[u8]切片传入的原始像素的引用。每个像素代表一个 8 位灰度值。这是一个将像素编码为内存PNG图像的函数。

pub fn create_png(pixels: &[u8], dimensions: (usize, usize)) -> Result<Vec<u8>> {
    let mut png_buffer = Vec::new();
    PNGEncoder::new(png_buffer.by_ref())
        .encode(
            pixels,
            dimensions.0 as u32,
            dimensions.1 as u32,
            ColorType::Gray(8),
        ).expect("error encoding pixels as PNG");

    Ok(png_buffer)
}
于 2018-11-04T01:45:32.733 回答
1

DynamicImage与其返回from ,不如返回get_image特定的图像类型更容易,例如彩色 RGBA 图像:

use image::RgbaImage;

fn get_image() -> RgbaImage {
    RgbaImage::new(512, 512)
}

RgbaImageimplements ,这Deref<[u8]>意味着可以将图像直接解引用为字节切片,因此&img可以用作 的第一个参数encode。高度和宽度很容易,只需访问img.height()img.width(). 最后一个参数encode是颜色类型,因为它作为Pixel类型参数的关联常量存储在ImageBuffer. 从泛型类型中,它可以被访问为P::COLOR_TYPE,因此encode_png我没有将其专门用于一种类型的图像,而是将其编写为接受任何ImageBuffer类型。

完整的例子是:

use std::error::Error;
use std::ops::Deref;
use image::{png::PNGEncoder, ImageBuffer, ImageError, Pixel, RgbaImage, Rgba};

fn encode_png<P, Container>(img: &ImageBuffer<P, Container>) -> Result<Vec<u8>, ImageError>
where
    P: Pixel<Subpixel = u8> + 'static,
    Container: Deref<Target = [P::Subpixel]>,
{
    let mut buf = Vec::new();
    let encoder = PNGEncoder::new(&mut buf);
    encoder.encode(img, img.width(), img.height(), P::COLOR_TYPE)?;
    Ok(buf)
}

fn get_image() -> RgbaImage {
    let mut img = RgbaImage::new(32, 32);

    // Draw something to show in the final image
    for i in 0..32 {
        img.put_pixel(i, i, Rgba([255, 0, 0, 255]));
    }
    img
}

fn main() -> Result<(), Box<dyn Error>> {
    let img = get_image();
    let buf = encode_png(&img)?;

    // write out the image using the base64 crate as a data
    // URL so that it can be copy-pasted into a web browser
    println!("data:image/png;base64,{}", base64::encode(&buf));
    Ok(())
}

操场:https ://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e2611c5ef248667bf984a8dd3cedfec8

于 2020-03-25T14:22:24.787 回答