Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2f64849
autoresearch setup
laurenspriem Jul 16, 2026
790b22f
Merge branch 'main' into faster
laurenspriem Jul 16, 2026
b8586e8
fix autoresearch pure-Rust Rayon dependency gate
laurenspriem Jul 16, 2026
73c7487
perf(autoresearch): ARM NEON full-range 8-bit 4:2:0 hook color conver…
laurenspriem Jul 16, 2026
b59130e
perf(autoresearch): Experiment: Replace residual-decoding boolean arr…
laurenspriem Jul 16, 2026
b5e5787
perf(autoresearch): Make infallible CABAC primitives return plain val…
laurenspriem Jul 17, 2026
2f4fc3d
perf(autoresearch): Experiment: Extend full-range 8-bit 4:2:0 SIMD co…
laurenspriem Jul 17, 2026
6a4adbd
feat(autoresearch): journal every optimization attempt
laurenspriem Jul 17, 2026
c2bfbb7
perf(autoresearch): Experiment: Replace per-pixel grid transform inte…
laurenspriem Jul 17, 2026
4d5e861
perf(autoresearch): Re-evaluate stable packed CABAC transitions and b…
laurenspriem Jul 17, 2026
2d714fa
perf(autoresearch): Recover dense residual coefficient bookkeeping af…
laurenspriem Jul 17, 2026
181792f
perf(autoresearch): Experiment: Decode residuals into a persistent sp…
laurenspriem Jul 17, 2026
34ef18f
perf(autoresearch): Experiment: Decode residual subblocks directly in…
laurenspriem Jul 17, 2026
fc14b3b
perf(autoresearch): Experiment: Replace residual scan-coordinate inte…
laurenspriem Jul 17, 2026
8fe9d3c
fix CABAC short-substream reinitialization
laurenspriem Jul 17, 2026
5f75417
autoresearch: require repeatable 2% gains
laurenspriem Jul 17, 2026
7c17018
speed optimization suggestions
laurenspriem Jul 17, 2026
05df6a8
docs: record rejected single-pass HEVC experiment
laurenspriem Jul 18, 2026
39b9a26
docs: record rejected strided crop experiment
laurenspriem Jul 18, 2026
c6454f9
docs: record rejected direct grid output experiment
laurenspriem Jul 18, 2026
917808d
speed: stream grid tile decoding
laurenspriem Jul 18, 2026
0bff6e1
docs: record rejected ThinLTO and PGO experiment
laurenspriem Jul 18, 2026
bccceeb
speed: extend AArch64 color conversion SIMD
laurenspriem Jul 18, 2026
23de425
docs: record rejected CABAC bundle experiment
laurenspriem Jul 18, 2026
f47614e
docs: record SAO clone experiment
laurenspriem Jul 18, 2026
04b81a8
docs: record oriented output experiment
laurenspriem Jul 18, 2026
214af1d
docs: record WPP feasibility experiment
laurenspriem Jul 18, 2026
20ca446
docs: record final optimization audit
laurenspriem Jul 18, 2026
03cebf0
cleanup
laurenspriem Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ the CI toolchain, validator, or corpus forward deliberately.
- pixel-for-pixel comparison of the `image` crate integration hook output
(`ImageReader`/`DynamicImage::from_decoder`) against the direct Rust decode
for every comparable verifier file, including exact ICC-profile equality
through the hook decoder's `ImageDecoder::icc_profile`
through the hook decoder's `ImageDecoder::icc_profile`; this reproduces
Ente's production hook shape, including its explicit guardrails,
`with_guessed_format`, `Limits::reserve`, and `set_limits`
- embedded ICC colour-profile comparison against the validator's PNG output:
when `heif-dec` embeds a profile, the Rust PNG must carry byte-identical
profile data; a Rust-only profile is allowed (the Rust decoder synthesizes
Expand Down
38 changes: 28 additions & 10 deletions scripts/heic_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,9 @@ fn main() -> Result<(), Box<dyn Error>> {
RS

cat > "$HELPER_DIR/src/bin/heif-image-adapter-bench.rs" <<'RS'
use heic_decoder::image_integration::register_image_decoder_hooks;
use heic_decoder::{DecodedRgbaImage, DecodedRgbaPixels, decode_path_to_rgba};
use image::{DynamicImage, ImageReader};
use heic_decoder::image_integration::register_image_decoder_hooks_with_guardrails;
use heic_decoder::{DecodeGuardrails, DecodedRgbaImage, DecodedRgbaPixels, decode_path_to_rgba};
use image::{DynamicImage, ImageDecoder, ImageReader, Limits};
use std::error::Error;
use std::path::Path;

Expand Down Expand Up @@ -462,8 +462,18 @@ fn main() -> Result<(), Box<dyn Error>> {
let value = match args[1].as_str() {
"direct" => direct_checksum(&decode_path_to_rgba(input)?),
"adapter" => {
let _ = register_image_decoder_hooks();
let decoded = ImageReader::open(input)?.decode()?;
let _ = register_image_decoder_hooks_with_guardrails(DecodeGuardrails {
max_input_bytes: Some(128 * 1024 * 1024),
max_pixels: Some(256_000_000),
max_temp_spool_bytes: Some(256 * 1024 * 1024),
temp_spool_directory: None,
});
let mut decoder = ImageReader::open(input)?.with_guessed_format()?.into_decoder()?;
let _icc_profile = decoder.icc_profile()?;
let mut limits = Limits::default();
limits.reserve(decoder.total_bytes())?;
decoder.set_limits(limits)?;
let decoded = DynamicImage::from_decoder(decoder)?;
let (width, height) = (decoded.width(), decoded.height());
let pixels = match decoded {
DynamicImage::ImageRgba8(buffer) => checksum(buffer.as_raw()),
Expand All @@ -480,9 +490,9 @@ fn main() -> Result<(), Box<dyn Error>> {
RS

cat > "$HELPER_DIR/src/bin/heif-image-hook-check.rs" <<'RS'
use heic_decoder::image_integration::register_image_decoder_hooks;
use heic_decoder::{DecodedRgbaPixels, decode_path_to_rgba};
use image::{DynamicImage, ImageDecoder, ImageReader};
use heic_decoder::image_integration::register_image_decoder_hooks_with_guardrails;
use heic_decoder::{DecodeGuardrails, DecodedRgbaPixels, decode_path_to_rgba};
use image::{DynamicImage, ImageDecoder, ImageReader, Limits};
use std::error::Error;
use std::path::Path;

Expand All @@ -495,9 +505,17 @@ fn main() -> Result<(), Box<dyn Error>> {
let input = Path::new(&args[1]);
let direct = decode_path_to_rgba(input)?;

let _ = register_image_decoder_hooks();
let mut decoder = ImageReader::open(input)?.into_decoder()?;
let _ = register_image_decoder_hooks_with_guardrails(DecodeGuardrails {
max_input_bytes: Some(128 * 1024 * 1024),
max_pixels: Some(256_000_000),
max_temp_spool_bytes: Some(256 * 1024 * 1024),
temp_spool_directory: None,
});
let mut decoder = ImageReader::open(input)?.with_guessed_format()?.into_decoder()?;
let icc_profile = decoder.icc_profile()?;
let mut limits = Limits::default();
limits.reserve(decoder.total_bytes())?;
decoder.set_limits(limits)?;
if icc_profile != direct.icc_profile {
return Err("image hook ICC profile differs from direct decode".into());
}
Expand Down
31 changes: 23 additions & 8 deletions src/bin/heif-image-adapter-bench.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use heic_decoder::image_integration::register_image_decoder_hooks;
use heic_decoder::{DecodedRgbaPixels, decode_path_to_rgb8, decode_path_to_rgba};
use image::{DynamicImage, ImageReader};
use heic_decoder::image_integration::register_image_decoder_hooks_with_guardrails;
use heic_decoder::{DecodeGuardrails, DecodedRgbaPixels, decode_path_to_rgb8, decode_path_to_rgba};
use image::{DynamicImage, ImageDecoder, ImageReader, Limits};
use std::env;
use std::error::Error;
use std::fmt::{Display, Formatter};
Expand Down Expand Up @@ -80,10 +80,26 @@ fn bench_direct(input_path: &Path) -> Result<u64, Box<dyn Error>> {
Ok(((decoded.width as u64) << 32) ^ (decoded.height as u64) ^ checksum)
}

fn bench_adapter(input_path: &Path) -> Result<u64, Box<dyn Error>> {
let _ = register_image_decoder_hooks();
fn decode_adapter(input_path: &Path) -> Result<DynamicImage, Box<dyn Error>> {
let _ = register_image_decoder_hooks_with_guardrails(DecodeGuardrails {
max_input_bytes: Some(128 * 1024 * 1024),
max_pixels: Some(256_000_000),
max_temp_spool_bytes: Some(256 * 1024 * 1024),
temp_spool_directory: None,
});

let mut decoder = ImageReader::open(input_path)?
.with_guessed_format()?
.into_decoder()?;
let _icc_profile = decoder.icc_profile()?;
let mut limits = Limits::default();
limits.reserve(decoder.total_bytes())?;
decoder.set_limits(limits)?;
Ok(DynamicImage::from_decoder(decoder)?)
}

let decoded = ImageReader::open(input_path)?.decode()?;
fn bench_adapter(input_path: &Path) -> Result<u64, Box<dyn Error>> {
let decoded = decode_adapter(input_path)?;
let (width, height) = (decoded.width(), decoded.height());
let checksum = match decoded {
DynamicImage::ImageRgba8(buffer) => small_checksum(buffer.as_raw()),
Expand All @@ -105,8 +121,7 @@ fn bench_rgb(input_path: &Path) -> Result<u64, Box<dyn Error>> {
}

fn decode_adapter_rgb(input_path: &Path) -> Result<image::RgbImage, Box<dyn Error>> {
let _ = register_image_decoder_hooks();
Ok(ImageReader::open(input_path)?.decode()?.into_rgb8())
Ok(decode_adapter(input_path)?.into_rgb8())
}

fn bench_adapter_rgb(input_path: &Path) -> Result<u64, Box<dyn Error>> {
Expand Down
Loading