1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright (c) 2023.
 *
 * This software is free software;
 *
 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
 */

#![cfg(feature = "hdr")]
//! Radiance HDR decoding support
use zune_core::bit_depth::BitDepth;
use zune_core::bytestream::ZReaderTrait;
use zune_core::colorspace::ColorSpace;
use zune_core::options::EncoderOptions;
pub use zune_hdr::*;

use crate::codecs::{create_options_for_encoder, ImageFormat};
use crate::errors::{ImageErrors, ImgEncodeErrors};
use crate::image::Image;
use crate::metadata::ImageMetadata;
use crate::traits::{DecoderTrait, EncoderTrait};

impl<T> DecoderTrait<T> for HdrDecoder<T>
where
    T: ZReaderTrait
{
    fn decode(&mut self) -> Result<Image, ImageErrors> {
        let bytes = self.decode()?;
        let (width, height) = self.get_dimensions().unwrap();
        let colorspace = self.get_colorspace().unwrap();

        Ok(Image::from_f32(&bytes, width, height, colorspace))
    }

    fn dimensions(&self) -> Option<(usize, usize)> {
        self.get_dimensions()
    }

    fn out_colorspace(&self) -> ColorSpace {
        self.get_colorspace().unwrap()
    }

    fn name(&self) -> &'static str {
        "HDR decoder"
    }

    fn read_headers(&mut self) -> Result<Option<ImageMetadata>, ImageErrors> {
        self.decode_headers()?;

        let (width, height) = self.get_dimensions().unwrap();

        let metadata = ImageMetadata {
            width: width,
            height: height,
            colorspace: ColorSpace::RGB,
            depth: BitDepth::Float32,
            format: Some(ImageFormat::HDR),
            ..Default::default()
        };
        Ok(Some(metadata))
    }
}

impl From<HdrDecodeErrors> for ImageErrors {
    fn from(value: HdrDecodeErrors) -> Self {
        Self::ImageDecodeErrors(format!("hdr: {value:?}"))
    }
}

#[derive(Default)]
pub struct HdrEncoder {
    options: Option<EncoderOptions>
}

impl HdrEncoder {
    pub fn new() -> HdrEncoder {
        Self::default()
    }
    pub fn new_with_options(options: EncoderOptions) -> HdrEncoder {
        HdrEncoder {
            options: Some(options)
        }
    }
}

impl EncoderTrait for HdrEncoder {
    fn name(&self) -> &'static str {
        "Hdr"
    }

    fn encode_inner(&mut self, image: &Image) -> Result<Vec<u8>, ImageErrors> {
        let options = create_options_for_encoder(self.options, image);

        assert_eq!(image.depth(), BitDepth::Float32);

        let data = &image.flatten_frames()[0];

        let encoder_options = zune_hdr::HdrEncoder::new(data, options);

        let data = encoder_options
            .encode()
            .map_err(<HdrEncodeErrors as Into<ImgEncodeErrors>>::into)?;

        Ok(data)
    }
    fn supported_colorspaces(&self) -> &'static [ColorSpace] {
        &[ColorSpace::RGB]
    }

    fn format(&self) -> ImageFormat {
        ImageFormat::HDR
    }

    fn supported_bit_depth(&self) -> &'static [BitDepth] {
        &[BitDepth::Float32]
    }

    fn default_depth(&self, _: BitDepth) -> BitDepth {
        BitDepth::Float32
    }

    fn default_colorspace(&self, _: ColorSpace) -> ColorSpace {
        ColorSpace::RGB
    }

    fn set_options(&mut self, opts: EncoderOptions) {
        self.options = Some(opts)
    }
}

impl From<HdrEncodeErrors> for ImgEncodeErrors {
    fn from(value: HdrEncodeErrors) -> Self {
        ImgEncodeErrors::ImageEncodeErrors(format!("HDR: {:?}", value))
    }
}