diff --git a/src/encoder.rs b/src/encoder.rs index eded305..e88266b 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -4,7 +4,7 @@ use crate::image_buffer::*; use crate::marker::Marker; use crate::quantization::{QuantizationTable, QuantizationTableType}; use crate::writer::{JfifWrite, JfifWriter, ZIGZAG}; -use crate::{Density, EncodingError}; +use crate::{PixelDensity, EncodingError}; use alloc::vec; use alloc::vec::Vec; @@ -194,7 +194,7 @@ macro_rules! add_component { /// # The JPEG encoder pub struct Encoder { writer: JfifWriter, - density: Density, + density: PixelDensity, quality: u8, components: Vec, @@ -243,7 +243,7 @@ impl Encoder { Encoder { writer: JfifWriter::new(w), - density: Density::None, + density: PixelDensity::default(), quality, components: vec![], quantization_tables, @@ -259,12 +259,12 @@ impl Encoder { /// Set pixel density for the image /// /// By default, this value is None which is equal to "1 pixel per pixel". - pub fn set_density(&mut self, density: Density) { + pub fn set_density(&mut self, density: PixelDensity) { self.density = density; } /// Return pixel density - pub fn density(&self) -> Density { + pub fn density(&self) -> PixelDensity { self.density } diff --git a/src/lib.rs b/src/lib.rs index 9fc0a0e..0ba9ba2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ pub use encoder::{ColorType, Encoder, JpegColorType, SamplingFactor}; pub use error::EncodingError; pub use image_buffer::{cmyk_to_ycck, rgb_to_ycbcr, ImageBuffer}; pub use quantization::QuantizationTableType; -pub use writer::{Density, JfifWrite}; +pub use writer::{PixelDensity, PixelDensityUnit, JfifWrite}; #[cfg(feature = "benchmark")] pub use fdct::fdct; diff --git a/src/writer.rs b/src/writer.rs index e818b67..6490e98 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -4,17 +4,58 @@ use crate::marker::{Marker, SOFType}; use crate::quantization::QuantizationTable; use crate::EncodingError; -/// Density settings -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum Density { - /// No pixel density is set, which means "1 pixel per pixel" - None, +/// Represents the pixel density of an image +/// +/// For example, a 300 DPI image is represented by: +/// +/// ```rust +/// # use jpeg_encoder::{PixelDensity, PixelDensityUnit}; +/// let hdpi = PixelDensity::dpi(300); +/// assert_eq!(hdpi, PixelDensity {density: (300,300), unit: PixelDensityUnit::Inches}) +/// ``` +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct PixelDensity { + /// A couple of values for (Xdensity, Ydensity) + pub density: (u16, u16), + /// The unit in which the density is measured + pub unit: PixelDensityUnit, +} + +impl PixelDensity { + /// Creates the most common pixel density type: + /// the horizontal and the vertical density are equal, + /// and measured in pixels per inch. + #[must_use] + pub fn dpi(density: u16) -> Self { + PixelDensity { + density: (density, density), + unit: PixelDensityUnit::Inches, + } + } +} + +impl Default for PixelDensity { + /// Returns a pixel density with a pixel aspect ratio of 1 + fn default() -> Self { + PixelDensity { + density: (1, 1), + unit: PixelDensityUnit::PixelAspectRatio, + } + } +} + +/// Represents a unit in which the density of an image is measured +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum PixelDensityUnit { + /// Represents the absence of a unit, the values indicate only a + /// [pixel aspect ratio](https://en.wikipedia.org/wiki/Pixel_aspect_ratio) + PixelAspectRatio, - /// Horizontal and vertical dots per inch (dpi) - Inch { x: u16, y: u16 }, + /// Pixels per inch (2.54 cm) + Inches, - /// Horizontal and vertical dots per centimeters - Centimeter { x: u16, y: u16 }, + /// Pixels per centimeter + Centimeters, } /// Zig-zag sequence of quantized DCT coefficients @@ -172,30 +213,27 @@ impl JfifWriter { Ok(()) } - pub fn write_header(&mut self, density: &Density) -> Result<(), EncodingError> { + pub fn write_header(&mut self, density: &PixelDensity) -> Result<(), EncodingError> { self.write_marker(Marker::APP(0))?; self.write_u16(16)?; self.write(b"JFIF\0")?; self.write(&[0x01, 0x02])?; - match *density { - Density::None => { + match density.unit { + PixelDensityUnit::PixelAspectRatio => { self.write_u8(0x00)?; - self.write_u16(1)?; - self.write_u16(1)?; } - Density::Inch { x, y } => { + PixelDensityUnit::Inches => { self.write_u8(0x01)?; - self.write_u16(x)?; - self.write_u16(y)?; } - Density::Centimeter { x, y } => { + PixelDensityUnit::Centimeters => { self.write_u8(0x02)?; - self.write_u16(x)?; - self.write_u16(y)?; } } + let (x, y) = density.density; + self.write_u16(x)?; + self.write_u16(y)?; self.write(&[0x00, 0x00]) }