Merge pull request #343 from Shnatsel/float-predictor-opt
Optimize floating-point predictor encoding
This commit is contained in:
commit
9a9193345c
3 files changed
+55
-7
No files matched your search
@@ -50,6 +50,10 @@ zstd = ["dep:zstd"]
|
|||||||
name = "lzw"
|
name = "lzw"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "encode"
|
||||||
|
harness = false
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "decode_libtiffpic"
|
name = "decode_libtiffpic"
|
||||||
path = "tests/decode_libtiffpic.rs"
|
path = "tests/decode_libtiffpic.rs"
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
extern crate criterion;
|
||||||
|
extern crate tiff;
|
||||||
|
|
||||||
|
use criterion::{black_box, Criterion, Throughput};
|
||||||
|
use std::io::Cursor;
|
||||||
|
use tiff::encoder::colortype::RGB32Float;
|
||||||
|
use tiff::encoder::{Compression, DeflateLevel, Predictor, TiffEncoder};
|
||||||
|
|
||||||
|
const WIDTH: u32 = 500;
|
||||||
|
const HEIGHT: u32 = 500;
|
||||||
|
|
||||||
|
fn encode_image_f32_float_predictor_deflate(data: &[f32]) {
|
||||||
|
let mut buf = Cursor::new(Vec::with_capacity(WIDTH as usize * HEIGHT as usize * 4));
|
||||||
|
TiffEncoder::new(&mut buf)
|
||||||
|
.unwrap()
|
||||||
|
.with_predictor(Predictor::FloatingPoint)
|
||||||
|
.with_compression(Compression::Deflate(DeflateLevel::Fast))
|
||||||
|
.write_image::<RGB32Float>(WIDTH, HEIGHT, black_box(data))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Generate synthetic f32 image data with a gradient pattern
|
||||||
|
let data: Vec<f32> = (0..WIDTH as usize * HEIGHT as usize * 3)
|
||||||
|
.map(|i| {
|
||||||
|
let pixel = i / 3;
|
||||||
|
let x = (pixel % WIDTH as usize) as f32 / WIDTH as f32;
|
||||||
|
let y = (pixel / WIDTH as usize) as f32 / HEIGHT as f32;
|
||||||
|
x * 0.5 + y * 0.5
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut c = Criterion::default().configure_from_args();
|
||||||
|
let mut group = c.benchmark_group("tiff-encode");
|
||||||
|
|
||||||
|
group
|
||||||
|
.sample_size(20)
|
||||||
|
.throughput(Throughput::Bytes(
|
||||||
|
(WIDTH as u64) * (HEIGHT as u64) * 3 * std::mem::size_of::<f32>() as u64,
|
||||||
|
))
|
||||||
|
.bench_function("f32-float-predictor-deflate-fast", |b| {
|
||||||
|
b.iter(|| encode_image_f32_float_predictor_deflate(&data))
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -18,15 +18,15 @@ macro_rules! fp_predict {
|
|||||||
let byte_count = num_values * BYTE_SIZE;
|
let byte_count = num_values * BYTE_SIZE;
|
||||||
let start_len = result.len();
|
let start_len = result.len();
|
||||||
|
|
||||||
// Reserve space for the output
|
// Allocate zeroed space so we can write to arbitrary positions
|
||||||
result.reserve(byte_count);
|
result.resize(start_len + byte_count, 0);
|
||||||
|
let output = &mut result[start_len..];
|
||||||
|
|
||||||
// Step 1 & 2: Convert to big-endian and shuffle bytes
|
// Step 1 & 2: Convert to big-endian and scatter bytes
|
||||||
// All first bytes, then all second bytes, etc.
|
for (i, &value) in row.iter().enumerate() {
|
||||||
for byte_idx in 0..BYTE_SIZE {
|
|
||||||
for &value in row {
|
|
||||||
let bytes = value.to_be_bytes();
|
let bytes = value.to_be_bytes();
|
||||||
result.push(bytes[byte_idx]);
|
for b in 0..BYTE_SIZE {
|
||||||
|
output[b * num_values + i] = bytes[b];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user