google / google/jpegli

djpegli rejects real-world progressive JPEGs with empty DHT segments

Open
#248 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
401
Forks
66
PR merge metrics
No merged PRs in 30d

Description

## Summary

`djpegli` rejects progressive JPEGs containing empty DHT segments (`FF C4 00 02`). These files are accepted by several widely used libjpeg-turbo-based decoders. This was previously reported in libjxl/libjxl#3597, but it still reproduces in the standalone Jpegli repository.

I understand that a DHT segment with no tables is not conforming to the JPEG syntax. This is a compatibility request for real-world files that other common decoders handle: treat an empty DHT segment as a no-op that preserves previously defined tables, or provide an equivalent tolerant decoding mode.

## Reproduction on current `main`

I built `djpegli` from google/jpegli@031a0077f5799a6041004267fc12b956c1f52a20 on macOS 26.4.1 arm64 with AppleClang 21.0.0:

```console
$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DJPEGLI_ENABLE_TOOLS=ON
$ cmake --build build --target djpegli -j 8
$ build/tools/djpegli photo_2024-05-21_21-56-01.jpg output.png
Read 85012 compressed bytes.
jpegli decoding failed
```

The public reproducer is attached to libjxl/libjxl#3597: https://github.com/libjxl/libjxl/files/15393696/photo_2024-05-21_21-56-01.zip

Its JPEG has SHA-256 `caeb422c07ff7b134a03c4d8a5727ca0aab998ac70a07a263e135b85a17d7c77` and contains two `FF C4 00 02` sequences.

The current source still reports an error when a DHT segment contains no tables:

https://github.com/google/jpegli/blob/031a0077f5799a6041004267fc12b956c1f52a20/lib/jpegli/decode_marker.cc#L285-L289

## Real-world scope

I encountered this while auditing the exact common-support exclusions in a JPEG decoder benchmark based on the Forchheim Image Database (FODB). All 276 excluded files have the same characteristics:

- 276/276 are progressive WhatsApp variants, spanning 23 devices and 12 scenes;
- 276/276 contain exactly two empty DHT segments (`FF C4 00 02`);
- 276/276 fail in Jpegli with `DHT marker: no Huffman table found`;
- 276/276 decode successfully and materialize RGB output with simplejpeg 1.9.0, OpenCV 5.0.0, and torchvision 0.28.0.

One representative FODB file is 1600x1201 and has SHA-256 `5e97e82ee53716360d21d02298ac76a1a7112b65e3bbe3c154ce0c806bf84b93`. I am not attaching the FODB image because the dataset's redistribution terms should be respected; the public reproducer above triggers the same behavior.

The Python binding `ajpegli==1.0.0`, which pins Jpegli commit `7cdf212790241868c77dca777dbee14e98128cba`, exposes the underlying error as:

```text
ajpegli.errors.DecodeError: jpegli decode failed: lib/jpegli/decode_marker.cc:288: DHT marker: no Huffman table found
```

## Expected behavior

Jpegli decodes these files in a compatibility mode, ideally with a regression test using the existing public reproducer. If strict rejection is intentional, an explicit tolerant option would still allow applications to match the behavior of common JPEG decoders.

Contributor guide

Open the contributing guide

Research direction

Start at lib/jpegli/decode_marker.cc:285-289, where an empty DHT segment is reported as an error, and build djpegli with the CMake commands in the report. Use the public libjxl#3597 reproducer to verify decoding behavior, then add a regression test using that file. Done means the reproducer decodes successfully without breaking strict JPEG handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
computer-graphics, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.