Skip to content

Commit

Permalink
reduce low-level byte fiddling in openexr encoder (#2012)
Browse files Browse the repository at this point in the history
* use more high-level function `pod_read_unaligned` to read [f32;3] array instead of manually constructing it component by component

* reformat with rustfmt

* beautify (apply clippy suggestions)
  • Loading branch information
johannesvollmer authored Oct 15, 2023
1 parent 6139e8d commit ff2f67e
Showing 1 changed file with 17 additions and 22 deletions.
39 changes: 17 additions & 22 deletions src/codecs/openexr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use crate::{
ColorType, ExtendedColorType, ImageDecoder, ImageEncoder, ImageError, ImageFormat, ImageResult,
Progress,
};
use std::convert::TryInto;
use std::io::{Cursor, Read, Seek, Write};

/// An OpenEXR decoder. Immediately reads the meta data from the file.
Expand Down Expand Up @@ -272,27 +271,22 @@ fn write_buffer(
}
}

// bytes might be unaligned so we cannot cast the whole thing, instead lookup each f32 individually
let lookup_f32 = move |f32_index: usize| {
let unaligned_f32_bytes_slice = &unaligned_bytes[f32_index * 4..(f32_index + 1) * 4];
let f32_bytes_array = unaligned_f32_bytes_slice
.try_into()
.expect("indexing error");
f32::from_ne_bytes(f32_bytes_array)
};
let bytes_per_pixel = color_type.bytes_per_pixel() as usize;

match color_type {
ColorType::Rgb32F => {
exr::prelude::Image // TODO compression method zip??
::from_channels(
(width, height),
SpecificChannels::rgb(|pixel: Vec2<usize>| {
let pixel_index = 3 * pixel.flat_index_for_size(Vec2(width, height));
(
lookup_f32(pixel_index),
lookup_f32(pixel_index + 1),
lookup_f32(pixel_index + 2),
)
let pixel_index = pixel.flat_index_for_size(Vec2(width, height));
let start_byte = pixel_index * bytes_per_pixel;

let [r, g, b]: [f32; 3] = bytemuck::pod_read_unaligned(
&unaligned_bytes[start_byte..start_byte + bytes_per_pixel],
);

(r, g, b)
}),
)
.write()
Expand All @@ -306,13 +300,14 @@ fn write_buffer(
::from_channels(
(width, height),
SpecificChannels::rgba(|pixel: Vec2<usize>| {
let pixel_index = 4 * pixel.flat_index_for_size(Vec2(width, height));
(
lookup_f32(pixel_index),
lookup_f32(pixel_index + 1),
lookup_f32(pixel_index + 2),
lookup_f32(pixel_index + 3),
)
let pixel_index = pixel.flat_index_for_size(Vec2(width, height));
let start_byte = pixel_index * bytes_per_pixel;

let [r, g, b, a]: [f32; 4] = bytemuck::pod_read_unaligned(
&unaligned_bytes[start_byte..start_byte + bytes_per_pixel],
);

(r, g, b, a)
}),
)
.write()
Expand Down

0 comments on commit ff2f67e

Please sign in to comment.