Traneptora / jxlatte

Java JPEG XL decoder
MIT License
44 stars 5 forks source link

New feature: Read header only #38

Open haraldk opened 5 days ago

haraldk commented 5 days ago

As mentioned in #20, I'm working on an ImageIO plugin for JPEG XL using your decoder. For this to work reasonably, I need a way to read the header (ImageHeader) without also decoding the entire image.

I've added a method to JXLCodestreamDecoder, like this:

    public ImageHeader readHeader() throws IOException {
        if (imageHeader == null) {
            if (atEnd()) {
                return null;
            }

            bitreader.showBits(16); // force the level to be populated
            int level = demuxer.getLevel();

            imageHeader = ImageHeader.read(new Loggers(options, new PrintWriter(new OutputStreamWriter(System.err, StandardCharsets.UTF_8))), bitreader, level);
        }

        return imageHeader;
    }

(I also made some minor tweaks to initialize canvas in the decode method to avoid NPE). This kind of works, but in some cases it seems to create what I believe is alignment issues in the codestream when I later invoke decode(). Causing exceptions like:

For samples/ants.jxl as an example:

com.traneptora.jxlatte.io.InvalidBitstreamException: Invalid Level 1 Prefix codes
    at com.traneptora.jxlatte.entropy.PrefixSymbolDistribution.populateComplexPrefix(PrefixSymbolDistribution.java:97)
    at com.traneptora.jxlatte.entropy.PrefixSymbolDistribution.<init>(PrefixSymbolDistribution.java:194)
    at com.traneptora.jxlatte.entropy.EntropyStream.<init>(EntropyStream.java:147)
    at com.traneptora.jxlatte.entropy.EntropyStream.<init>(EntropyStream.java:101)
    at com.traneptora.jxlatte.frame.Frame.readTOC(Frame.java:155)
    at com.traneptora.jxlatte.JXLCodestreamDecoder.decode(JXLCodestreamDecoder.java:754)
    at com.traneptora.jxlatte.JXLCodestreamDecoder.decode(JXLCodestreamDecoder.java:686)
    at com.traneptora.jxlatte.JXLDecoder.decode(JXLDecoder.java:41)

I can work around this, by repositioning the stream and creating a new decoder for reading the image after reading the header. But it would be nice to have a method that could read the header without other side effects. My plan was to create a PR with the above code, but it's no good until we can fix the alignment issues.

Traneptora commented 4 days ago

I'm not going to give you a programming lesson on how to debug your own code

haraldk commented 1 day ago

You can save the programming lessons for someone who needs that... 😉

But some friendly advice on how to implement reading the header only in your code would be appreciated.