uclouvain / openjpeg

Official repository of the OpenJPEG project
Other
981 stars 456 forks source link

`Invalid tile part index` error on some JPEG 2000 files #1558

Open mbklein opened 1 month ago

mbklein commented 1 month ago

Expected behavior and actual behavior

Expected behavior: Calling opj_get_decoded_tile for each tile in an image should allow decoding of each tile in turn

Actual behavior: On some (not all) images, decoding fails with Invalid tile part index for tile number 1. Got 7, expected 0. This appears to be because of the reset of m_current_tile_part_number taking place here.

opj_decompress has no trouble at all with the image (either the full image or a single tile), and jpylyzer reports that the image is compliant with the JPEG 2000 spec.

The problem was first discovered trying to load certain jp2 files into libvips. The issue was reported and investigated in libvips/libvips#4205. There is much more detailed debugging output attached to that issue.

I managed to reproduce the issue outside libvips and create a minimal example.

Steps to reproduce the problem.

Use this code and sample images: tile_part_index_error.zip

Compile and link main.c against libopenjp2, and then run the resulting binary with the name of the file to decode.

Operating system

Both Linux (Fedora 36) and MacOS (Sequoia 15.0.1)

openjpeg version

v2.5.2

mbklein commented 1 month ago

Looking more closely at the working vs. nonworking JP2 files, it seems the one that does not exhibit the bad behavior only has one tile-part per tile. The issue still exists, but there's now an easy explanation for why one file works and the other doesn't.

mbklein commented 1 month ago

Re-creating the “working” JP2 with multiple tile parts causes the error again, so it seems to be happening whenever there is more than one tile-part per tile.

mbklein commented 4 weeks ago

More data: I decided to see if the index order mattered, and found that while I could not read the tiles from 0..n, I could read them in reverse order (n..0). In fact, I've found that if I read the last tile first, I can then read the rest of the tiles as many times as I want in any order without causing any problems. It only seems to work if I read the last tile first, e.g., if I have 2 tiles across and 2 tiles down (as in the example image I attached to this issue), I have to start with tile index 3 (after which I can jump back and read 0..n in order, or whatever).

mbklein commented 4 weeks ago

I've created several more images with different numbers of tiles and different numbers of parts per tile. Unfortunately, the workaround mentioned above doesn't work for most of them. It does get farther into the image with that code than without it, but it always bombs out again partway through.