exr/image/write/
layers.rs

1//! How to write either a single or a list of layers.
2
3use crate::meta::header::{ImageAttributes, Header};
4use crate::meta::{Headers, compute_chunk_count};
5use crate::block::BlockIndex;
6use crate::image::{Layers, Layer};
7use crate::meta::attribute::{TileDescription};
8use crate::prelude::{SmallVec};
9use crate::image::write::channels::{WritableChannels, ChannelsWriter};
10use crate::image::recursive::{Recursive, NoneMore};
11
12/// Enables an image containing this list of layers to be written to a file.
13pub trait WritableLayers<'slf> {
14
15    /// Generate the file meta data for this list of layers
16    fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers;
17
18    /// The type of temporary writer
19    type Writer: LayersWriter;
20
21    /// Create a temporary writer for this list of layers
22    fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer;
23}
24
25/// A temporary writer for a list of channels
26pub trait LayersWriter: Sync {
27
28    /// Deliver a block of pixels from a single layer to be stored in the file
29    fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8>;
30}
31
32/// A temporary writer for an arbitrary list of layers
33#[derive(Debug, Clone, Eq, PartialEq)]
34pub struct AllLayersWriter<ChannelsWriter> {
35    layers: SmallVec<[LayerWriter<ChannelsWriter>; 2]>
36}
37
38/// A temporary writer for a single layer
39#[derive(Debug, Clone, Eq, PartialEq)]
40pub struct LayerWriter<ChannelsWriter> {
41    channels: ChannelsWriter, // impl ChannelsWriter
42}
43
44// impl for smallvec
45impl<'slf, Channels: 'slf> WritableLayers<'slf> for Layers<Channels> where Channels: WritableChannels<'slf> {
46    fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers {
47        slice_infer_headers(self.as_slice(), image_attributes)
48    }
49
50    type Writer = AllLayersWriter<Channels::Writer>;
51    fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer {
52        slice_create_writer(self.as_slice(), headers)
53    }
54}
55
56fn slice_infer_headers<'slf, Channels:'slf + WritableChannels<'slf>>(
57    slice: &[Layer<Channels>], image_attributes: &ImageAttributes
58) -> Headers
59{
60    slice.iter().map(|layer| layer.infer_headers(image_attributes).remove(0)).collect() // TODO no array-vs-first
61}
62
63fn slice_create_writer<'slf, Channels:'slf + WritableChannels<'slf>>(
64    slice: &'slf [Layer<Channels>], headers: &[Header]
65) -> AllLayersWriter<Channels::Writer>
66{
67    AllLayersWriter {
68        layers: slice.iter().zip(headers.chunks_exact(1)) // TODO no array-vs-first
69            .map(|(layer, header)| layer.create_writer(header))
70            .collect()
71    }
72}
73
74
75impl<'slf, Channels: WritableChannels<'slf>> WritableLayers<'slf> for Layer<Channels> {
76    fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers {
77        let blocks = match self.encoding.blocks {
78            crate::image::Blocks::ScanLines => crate::meta::BlockDescription::ScanLines,
79            crate::image::Blocks::Tiles(tile_size) => {
80                let (level_mode, rounding_mode) = self.channel_data.infer_level_modes();
81                crate::meta::BlockDescription::Tiles(TileDescription { level_mode, rounding_mode, tile_size, })
82            },
83        };
84
85        let chunk_count = compute_chunk_count(
86            self.encoding.compression, self.size, blocks
87        );
88
89        let header = Header {
90            channels: self.channel_data.infer_channel_list(),
91            compression: self.encoding.compression,
92
93            blocks,
94            chunk_count,
95
96            line_order: self.encoding.line_order,
97            layer_size: self.size,
98            shared_attributes: image_attributes.clone(),
99            own_attributes: self.attributes.clone(),
100
101
102            deep: false, // TODO deep data
103            deep_data_version: None,
104            max_samples_per_pixel: None,
105        };
106
107        smallvec![ header ]// TODO no array-vs-first
108    }
109
110    type Writer = LayerWriter</*'l,*/ Channels::Writer>;
111    fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer {
112        let channels = self.channel_data
113            .create_writer(headers.first().expect("inferred header error")); // TODO no array-vs-first
114
115        LayerWriter { channels }
116    }
117}
118
119impl<C> LayersWriter for AllLayersWriter<C> where C: ChannelsWriter {
120    fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8> {
121        self.layers[block.layer].extract_uncompressed_block(std::slice::from_ref(&headers[block.layer]), block) // TODO no array-vs-first
122    }
123}
124
125impl<C> LayersWriter for LayerWriter<C> where C: ChannelsWriter {
126    fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8> {
127        self.channels.extract_uncompressed_block(headers.first().expect("invalid inferred header"), block) // TODO no array-vs-first
128    }
129}
130
131
132
133
134
135impl<'slf> WritableLayers<'slf> for NoneMore {
136    fn infer_headers(&self, _: &ImageAttributes) -> Headers { SmallVec::new() }
137
138    type Writer = NoneMore;
139    fn create_writer(&'slf self, _: &[Header]) -> Self::Writer { NoneMore }
140}
141
142impl<'slf, InnerLayers, Channels> WritableLayers<'slf> for Recursive<InnerLayers, Layer<Channels>>
143    where InnerLayers: WritableLayers<'slf>, Channels: WritableChannels<'slf>
144{
145    fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers {
146        let mut headers = self.inner.infer_headers(image_attributes);
147        headers.push(self.value.infer_headers(image_attributes).remove(0)); // TODO no unwrap
148        headers
149    }
150
151    type Writer = RecursiveLayersWriter<InnerLayers::Writer, Channels::Writer>;
152
153    fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer {
154        let (own_header, inner_headers) = headers.split_last()
155            .expect("header has not been inferred correctly");
156
157        let layer_index = inner_headers.len();
158        RecursiveLayersWriter {
159            inner: self.inner.create_writer(inner_headers),
160            value: (layer_index, self.value.create_writer(std::slice::from_ref(own_header))) // TODO no slice
161        }
162    }
163}
164
165type RecursiveLayersWriter<InnerLayersWriter, ChannelsWriter> = Recursive<InnerLayersWriter, (usize, LayerWriter<ChannelsWriter>)>;
166
167impl LayersWriter for NoneMore {
168    fn extract_uncompressed_block(&self, _: &[Header], _: BlockIndex) -> Vec<u8> {
169        panic!("recursive length mismatch bug");
170    }
171}
172
173impl<InnerLayersWriter, Channels> LayersWriter for RecursiveLayersWriter<InnerLayersWriter, Channels>
174    where InnerLayersWriter: LayersWriter, Channels: ChannelsWriter
175{
176    fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8> {
177        let (layer_index, layer) = &self.value;
178        if *layer_index == block.layer {
179            let header = headers.get(*layer_index).expect("layer index bug");
180            layer.extract_uncompressed_block(std::slice::from_ref(header), block) // TODO no slice?
181        }
182        else {
183            self.inner.extract_uncompressed_block(headers, block)
184        }
185    }
186}
187
188