Skip to main content

zune_image/codecs/
hdr.rs

1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software;
5 *
6 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7 */
8#![cfg_attr(feature = "docs", doc(cfg(feature = "hdr")))]
9#![cfg(feature = "hdr")]
10//! Radiance HDR decoding and encoding support
11use zune_core::bit_depth::BitDepth;
12use zune_core::bytestream::{ZByteReaderTrait, ZByteWriterTrait};
13use zune_core::colorspace::ColorSpace;
14use zune_core::options::EncoderOptions;
15pub use zune_hdr::*;
16
17use crate::codecs::{create_options_for_encoder, ImageFormat};
18use crate::errors::{ImageErrors, ImgEncodeErrors};
19use crate::image::Image;
20use crate::metadata::ImageMetadata;
21use crate::traits::{DecodeInto, DecoderTrait, EncoderTrait};
22
23impl<T> DecoderTrait for HdrDecoder<T>
24where
25    T: ZByteReaderTrait
26{
27    fn decode(&mut self) -> Result<Image, ImageErrors> {
28        let bytes = self.decode()?;
29        let (width, height) = self.dimensions().unwrap();
30        let colorspace = self.get_colorspace().unwrap();
31
32        Ok(Image::from_f32(&bytes, width, height, colorspace))
33    }
34
35    fn dimensions(&self) -> Option<(usize, usize)> {
36        self.dimensions()
37    }
38
39    fn out_colorspace(&self) -> ColorSpace {
40        self.get_colorspace().unwrap()
41    }
42
43    fn name(&self) -> &'static str {
44        "HDR decoder"
45    }
46
47    fn read_headers(&mut self) -> Result<Option<ImageMetadata>, ImageErrors> {
48        self.decode_headers()?;
49
50        let (width, height) = self.dimensions().unwrap();
51
52        let metadata = ImageMetadata {
53            width,
54            height,
55            colorspace: ColorSpace::RGB,
56            depth: BitDepth::Float32,
57            format: Some(ImageFormat::HDR),
58            ..Default::default()
59        };
60        Ok(Some(metadata))
61    }
62}
63
64impl From<HdrDecodeErrors> for ImageErrors {
65    fn from(value: HdrDecodeErrors) -> Self {
66        Self::ImageDecodeErrors(format!("hdr: {value:?}"))
67    }
68}
69
70#[derive(Default)]
71pub struct HdrEncoder {
72    options: Option<EncoderOptions>
73}
74
75impl HdrEncoder {
76    pub fn new() -> HdrEncoder {
77        Self::default()
78    }
79    pub fn new_with_options(options: EncoderOptions) -> HdrEncoder {
80        HdrEncoder {
81            options: Some(options)
82        }
83    }
84}
85
86impl EncoderTrait for HdrEncoder {
87    fn name(&self) -> &'static str {
88        "Hdr"
89    }
90
91    fn encode_inner<T: ZByteWriterTrait>(
92        &mut self, image: &Image, sink: T
93    ) -> Result<usize, ImageErrors> {
94        let options = create_options_for_encoder(self.options, image);
95
96        assert_eq!(image.depth(), BitDepth::Float32);
97
98        let data = &image.flatten_frames()[0];
99
100        let encoder_options = zune_hdr::HdrEncoder::new(data, options);
101
102        let data = encoder_options
103            .encode(sink)
104            .map_err(<HdrEncodeErrors as Into<ImgEncodeErrors>>::into)?;
105
106        Ok(data)
107    }
108    fn supported_colorspaces(&self) -> &'static [ColorSpace] {
109        &[ColorSpace::RGB]
110    }
111
112    fn format(&self) -> ImageFormat {
113        ImageFormat::HDR
114    }
115
116    fn supported_bit_depth(&self) -> &'static [BitDepth] {
117        &[BitDepth::Float32]
118    }
119
120    fn default_depth(&self, _: BitDepth) -> BitDepth {
121        BitDepth::Float32
122    }
123
124    fn default_colorspace(&self, _: ColorSpace) -> ColorSpace {
125        ColorSpace::RGB
126    }
127
128    fn set_options(&mut self, opts: EncoderOptions) {
129        self.options = Some(opts)
130    }
131}
132
133impl From<HdrEncodeErrors> for ImgEncodeErrors {
134    fn from(value: HdrEncodeErrors) -> Self {
135        ImgEncodeErrors::ImageEncodeErrors(format!("HDR: {:?}", value))
136    }
137}
138
139impl<T> DecodeInto for HdrDecoder<T>
140where
141    T: ZByteReaderTrait
142{
143    type BufferType = f32;
144
145    fn decode_into(&mut self, buffer: &mut [Self::BufferType]) -> Result<(), ImageErrors> {
146        self.decode_into(buffer)
147            .map_err(<HdrDecodeErrors as Into<ImageErrors>>::into)?;
148
149        Ok(())
150    }
151
152    fn decode_output_buffer_size(&mut self) -> Result<usize, ImageErrors> {
153        self.decode_headers()
154            .map_err(<HdrDecodeErrors as Into<ImageErrors>>::into)?;
155
156        // unwrap is okay because we successfully decoded image headers
157        Ok(self.output_buffer_size().unwrap())
158    }
159}