aboutsummaryrefslogtreecommitdiff
path: root/vendor/exr/src/image/write
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/exr/src/image/write')
-rw-r--r--vendor/exr/src/image/write/channels.rs407
-rw-r--r--vendor/exr/src/image/write/layers.rs188
-rw-r--r--vendor/exr/src/image/write/mod.rs184
-rw-r--r--vendor/exr/src/image/write/samples.rs205
4 files changed, 0 insertions, 984 deletions
diff --git a/vendor/exr/src/image/write/channels.rs b/vendor/exr/src/image/write/channels.rs
deleted file mode 100644
index 2450f09..0000000
--- a/vendor/exr/src/image/write/channels.rs
+++ /dev/null
@@ -1,407 +0,0 @@
-//! How to read arbitrary channels and rgb channels.
-
-use crate::prelude::*;
-use crate::io::*;
-use crate::math::*;
-use crate::meta::{header::*, attribute::*};
-use crate::block::*;
-use crate::image::recursive::*;
-use crate::block::samples::*;
-use crate::image::write::samples::*;
-
-use std::marker::PhantomData;
-
-
-/// Enables an image containing this list of channels to be written to a file.
-pub trait WritableChannels<'slf> {
-
- /// Generate the file meta data for this list of channel
- fn infer_channel_list(&self) -> ChannelList;
-
- /// Generate the file meta data of whether and how resolution levels should be stored in the file
- fn infer_level_modes(&self) -> (LevelMode, RoundingMode);
-
- /// The type of temporary writer
- type Writer: ChannelsWriter;
-
- /// Create a temporary writer for this list of channels
- fn create_writer(&'slf self, header: &Header) -> Self::Writer;
-}
-
-/// A temporary writer for a list of channels
-pub trait ChannelsWriter: Sync {
-
- /// Deliver a block of pixels, containing all channel data, to be stored in the file
- fn extract_uncompressed_block(&self, header: &Header, block: BlockIndex) -> Vec<u8>; // TODO return uncompressed block?
-}
-
-
-/// Define how to get a pixel from your custom pixel storage.
-/// Can be a closure of type [`Sync + Fn(Vec2<usize>) -> YourPixel`].
-pub trait GetPixel: Sync {
-
- /// The pixel tuple containing `f32`, `f16`, `u32` and `Sample` values.
- /// The length of the tuple must match the number of channels in the image.
- type Pixel;
-
- /// Inspect a single pixel at the requested position.
- /// Will be called exactly once for each pixel in the image.
- /// The position will not exceed the image dimensions.
- /// Might be called from multiple threads at the same time.
- fn get_pixel(&self, position: Vec2<usize>) -> Self::Pixel;
-}
-
-impl<F, P> GetPixel for F where F: Sync + Fn(Vec2<usize>) -> P {
- type Pixel = P;
- fn get_pixel(&self, position: Vec2<usize>) -> P { self(position) }
-}
-
-impl<'samples, Samples> WritableChannels<'samples> for AnyChannels<Samples>
- where Samples: 'samples + WritableSamples<'samples>
-{
- fn infer_channel_list(&self) -> ChannelList {
- ChannelList::new(self.list.iter().map(|channel| ChannelDescription {
- name: channel.name.clone(),
- sample_type: channel.sample_data.sample_type(),
- quantize_linearly: channel.quantize_linearly,
- sampling: channel.sampling
- }).collect())
- }
-
- fn infer_level_modes(&self) -> (LevelMode, RoundingMode) {
- let mode = self.list.iter().next().expect("zero channels in list").sample_data.infer_level_modes();
-
- debug_assert!(
- std::iter::repeat(mode).zip(self.list.iter().skip(1))
- .all(|(first, other)| other.sample_data.infer_level_modes() == first),
-
- "level mode must be the same across all levels (do not nest resolution levels!)"
- );
-
- mode
- }
-
- type Writer = AnyChannelsWriter<Samples::Writer>;
- fn create_writer(&'samples self, header: &Header) -> Self::Writer {
- let channels = self.list.iter()
- .map(|chan| chan.sample_data.create_samples_writer(header))
- .collect();
-
- AnyChannelsWriter { channels }
- }
-}
-
-/// A temporary writer for an arbitrary list of channels
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct AnyChannelsWriter<SamplesWriter> {
- channels: SmallVec<[SamplesWriter; 4]>
-}
-
-impl<Samples> ChannelsWriter for AnyChannelsWriter<Samples> where Samples: SamplesWriter {
- fn extract_uncompressed_block(&self, header: &Header, block_index: BlockIndex) -> Vec<u8> {
- UncompressedBlock::collect_block_data_from_lines(&header.channels, block_index, |line_ref| {
- self.channels[line_ref.location.channel].extract_line(line_ref)
- })
- }
-}
-
-
-
-
-
-
-impl<'c, Channels, Storage>
-WritableChannels<'c> for SpecificChannels<Storage, Channels>
-where
- Storage: 'c + GetPixel,
- Storage::Pixel: IntoRecursive,
- Channels: 'c + Sync + Clone + IntoRecursive,
- <Channels as IntoRecursive>::Recursive: WritableChannelsDescription<<Storage::Pixel as IntoRecursive>::Recursive>,
-{
- fn infer_channel_list(&self) -> ChannelList {
- let mut vec = self.channels.clone().into_recursive().channel_descriptions_list();
- vec.sort_unstable_by_key(|channel:&ChannelDescription| channel.name.clone()); // TODO no clone?
-
- debug_assert!(
- // check for equal neighbors in sorted vec
- vec.iter().zip(vec.iter().skip(1)).all(|(prev, next)| prev.name != next.name),
- "specific channels contain duplicate channel names"
- );
-
- ChannelList::new(vec)
- }
-
- fn infer_level_modes(&self) -> (LevelMode, RoundingMode) {
- (LevelMode::Singular, RoundingMode::Down) // TODO
- }
-
- type Writer = SpecificChannelsWriter<
- 'c,
- <<Channels as IntoRecursive>::Recursive as WritableChannelsDescription<<Storage::Pixel as IntoRecursive>::Recursive>>::RecursiveWriter,
- Storage,
- Channels
- >;
-
- fn create_writer(&'c self, header: &Header) -> Self::Writer {
- SpecificChannelsWriter {
- channels: self,
- recursive_channel_writer: self.channels.clone().into_recursive().create_recursive_writer(&header.channels),
- }
- }
-}
-
-
-
-/// A temporary writer for a layer of channels, alpha being optional
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct SpecificChannelsWriter<'channels, PixelWriter, Storage, Channels> {
- channels: &'channels SpecificChannels<Storage, Channels>, // TODO this need not be a reference?? impl writer for specific_channels directly?
- recursive_channel_writer: PixelWriter,
-}
-
-
-impl<'channels, PxWriter, Storage, Channels> ChannelsWriter
-for SpecificChannelsWriter<'channels, PxWriter, Storage, Channels>
- where
- Channels: Sync,
- Storage: GetPixel,
- Storage::Pixel: IntoRecursive,
- PxWriter: Sync + RecursivePixelWriter<<Storage::Pixel as IntoRecursive>::Recursive>,
-{
- fn extract_uncompressed_block(&self, header: &Header, block_index: BlockIndex) -> Vec<u8> {
- let block_bytes = block_index.pixel_size.area() * header.channels.bytes_per_pixel;
- let mut block_bytes = vec![0_u8; block_bytes];
-
- let width = block_index.pixel_size.0;
- let line_bytes = width * header.channels.bytes_per_pixel;
- let byte_lines = block_bytes.chunks_exact_mut(line_bytes);
- assert_eq!(byte_lines.len(), block_index.pixel_size.height(), "invalid block line splits");
-
- //dbg!(width, line_bytes, header.channels.bytes_per_pixel, byte_lines.len());
-
- let mut pixel_line = Vec::with_capacity(width);
-
- for (y, line_bytes) in byte_lines.enumerate() {
- pixel_line.clear();
- pixel_line.extend((0 .. width).map(|x|
- self.channels.pixels.get_pixel(block_index.pixel_position + Vec2(x, y)).into_recursive()
- ));
-
- self.recursive_channel_writer.write_pixels(line_bytes, pixel_line.as_slice(), |px| px);
- }
-
- block_bytes
- }
-}
-
-/// A tuple containing either `ChannelsDescription` or `Option<ChannelsDescription>` entries.
-/// Use an `Option` if you want to dynamically omit a single channel (probably only for roundtrip tests).
-/// The number of entries must match the number of channels.
-pub trait WritableChannelsDescription<Pixel>: Sync {
-
- /// A type that has a recursive entry for each channel in the image,
- /// which must accept the desired pixel type.
- type RecursiveWriter: RecursivePixelWriter<Pixel>;
-
- /// Create the temporary writer, accepting the sorted list of channels from `channel_descriptions_list`.
- fn create_recursive_writer(&self, channels: &ChannelList) -> Self::RecursiveWriter;
-
- /// Return all the channels that should actually end up in the image, in any order.
- fn channel_descriptions_list(&self) -> SmallVec<[ChannelDescription; 5]>;
-}
-
-impl WritableChannelsDescription<NoneMore> for NoneMore {
- type RecursiveWriter = NoneMore;
- fn create_recursive_writer(&self, _: &ChannelList) -> Self::RecursiveWriter { NoneMore }
- fn channel_descriptions_list(&self) -> SmallVec<[ChannelDescription; 5]> { SmallVec::new() }
-}
-
-impl<InnerDescriptions, InnerPixel, Sample: IntoNativeSample>
- WritableChannelsDescription<Recursive<InnerPixel, Sample>>
- for Recursive<InnerDescriptions, ChannelDescription>
- where InnerDescriptions: WritableChannelsDescription<InnerPixel>
-{
- type RecursiveWriter = RecursiveWriter<InnerDescriptions::RecursiveWriter, Sample>;
-
- fn create_recursive_writer(&self, channels: &ChannelList) -> Self::RecursiveWriter {
- // this linear lookup is required because the order of the channels changed, due to alphabetical sorting
- let (start_byte_offset, target_sample_type) = channels.channels_with_byte_offset()
- .find(|(_offset, channel)| channel.name == self.value.name)
- .map(|(offset, channel)| (offset, channel.sample_type))
- .expect("a channel has not been put into channel list");
-
- Recursive::new(self.inner.create_recursive_writer(channels), SampleWriter {
- start_byte_offset, target_sample_type,
- px: PhantomData::default()
- })
- }
-
- fn channel_descriptions_list(&self) -> SmallVec<[ChannelDescription; 5]> {
- let mut inner_list = self.inner.channel_descriptions_list();
- inner_list.push(self.value.clone());
- inner_list
- }
-}
-
-impl<InnerDescriptions, InnerPixel, Sample: IntoNativeSample>
-WritableChannelsDescription<Recursive<InnerPixel, Sample>>
-for Recursive<InnerDescriptions, Option<ChannelDescription>>
- where InnerDescriptions: WritableChannelsDescription<InnerPixel>
-{
- type RecursiveWriter = OptionalRecursiveWriter<InnerDescriptions::RecursiveWriter, Sample>;
-
- fn create_recursive_writer(&self, channels: &ChannelList) -> Self::RecursiveWriter {
- // this linear lookup is required because the order of the channels changed, due to alphabetical sorting
-
- let channel = self.value.as_ref().map(|required_channel|
- channels.channels_with_byte_offset()
- .find(|(_offset, channel)| channel == &required_channel)
- .map(|(offset, channel)| (offset, channel.sample_type))
- .expect("a channel has not been put into channel list")
- );
-
- Recursive::new(
- self.inner.create_recursive_writer(channels),
- channel.map(|(start_byte_offset, target_sample_type)| SampleWriter {
- start_byte_offset, target_sample_type,
- px: PhantomData::default(),
- })
- )
- }
-
- fn channel_descriptions_list(&self) -> SmallVec<[ChannelDescription; 5]> {
- let mut inner_list = self.inner.channel_descriptions_list();
- if let Some(value) = &self.value { inner_list.push(value.clone()); }
- inner_list
- }
-}
-
-/// Write pixels to a slice of bytes. The top level writer contains all the other channels,
-/// the most inner channel is `NoneMore`.
-pub trait RecursivePixelWriter<Pixel>: Sync {
-
- /// Write pixels to a slice of bytes. Recursively do this for all channels.
- fn write_pixels<FullPixel>(&self, bytes: &mut [u8], pixels: &[FullPixel], get_pixel: impl Fn(&FullPixel) -> &Pixel);
-}
-
-type RecursiveWriter<Inner, Sample> = Recursive<Inner, SampleWriter<Sample>>;
-type OptionalRecursiveWriter<Inner, Sample> = Recursive<Inner, Option<SampleWriter<Sample>>>;
-
-/// Write the pixels of a single channel, unconditionally. Generic over the concrete sample type (f16, f32, u32).
-#[derive(Debug, Clone)]
-pub struct SampleWriter<Sample> {
- target_sample_type: SampleType,
- start_byte_offset: usize,
- px: PhantomData<Sample>,
-}
-
-impl<Sample> SampleWriter<Sample> where Sample: IntoNativeSample {
- fn write_own_samples(&self, bytes: &mut [u8], samples: impl ExactSizeIterator<Item=Sample>) {
- let byte_start_index = samples.len() * self.start_byte_offset;
- let byte_count = samples.len() * self.target_sample_type.bytes_per_sample();
- let ref mut byte_writer = &mut bytes[byte_start_index..byte_start_index + byte_count];
-
- let write_error_msg = "invalid memory buffer length when writing";
-
- // match outside the loop to avoid matching on every single sample
- match self.target_sample_type {
- // TODO does this boil down to a `memcpy` where the sample type equals the type parameter?
- SampleType::F16 => for sample in samples { sample.to_f16().write(byte_writer).expect(write_error_msg); },
- SampleType::F32 => for sample in samples { sample.to_f32().write(byte_writer).expect(write_error_msg); },
- SampleType::U32 => for sample in samples { sample.to_u32().write(byte_writer).expect(write_error_msg); },
- };
-
- debug_assert!(byte_writer.is_empty(), "all samples are written, but more were expected");
- }
-}
-
-impl RecursivePixelWriter<NoneMore> for NoneMore {
- fn write_pixels<FullPixel>(&self, _: &mut [u8], _: &[FullPixel], _: impl Fn(&FullPixel) -> &NoneMore) {}
-}
-
-impl<Inner, InnerPixel, Sample: IntoNativeSample>
- RecursivePixelWriter<Recursive<InnerPixel, Sample>>
- for RecursiveWriter<Inner, Sample>
- where Inner: RecursivePixelWriter<InnerPixel>
-{
- // TODO impl exact size iterator <item = Self::Pixel>
- fn write_pixels<FullPixel>(&self, bytes: &mut [u8], pixels: &[FullPixel], get_pixel: impl Fn(&FullPixel) -> &Recursive<InnerPixel, Sample>){
- self.value.write_own_samples(bytes, pixels.iter().map(|px| get_pixel(px).value));
- self.inner.write_pixels(bytes, pixels, |px| &get_pixel(px).inner);
- }
-}
-
-impl<Inner, InnerPixel, Sample> RecursivePixelWriter<Recursive<InnerPixel, Sample>>
- for OptionalRecursiveWriter<Inner, Sample>
- where Inner: RecursivePixelWriter<InnerPixel>,
- Sample: IntoNativeSample
-{
- fn write_pixels<FullPixel>(&self, bytes: &mut [u8], pixels: &[FullPixel], get_pixel: impl Fn(&FullPixel) -> &Recursive<InnerPixel, Sample>) {
- if let Some(writer) = &self.value {
- writer.write_own_samples(bytes, pixels.iter().map(|px| get_pixel(px).value));
- }
-
- self.inner.write_pixels(bytes, pixels, |px| &get_pixel(px).inner);
- }
-}
-
-
-
-
-
-
-
-#[cfg(test)]
-pub mod test {
- use crate::image::write::channels::WritableChannels;
- use crate::image::SpecificChannels;
- use crate::prelude::{f16};
- use crate::meta::attribute::{ChannelDescription, SampleType};
- use crate::image::pixel_vec::PixelVec;
-
- #[test]
- fn compiles(){
- let x = 3_f32;
- let y = f16::from_f32(4.0);
- let z = 2_u32;
- let s = 1.3_f32;
- let px = (x,y,z,s);
-
- assert_is_writable_channels(
- SpecificChannels::rgba(|_pos| px)
- );
-
- assert_is_writable_channels(SpecificChannels::rgba(
- PixelVec::new((3, 2), vec![px, px, px, px, px, px])
- ));
-
- let px = (2333_u32, 4_f32);
- assert_is_writable_channels(
- SpecificChannels::build()
- .with_channel("A")
- .with_channel("C")
- .with_pixels(PixelVec::new((3, 2), vec![px, px, px, px, px, px]))
- );
-
- let px = (3_f32, f16::ONE, 2333_u32, 4_f32);
- assert_is_writable_channels(SpecificChannels::new(
- (
- ChannelDescription::named("x", SampleType::F32),
- ChannelDescription::named("y", SampleType::F16),
- Some(ChannelDescription::named("z", SampleType::U32)),
- Some(ChannelDescription::named("p", SampleType::F32)),
- ),
-
- PixelVec::new((3, 2), vec![px, px, px, px, px, px])
- ));
-
-
-
- fn assert_is_writable_channels<'s>(_channels: impl WritableChannels<'s>){}
-
- }
-}
-
-
-
-
diff --git a/vendor/exr/src/image/write/layers.rs b/vendor/exr/src/image/write/layers.rs
deleted file mode 100644
index 85648ff..0000000
--- a/vendor/exr/src/image/write/layers.rs
+++ /dev/null
@@ -1,188 +0,0 @@
-//! 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)
- }
- }
-}
-
-
diff --git a/vendor/exr/src/image/write/mod.rs b/vendor/exr/src/image/write/mod.rs
deleted file mode 100644
index 3c20060..0000000
--- a/vendor/exr/src/image/write/mod.rs
+++ /dev/null
@@ -1,184 +0,0 @@
-
-//! Write an exr image to a file.
-//!
-//! First, call `my_image.write()`. The resulting value can be customized, like this:
-//! ```no_run
-//! use exr::prelude::*;
-//! # let my_image: FlatImage = unimplemented!();
-//!
-//! my_image.write()
-//! .on_progress(|progress| println!("progress: {:.1}", progress*100.0))
-//! .to_file("image.exr").unwrap();
-//! ```
-//!
-
-pub mod layers;
-pub mod samples;
-pub mod channels;
-
-
-
-use crate::meta::Headers;
-use crate::error::UnitResult;
-use std::io::{Seek, BufWriter};
-use crate::io::Write;
-use crate::image::{Image, ignore_progress, SpecificChannels, IntoSample};
-use crate::image::write::layers::{WritableLayers, LayersWriter};
-use crate::math::Vec2;
-use crate::block::writer::ChunksWriter;
-
-/// An oversimplified function for "just write the damn file already" use cases.
-/// Have a look at the examples to see how you can write an image with more flexibility (it's not that hard).
-/// Use `write_rgb_file` if you do not need an alpha channel.
-///
-/// Each of `R`, `G`, `B` and `A` can be either `f16`, `f32`, `u32`, or `Sample`.
-// TODO explain pixel tuple f32,f16,u32
-pub fn write_rgba_file<R,G,B,A>(
- path: impl AsRef<std::path::Path>, width: usize, height: usize,
- colors: impl Sync + Fn(usize, usize) -> (R, G, B, A)
-) -> UnitResult
- where R: IntoSample, G: IntoSample, B: IntoSample, A: IntoSample,
-{
- let channels = SpecificChannels::rgba(|Vec2(x,y)| colors(x,y));
- Image::from_channels((width, height), channels).write().to_file(path)
-}
-
-/// An oversimplified function for "just write the damn file already" use cases.
-/// Have a look at the examples to see how you can write an image with more flexibility (it's not that hard).
-/// Use `write_rgb_file` if you do not need an alpha channel.
-///
-/// Each of `R`, `G`, and `B` can be either `f16`, `f32`, `u32`, or `Sample`.
-// TODO explain pixel tuple f32,f16,u32
-pub fn write_rgb_file<R,G,B>(
- path: impl AsRef<std::path::Path>, width: usize, height: usize,
- colors: impl Sync + Fn(usize, usize) -> (R, G, B)
-) -> UnitResult
- where R: IntoSample, G: IntoSample, B: IntoSample
-{
- let channels = SpecificChannels::rgb(|Vec2(x,y)| colors(x,y));
- Image::from_channels((width, height), channels).write().to_file(path)
-}
-
-
-
-/// Enables an image to be written to a file. Call `image.write()` where this trait is implemented.
-pub trait WritableImage<'img, WritableLayers>: Sized {
-
- /// Create a temporary writer which can be configured and used to write the image to a file.
- fn write(self) -> WriteImageWithOptions<'img, WritableLayers, fn(f64)>;
-}
-
-impl<'img, WritableLayers> WritableImage<'img, WritableLayers> for &'img Image<WritableLayers> {
- fn write(self) -> WriteImageWithOptions<'img, WritableLayers, fn(f64)> {
- WriteImageWithOptions {
- image: self,
- check_compatibility: true,
- parallel: true,
- on_progress: ignore_progress
- }
- }
-}
-
-/// A temporary writer which can be configured and used to write an image to a file.
-// temporary writer with options
-#[derive(Debug, Clone, PartialEq)]
-pub struct WriteImageWithOptions<'img, Layers, OnProgress> {
- image: &'img Image<Layers>,
- on_progress: OnProgress,
- check_compatibility: bool,
- parallel: bool,
-}
-
-
-impl<'img, L, F> WriteImageWithOptions<'img, L, F>
- where L: WritableLayers<'img>, F: FnMut(f64)
-{
- /// Generate file meta data for this image. The meta data structure is close to the data in the file.
- pub fn infer_meta_data(&self) -> Headers { // TODO this should perform all validity checks? and none after that?
- self.image.layer_data.infer_headers(&self.image.attributes)
- }
-
- /// Do not compress multiple pixel blocks on multiple threads at once.
- /// Might use less memory and synchronization, but will be slower in most situations.
- pub fn non_parallel(self) -> Self { Self { parallel: false, ..self } }
-
- /// Skip some checks that ensure a file can be opened by other exr software.
- /// For example, it is no longer checked that no two headers or two attributes have the same name,
- /// which might be an expensive check for images with an exorbitant number of headers.
- ///
- /// If you write an uncompressed file and need maximum speed, it might save a millisecond to disable the checks,
- /// if you know that your file is not invalid any ways. I do not recommend this though,
- /// as the file might not be readably by any other exr library after that.
- /// __You must care for not producing an invalid file yourself.__
- pub fn skip_compatibility_checks(self) -> Self { Self { check_compatibility: false, ..self } }
-
- /// Specify a function to be called regularly throughout the writing process.
- /// Replaces all previously specified progress functions in this reader.
- pub fn on_progress<OnProgress>(self, on_progress: OnProgress) -> WriteImageWithOptions<'img, L, OnProgress>
- where OnProgress: FnMut(f64)
- {
- WriteImageWithOptions {
- on_progress,
- image: self.image,
- check_compatibility: self.check_compatibility,
- parallel: self.parallel
- }
- }
-
- /// Write the exr image to a file.
- /// Use `to_unbuffered` instead, if you do not have a file.
- /// If an error occurs, attempts to delete the partially written file.
- #[inline]
- #[must_use]
- pub fn to_file(self, path: impl AsRef<std::path::Path>) -> UnitResult {
- crate::io::attempt_delete_file_on_write_error(path.as_ref(), move |write|
- self.to_unbuffered(write)
- )
- }
-
- /// Buffer the writer and then write the exr image to it.
- /// Use `to_buffered` instead, if your writer is an in-memory buffer.
- /// Use `to_file` instead, if you have a file path.
- /// If your writer cannot seek, you can write to an in-memory vector of bytes first, using `to_buffered`.
- #[inline]
- #[must_use]
- pub fn to_unbuffered(self, unbuffered: impl Write + Seek) -> UnitResult {
- self.to_buffered(BufWriter::new(unbuffered))
- }
-
- /// Write the exr image to a writer.
- /// Use `to_file` instead, if you have a file path.
- /// Use `to_unbuffered` instead, if this is not an in-memory writer.
- /// If your writer cannot seek, you can write to an in-memory vector of bytes first.
- #[must_use]
- pub fn to_buffered(self, write: impl Write + Seek) -> UnitResult {
- let headers = self.infer_meta_data();
- let layers = self.image.layer_data.create_writer(&headers);
-
- crate::block::write(
- write, headers, self.check_compatibility,
- move |meta, chunk_writer|{
-
- let blocks = meta.collect_ordered_block_data(|block_index|
- layers.extract_uncompressed_block(&meta.headers, block_index)
- );
-
- let chunk_writer = chunk_writer.on_progress(self.on_progress);
- if self.parallel { chunk_writer.compress_all_blocks_parallel(&meta, blocks)?; }
- else { chunk_writer.compress_all_blocks_sequential(&meta, blocks)?; }
- /*let blocks_writer = chunk_writer.as_blocks_writer(&meta);
-
- // TODO propagate send requirement further upwards
- if self.parallel {
- blocks_writer.compress_all_blocks_parallel(blocks)?;
- }
- else {
- blocks_writer.compress_all_blocks_sequential(blocks)?;
- }*/
-
- Ok(())
- }
- )
- }
-}
-
diff --git a/vendor/exr/src/image/write/samples.rs b/vendor/exr/src/image/write/samples.rs
deleted file mode 100644
index e74105b..0000000
--- a/vendor/exr/src/image/write/samples.rs
+++ /dev/null
@@ -1,205 +0,0 @@
-//! How to write samples (a grid of `f32`, `f16` or `u32` values).
-
-use crate::meta::attribute::{LevelMode, SampleType, TileDescription};
-use crate::meta::header::Header;
-use crate::block::lines::LineRefMut;
-use crate::image::{FlatSamples, Levels, RipMaps};
-use crate::math::{Vec2, RoundingMode};
-use crate::meta::{rip_map_levels, mip_map_levels, rip_map_indices, mip_map_indices, BlockDescription};
-
-/// Enable an image with this sample grid to be written to a file.
-/// Also can contain multiple resolution levels.
-/// Usually contained within `Channels`.
-pub trait WritableSamples<'slf> {
- // fn is_deep(&self) -> bool;
-
- /// Generate the file meta data regarding the number type of this storage
- fn sample_type(&self) -> SampleType;
-
- /// Generate the file meta data regarding resolution levels
- fn infer_level_modes(&self) -> (LevelMode, RoundingMode);
-
- /// The type of the temporary writer for this sample storage
- type Writer: SamplesWriter;
-
- /// Create a temporary writer for this sample storage
- fn create_samples_writer(&'slf self, header: &Header) -> Self::Writer;
-}
-
-/// Enable an image with this single level sample grid to be written to a file.
-/// Only contained within `Levels`.
-pub trait WritableLevel<'slf> {
-
- /// Generate the file meta data regarding the number type of these samples
- fn sample_type(&self) -> SampleType;
-
- /// The type of the temporary writer for this single level of samples
- type Writer: SamplesWriter;
-
- /// Create a temporary writer for this single level of samples
- fn create_level_writer(&'slf self, size: Vec2<usize>) -> Self::Writer;
-}
-
-/// A temporary writer for one or more resolution levels containing samples
-pub trait SamplesWriter: Sync {
-
- /// Deliver a single short horizontal list of samples for a specific channel.
- fn extract_line(&self, line: LineRefMut<'_>);
-}
-
-/// A temporary writer for a predefined non-deep sample storage
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub struct FlatSamplesWriter<'samples> {
- resolution: Vec2<usize>, // respects resolution level
- samples: &'samples FlatSamples
-}
-
-
-
-// used if no layers are used and the flat samples are directly inside the channels
-impl<'samples> WritableSamples<'samples> for FlatSamples {
- fn sample_type(&self) -> SampleType {
- match self {
- FlatSamples::F16(_) => SampleType::F16,
- FlatSamples::F32(_) => SampleType::F32,
- FlatSamples::U32(_) => SampleType::U32,
- }
- }
-
- fn infer_level_modes(&self) -> (LevelMode, RoundingMode) { (LevelMode::Singular, RoundingMode::Down) }
-
- type Writer = FlatSamplesWriter<'samples>; //&'s FlatSamples;
- fn create_samples_writer(&'samples self, header: &Header) -> Self::Writer {
- FlatSamplesWriter {
- resolution: header.layer_size,
- samples: self
- }
- }
-}
-
-// used if layers are used and the flat samples are inside the levels
-impl<'samples> WritableLevel<'samples> for FlatSamples {
- fn sample_type(&self) -> SampleType {
- match self {
- FlatSamples::F16(_) => SampleType::F16,
- FlatSamples::F32(_) => SampleType::F32,
- FlatSamples::U32(_) => SampleType::U32,
- }
- }
-
- type Writer = FlatSamplesWriter<'samples>;
- fn create_level_writer(&'samples self, size: Vec2<usize>) -> Self::Writer {
- FlatSamplesWriter {
- resolution: size,
- samples: self
- }
- }
-}
-
-impl<'samples> SamplesWriter for FlatSamplesWriter<'samples> {
- fn extract_line(&self, line: LineRefMut<'_>) {
- let image_width = self.resolution.width(); // header.layer_size.width();
- debug_assert_ne!(image_width, 0, "image width calculation bug");
-
- let start_index = line.location.position.y() * image_width + line.location.position.x();
- let end_index = start_index + line.location.sample_count;
-
- debug_assert!(
- start_index < end_index && end_index <= self.samples.len(),
- "for resolution {:?}, this is an invalid line: {:?}",
- self.resolution, line.location
- );
-
- match self.samples {
- FlatSamples::F16(samples) => line.write_samples_from_slice(&samples[start_index .. end_index]),
- FlatSamples::F32(samples) => line.write_samples_from_slice(&samples[start_index .. end_index]),
- FlatSamples::U32(samples) => line.write_samples_from_slice(&samples[start_index .. end_index]),
- }.expect("writing line bytes failed");
- }
-}
-
-
-impl<'samples, LevelSamples> WritableSamples<'samples> for Levels<LevelSamples>
- where LevelSamples: WritableLevel<'samples>
-{
- fn sample_type(&self) -> SampleType {
- let sample_type = self.levels_as_slice().first().expect("no levels found").sample_type();
-
- debug_assert!(
- self.levels_as_slice().iter().skip(1).all(|ty| ty.sample_type() == sample_type),
- "sample types must be the same across all levels"
- );
-
- sample_type
- }
-
- fn infer_level_modes(&self) -> (LevelMode, RoundingMode) {
- match self {
- Levels::Singular(_) => (LevelMode::Singular, RoundingMode::Down),
- Levels::Mip { rounding_mode, .. } => (LevelMode::MipMap, *rounding_mode),
- Levels::Rip { rounding_mode, .. } => (LevelMode::RipMap, *rounding_mode),
- }
- }
-
- type Writer = LevelsWriter<LevelSamples::Writer>;
- fn create_samples_writer(&'samples self, header: &Header) -> Self::Writer {
- let rounding = match header.blocks {
- BlockDescription::Tiles(TileDescription { rounding_mode, .. }) => Some(rounding_mode),
- BlockDescription::ScanLines => None,
- };
-
- LevelsWriter {
- levels: match self {
- Levels::Singular(level) => Levels::Singular(level.create_level_writer(header.layer_size)),
- Levels::Mip { level_data, rounding_mode } => {
- debug_assert_eq!(
- level_data.len(),
- mip_map_indices(rounding.expect("mip maps only with tiles"), header.layer_size).count(),
- "invalid mip map count"
- );
-
- Levels::Mip { // TODO store level size in image??
- rounding_mode: *rounding_mode,
- level_data: level_data.iter()
- .zip(mip_map_levels(rounding.expect("mip maps only with tiles"), header.layer_size))
- // .map(|level| level.create_samples_writer(header))
- .map(|(level, (_level_index, level_size))| level.create_level_writer(level_size))
- .collect()
- }
- },
- Levels::Rip { level_data, rounding_mode } => {
- debug_assert_eq!(level_data.map_data.len(), level_data.level_count.area(), "invalid rip level count");
- debug_assert_eq!(
- level_data.map_data.len(),
- rip_map_indices(rounding.expect("rip maps only with tiles"), header.layer_size).count(),
- "invalid rip map count"
- );
-
- Levels::Rip {
- rounding_mode: *rounding_mode,
- level_data: RipMaps {
- level_count: level_data.level_count,
- map_data: level_data.map_data.iter()
- .zip(rip_map_levels(rounding.expect("rip maps only with tiles"), header.layer_size))
- .map(|(level, (_level_index, level_size))| level.create_level_writer(level_size))
- .collect(),
- }
- }
- }
- }
- }
- }
-}
-
-/// A temporary writer for multiple resolution levels
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct LevelsWriter<SamplesWriter> {
- levels: Levels<SamplesWriter>,
-}
-
-impl<Samples> SamplesWriter for LevelsWriter<Samples> where Samples: SamplesWriter {
- fn extract_line(&self, line: LineRefMut<'_>) {
- self.levels.get_level(line.location.level).expect("invalid level index") // TODO compute level size from line index??
- .extract_line(line)
- }
-}