Files
DarkRoom/third_party/rawler-0.7.2/src/decompressors/packed.rs
T
dtourolle 77a1925bac Vendor rawler 0.7.2 unmodified
The crate as crates.io publishes it, minus .cargo-ok, its Cargo.lock and
data/testdata (13 MB of sample files only its own tests read). Not yet
routed through [patch.crates-io]; the next commit is the patch.
2026-09-27 17:33:19 -04:00

220 lines
7.8 KiB
Rust

use multiversion::multiversion;
use crate::bits::{BEf16, BEf24, BEf32, BEu16, LEf16, LEf24, LEf32, LEu16};
use crate::decompressors::LineIteratorMut;
use crate::pumps::{BitPump, BitPumpMSB};
use crate::{bits::Endian, decompressors::Decompressor};
/// Decompressor for packed data
pub struct PackedDecompressor {
bps: u32,
endian: Endian,
}
impl PackedDecompressor {
pub fn new(bps: u32, endian: Endian) -> Self {
Self { bps, endian }
}
}
impl<'a> Decompressor<'a, u16> for PackedDecompressor {
fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, u16>, line_width: usize) -> std::result::Result<(), String> {
match (self.endian, self.bps) {
// 16 bits, encoding depends on TIFF endianess
(Endian::Big, 16) => unpack_16be(lines, src, skip_rows, line_width),
(Endian::Little, 16) => unpack_16le(lines, src, skip_rows, line_width),
// 12 Bits, DNG spec says it must be always encoded as big-endian
(_, 12) => unpack_12be(lines, src, skip_rows, line_width),
// 10 Bits, DNG spec says it must be always encoded as big-endian
(_, 10) => unpack_10be(lines, src, skip_rows, line_width),
// 8 bits
(_, 8) => unpack_8bit(lines, src, skip_rows, line_width),
// Generic MSB decoder for exotic packed bit sizes
(_, bps) if bps > 0 && bps < 16 => unpack_generic_msb(lines, src, skip_rows, line_width, self.bps),
// Unhandled bits
(_, bps) => return Err(format_args!("DNG: Don't know how to handle DNG with {} bps", bps).to_string()),
}
Ok(())
}
fn strips_optimized(&self) -> bool {
true
}
fn tile_optimized(&self) -> bool {
true
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_16be<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) {
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * 2)..];
for (out, bytes) in line.iter_mut().zip(inb.chunks_exact(2)) {
*out = BEu16(bytes, 0);
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_16le<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) {
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * 2)..];
for (i, bytes) in (0..width).zip(inb.chunks_exact(2)) {
line[i] = LEu16(bytes, 0);
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_12be<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) {
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * 12 / 8)..];
for (o, i) in line.chunks_exact_mut(2).zip(inb.chunks_exact(3)) {
let g1: u16 = i[0] as u16;
let g2: u16 = i[1] as u16;
let g3: u16 = i[2] as u16;
o[0] = (g1 << 4) | (g2 >> 4);
o[1] = ((g2 & 0x0f) << 8) | g3;
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_10be<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) {
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * 10 / 8)..];
for (o, i) in line.chunks_exact_mut(4).zip(inb.chunks_exact(5)) {
let g1: u16 = i[0] as u16;
let g2: u16 = i[1] as u16;
let g3: u16 = i[2] as u16;
let g4: u16 = i[3] as u16;
let g5: u16 = i[4] as u16;
o[0] = (g1 << 2) | (g2 >> 6);
o[1] = ((g2 & 0x3f) << 4) | (g3 >> 4);
o[2] = ((g3 & 0x0f) << 6) | (g4 >> 2);
o[3] = ((g4 & 0x03) << 8) | g5;
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_8bit<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize) {
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width)..];
for (o, i) in line.iter_mut().zip(inb.iter()) {
*o = *i as u16;
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_generic_msb<'a>(lines: impl LineIteratorMut<'a, u16>, src: &[u8], skip_rows: usize, width: usize, bits: u32) {
assert!(bits <= 16);
let skip_bits = skip_rows * width * bits as usize;
let offset = skip_bits / 8;
let bias = skip_bits % 8;
let mut pump = BitPumpMSB::new(&src[offset..]);
pump.consume_bits(bias as u32);
for line in lines {
for p in line {
*p = pump.get_bits(bits) as u16;
}
}
}
impl<'a> Decompressor<'a, f32> for PackedDecompressor {
fn decompress(&self, src: &[u8], skip_rows: usize, lines: impl LineIteratorMut<'a, f32>, line_width: usize) -> std::result::Result<(), String> {
match (self.endian, self.bps) {
// 16 bits, encoding depends on TIFF endianess
(Endian::Big, 32) => unpack_f32be(lines, src, skip_rows, line_width),
(Endian::Little, 32) => unpack_f32le(lines, src, skip_rows, line_width),
(Endian::Big, 24) => unpack_f24be(lines, src, skip_rows, line_width),
(Endian::Little, 24) => unpack_f24le(lines, src, skip_rows, line_width),
(Endian::Big, 16) => unpack_f16be(lines, src, skip_rows, line_width),
(Endian::Little, 16) => unpack_f16le(lines, src, skip_rows, line_width),
// Unhandled bits
(_, bps) => return Err(format_args!("DNG: Don't know how to handle FP DNG with {} bps", bps).to_string()),
}
Ok(())
}
fn strips_optimized(&self) -> bool {
true
}
fn tile_optimized(&self) -> bool {
true
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_f32be<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) {
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * size_of::<f32>())..];
for (i, bytes) in (0..width).zip(inb.chunks_exact(4)) {
line[i] = BEf32(bytes, 0);
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_f32le<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) {
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * size_of::<f32>())..];
for (i, bytes) in (0..width).zip(inb.chunks_exact(4)) {
line[i] = LEf32(bytes, 0);
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_f24le<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) {
const SIZEOF_FP24: usize = 3;
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * SIZEOF_FP24)..];
for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP24)) {
line[i] = LEf24(bytes, 0);
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_f24be<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) {
const SIZEOF_FP24: usize = 3;
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * SIZEOF_FP24)..];
for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP24)) {
line[i] = BEf24(bytes, 0);
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_f16le<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) {
const SIZEOF_FP16: usize = 2;
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * SIZEOF_FP16)..];
for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP16)) {
line[i] = LEf16(bytes, 0);
}
}
}
#[multiversion(targets("x86_64+avx+avx2", "x86+sse", "aarch64+neon"))]
fn unpack_f16be<'a>(lines: impl LineIteratorMut<'a, f32>, src: &[u8], skip_rows: usize, width: usize) {
const SIZEOF_FP16: usize = 2;
for (row, line) in lines.enumerate() {
let inb = &src[((skip_rows + row) * width * SIZEOF_FP16)..];
for (i, bytes) in (0..width).zip(inb.chunks_exact(SIZEOF_FP16)) {
line[i] = BEf16(bytes, 0);
}
}
}