代码之家  ›  专栏  ›  技术社区  ›  Jeremy Meo

如何对生锈的活塞图像进行编码并将结果存入内存?

  •  2
  • Jeremy Meo  · 技术社区  · 6 年前

    我正在使用 the Piston image package 生成图像。

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

    我有一个 hyper web server ,我希望从中提供动态生成的图像。

    基于对 How to create an in-memory object that can be used as a Reader or Writer in Rust? ,我想我可以使用 Cursor<Vec<u8>> 作为目的地。然而, 形象 似乎只提供了写入文件名的方法,而不是 Writer 就像我的光标。

    看完之后 形象 的文档,我希望有一些方法可以使用 the image::png::PNGEncoder struct 直接。它提供了一种公共方法 encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> Result<()> . 但是,我不确定 data 争论应该是,我找不到 ColorType 使用的 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()),
        ))
    }
    

    如何编码 a Piston GenericImage 以PNG格式并在内存中得到结果?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Shepmaster Tim Diekmann    6 年前
    fn getImage() -> image::DynamicImage 
    

    你有一个 DynamicImage

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

    我想你是说 DynamicImage::save

    之前的方法 save write_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 .


    如何对活塞进行编码 GenericImage 像PNG这样的格式?

    我不知道最好的办法。我可能会把普通图像复制到 动态图像 然后按照上面的说明操作。

        2
  •  1
  •   Taras Alenin    6 年前

    我已经根据 image 板条箱。看起来可以使原始代码正常工作。没有必要 Cursor 但是需要为 Write 执行人 Vec .

    // 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)
    }