summaryrefslogtreecommitdiff
path: root/vendor/exr/src/image/write/layers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/exr/src/image/write/layers.rs')
-rw-r--r--vendor/exr/src/image/write/layers.rs188
1 files changed, 188 insertions, 0 deletions
diff --git a/vendor/exr/src/image/write/layers.rs b/vendor/exr/src/image/write/layers.rs
new file mode 100644
index 0000000..85648ff
--- /dev/null
+++ b/vendor/exr/src/image/write/layers.rs
@@ -0,0 +1,188 @@
+//! How to write either a single or a list of layers.
+
+use crate::meta::header::{ImageAttributes, Header};
+use crate::meta::{Headers, compute_chunk_count};
+use crate::block::BlockIndex;
+use crate::image::{Layers, Layer};
+use crate::meta::attribute::{TileDescription};
+use crate::prelude::{SmallVec};
+use crate::image::write::channels::{WritableChannels, ChannelsWriter};
+use crate::image::recursive::{Recursive, NoneMore};
+
+/// Enables an image containing this list of layers to be written to a file.
+pub trait WritableLayers<'slf> {
+
+ /// Generate the file meta data for this list of layers
+ fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers;
+
+ /// The type of temporary writer
+ type Writer: LayersWriter;
+
+ /// Create a temporary writer for this list of layers
+ fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer;
+}
+
+/// A temporary writer for a list of channels
+pub trait LayersWriter: Sync {
+
+ /// Deliver a block of pixels from a single layer to be stored in the file
+ fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8>;
+}
+
+/// A temporary writer for an arbitrary list of layers
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct AllLayersWriter<ChannelsWriter> {
+ layers: SmallVec<[LayerWriter<ChannelsWriter>; 2]>
+}
+
+/// A temporary writer for a single layer
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct LayerWriter<ChannelsWriter> {
+ channels: ChannelsWriter, // impl ChannelsWriter
+}
+
+// impl for smallvec
+impl<'slf, Channels: 'slf> WritableLayers<'slf> for Layers<Channels> where Channels: WritableChannels<'slf> {
+ fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers {
+ slice_infer_headers(self.as_slice(), image_attributes)
+ }
+
+ type Writer = AllLayersWriter<Channels::Writer>;
+ fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer {
+ slice_create_writer(self.as_slice(), headers)
+ }
+}
+
+fn slice_infer_headers<'slf, Channels:'slf + WritableChannels<'slf>>(
+ slice: &[Layer<Channels>], image_attributes: &ImageAttributes
+) -> Headers
+{
+ slice.iter().map(|layer| layer.infer_headers(image_attributes).remove(0)).collect() // TODO no array-vs-first
+}
+
+fn slice_create_writer<'slf, Channels:'slf + WritableChannels<'slf>>(
+ slice: &'slf [Layer<Channels>], headers: &[Header]
+) -> AllLayersWriter<Channels::Writer>
+{
+ AllLayersWriter {
+ layers: slice.iter().zip(headers.chunks_exact(1)) // TODO no array-vs-first
+ .map(|(layer, header)| layer.create_writer(header))
+ .collect()
+ }
+}
+
+
+impl<'slf, Channels: WritableChannels<'slf>> WritableLayers<'slf> for Layer<Channels> {
+ fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers {
+ let blocks = match self.encoding.blocks {
+ crate::image::Blocks::ScanLines => crate::meta::BlockDescription::ScanLines,
+ crate::image::Blocks::Tiles(tile_size) => {
+ let (level_mode, rounding_mode) = self.channel_data.infer_level_modes();
+ crate::meta::BlockDescription::Tiles(TileDescription { level_mode, rounding_mode, tile_size, })
+ },
+ };
+
+ let chunk_count = compute_chunk_count(
+ self.encoding.compression, self.size, blocks
+ );
+
+ let header = Header {
+ channels: self.channel_data.infer_channel_list(),
+ compression: self.encoding.compression,
+
+ blocks,
+ chunk_count,
+
+ line_order: self.encoding.line_order,
+ layer_size: self.size,
+ shared_attributes: image_attributes.clone(),
+ own_attributes: self.attributes.clone(),
+
+
+ deep: false, // TODO deep data
+ deep_data_version: None,
+ max_samples_per_pixel: None,
+ };
+
+ smallvec![ header ]// TODO no array-vs-first
+ }
+
+ type Writer = LayerWriter</*'l,*/ Channels::Writer>;
+ fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer {
+ let channels = self.channel_data
+ .create_writer(headers.first().expect("inferred header error")); // TODO no array-vs-first
+
+ LayerWriter { channels }
+ }
+}
+
+impl<C> LayersWriter for AllLayersWriter<C> where C: ChannelsWriter {
+ fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8> {
+ self.layers[block.layer].extract_uncompressed_block(std::slice::from_ref(&headers[block.layer]), block) // TODO no array-vs-first
+ }
+}
+
+impl<C> LayersWriter for LayerWriter<C> where C: ChannelsWriter {
+ fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8> {
+ self.channels.extract_uncompressed_block(headers.first().expect("invalid inferred header"), block) // TODO no array-vs-first
+ }
+}
+
+
+
+
+
+impl<'slf> WritableLayers<'slf> for NoneMore {
+ fn infer_headers(&self, _: &ImageAttributes) -> Headers { SmallVec::new() }
+
+ type Writer = NoneMore;
+ fn create_writer(&'slf self, _: &[Header]) -> Self::Writer { NoneMore }
+}
+
+impl<'slf, InnerLayers, Channels> WritableLayers<'slf> for Recursive<InnerLayers, Layer<Channels>>
+ where InnerLayers: WritableLayers<'slf>, Channels: WritableChannels<'slf>
+{
+ fn infer_headers(&self, image_attributes: &ImageAttributes) -> Headers {
+ let mut headers = self.inner.infer_headers(image_attributes);
+ headers.push(self.value.infer_headers(image_attributes).remove(0)); // TODO no unwrap
+ headers
+ }
+
+ type Writer = RecursiveLayersWriter<InnerLayers::Writer, Channels::Writer>;
+
+ fn create_writer(&'slf self, headers: &[Header]) -> Self::Writer {
+ let (own_header, inner_headers) = headers.split_last()
+ .expect("header has not been inferred correctly");
+
+ let layer_index = inner_headers.len();
+ RecursiveLayersWriter {
+ inner: self.inner.create_writer(inner_headers),
+ value: (layer_index, self.value.create_writer(std::slice::from_ref(own_header))) // TODO no slice
+ }
+ }
+}
+
+type RecursiveLayersWriter<InnerLayersWriter, ChannelsWriter> = Recursive<InnerLayersWriter, (usize, LayerWriter<ChannelsWriter>)>;
+
+impl LayersWriter for NoneMore {
+ fn extract_uncompressed_block(&self, _: &[Header], _: BlockIndex) -> Vec<u8> {
+ panic!("recursive length mismatch bug");
+ }
+}
+
+impl<InnerLayersWriter, Channels> LayersWriter for RecursiveLayersWriter<InnerLayersWriter, Channels>
+ where InnerLayersWriter: LayersWriter, Channels: ChannelsWriter
+{
+ fn extract_uncompressed_block(&self, headers: &[Header], block: BlockIndex) -> Vec<u8> {
+ let (layer_index, layer) = &self.value;
+ if *layer_index == block.layer {
+ let header = headers.get(*layer_index).expect("layer index bug");
+ layer.extract_uncompressed_block(std::slice::from_ref(header), block) // TODO no slice?
+ }
+ else {
+ self.inner.extract_uncompressed_block(headers, block)
+ }
+ }
+}
+
+