omf/file/
image.rs

1use std::io::{BufReader, Cursor, Seek, Write};
2
3use crate::{Array, array_type, error::Error};
4
5use super::{Limits, ReadAt, Reader, Writer};
6
7impl From<Limits> for image::Limits {
8    fn from(value: Limits) -> Self {
9        let mut out = Self::no_limits();
10        out.max_alloc = value.image_bytes;
11        out.max_image_width = value.image_dim;
12        out.max_image_height = value.image_dim;
13        out
14    }
15}
16
17impl<R: ReadAt> Reader<R> {
18    /// Read and decode an image.
19    pub fn image(&self, image: &Array<array_type::Image>) -> Result<image::DynamicImage, Error> {
20        let f = BufReader::new(self.array_bytes_reader(image)?);
21        let mut reader = image::ImageReader::new(f).with_guessed_format()?;
22        reader.limits(self.limits().into());
23        Ok(reader.decode()?)
24    }
25}
26
27impl<W: Write + Seek> Writer<W> {
28    /// Write an image in PNG encoding.
29    ///
30    /// This supports grayscale, grayscale + alpha, RGB, and RGBA, in 8 or 16 bits per channel.
31    pub fn image_png(
32        &mut self,
33        image: &image::DynamicImage,
34    ) -> Result<Array<array_type::Image>, Error> {
35        let mut bytes = Vec::new();
36        image.write_to(&mut Cursor::new(&mut bytes), image::ImageFormat::Png)?;
37        self.image_bytes(&bytes)
38    }
39
40    /// Write an image in JPEG encoding.
41    ///
42    /// Unlike PNG this is limited to 8-bit RGB and compression is lossy, but it will give
43    /// much better compression ratios. The JPEG compression level is set by the `quality`
44    /// argument, from 1 to 100. 90 is a reasonable level for preserving fine detail in the image,
45    /// while lower values will give a smaller file.
46    ///
47    /// If you have an existing image in JPEG encoding you shouldn't be using this method,
48    /// instead add the raw bytes of the file with `writer.image_bytes(&bytes)` to avoid recompressing
49    /// the image and losing more detail.
50    pub fn image_jpeg(
51        &mut self,
52        image: &image::RgbImage,
53        quality: u8,
54    ) -> Result<Array<array_type::Image>, Error> {
55        let mut bytes = Vec::new();
56        image.write_with_encoder(image::codecs::jpeg::JpegEncoder::new_with_quality(
57            &mut Cursor::new(&mut bytes),
58            quality.clamp(1, 100),
59        ))?;
60        self.image_bytes(&bytes)
61    }
62}