【问题标题】:How do I convert a custom image implementation of a bitmap slice to PNG?如何将位图切片的自定义图像实现转换为 PNG?
【发布时间】:2022-01-01 00:55:55
【问题描述】:

我在一个用 Rust 编写的项目工作,该项目基本上模拟了一台打印机。我得到打印机输入,并尝试将其转换为人类可读的数据(字符串、图像)。因此,为了重现 QR 码,我将打印机输入转换为位图切片(我创建了一个实现 GenericImageView 的结构)。

BitmapImageSlice {
      height,
      width,
      buffer: data
    }
impl GenericImageView for BitmapImageSlice {
  type Pixel = Rgb<u8>;
  type InnerImageView = BitmapImageSlice;

  fn dimensions(&self) -> (u32, u32) {
    (self.width as u32, self.height as u32)
  }

  fn bounds(&self) -> (u32, u32, u32, u32) {
    ( 0, 0, self.width as u32, self.height as u32)
  }

  fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
    let byte = self.buffer[x as usize];
    let bit_position = 7-y;
    let bit = 1 << bit_position;
    if (byte & bit as u8) > 0{
      Rgb([0, 0, 0])
    }
    else {
      Rgb([255, 255, 255])
    }
  }


  fn inner(&self) -> &Self::InnerImageView {
    self
  }
}

我的问题是,如何将BitMapImageSlice 值转换为以 PNG 编码的图像?

【问题讨论】:

  • @E_net4thevoter:这适用于 1bpp 图像和 24bpp 图像吗?我猜想一些与image::RGBA(8) 不同的参数,大概很容易在文档中查找image 板条箱记录在哪里?还是会使用这个定义的get_pixel 访问器函数?
  • docs.rs/image/0.23.14/image/codecs/png/struct.PngEncoder.html 或许你可以看看这个函数的实现?

标签: rust rust-cargo low-level rust-crates


【解决方案1】:

在尝试通过image crate 自己实现通用图像时存在一个关键问题:不支持每像素 1 位颜色类型,即使使用适配层,不兼容可用的API。

  • write_to 方法只存在于DynamicImage,它被定义为内置实现的枚举。它不能扩展到考虑孤儿实现。
  • save_buffer_with_format(如建议的 here)需要一个符合支持的颜色类型的像素样本缓冲区。
  • 即使是在 trait ImageEncoder 中声明的用于写入编码内容的裸图像编码器签名也需要一个支持颜色类型的像素缓冲区。

因此,在这里使用支持的图像类型更直接。将位图转换为L8 颜色类型并使用那里的现有函数。

impl BitmapImageSlice {
    
    pub fn to_image(&self) -> ImageBuffer<Luma<u8>, Vec<u8>> {
        // NOTE: this depends on the BitmapImageSlice data layout,
        // adjust vector construction accordingly
        let data: Vec<u8> = self.buffer.iter()
            .flat_map(|b| [
                b >> 7,
                (b >> 6) & 1,
                (b >> 5) & 1,
                (b >> 4) & 1,
                (b >> 3) & 1,
                (b >> 2) & 1,
                (b >> 1) & 1,
                b & 1,
            ])
            .map(|p| p * 0xFF)
            .collect();
        
        ImageBuffer::from_vec(self.width, self.height, data).unwrap()
    }
}

fn save(bitmap: &BitmapImageSlice) -> image::error::ImageResult<()> {
    let img = bitmap.to_image();
    image::save_buffer_with_format(
        "out.png",
        img.as_raw(),
        bitmap.width,
        bitmap.height,
        ColorType::L8,
        ImageFormat::Png,
    )?;
    Ok(())
}

Playground

【讨论】:

    猜你喜欢
    • 2013-10-07
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 2018-02-15
    • 2011-02-01
    • 2021-05-27
    • 2020-08-02
    • 2021-03-08
    相关资源
    最近更新 更多