Three.js: EXRLoader improvement - PXR24 compression

Created on 17 Aug 2020  路  6Comments  路  Source: mrdoob/three.js

The PXR24 compression is similar to a ZIP compression, there is just a different predictor and interleaving.

I implemented it below, but it still shows some artifacts. Would you be able to find a bug?

function uncompressPXR24( info ) {
    var compressed = info.array.slice( info.offset.value, info.offset.value + info.size );
    var inflate = new Inflate( compressed, { resize: true, verify: true } ); // eslint-disable-line no-undef
    var rawBuffer = new Uint8Array( inflate.decompress().buffer );

    // predictor
    var dec = rawBuffer, w=width;
    for(var o=0; o<dec.length; o+=w) {
        var v = 0;
        for(var j=0; j<w; j++) {
            v = (v+(dec[o+j]))&255;  dec[o+j]=v;
        }
    }
    // interleave
    for(var o=0; o<dec.length; o+=2*w) {
        var v = 0;
        for(var j=0; j<w; j++) {
            tmpBuffer[o+2*j  ]=dec[o+j+w];
            tmpBuffer[o+2*j+1]=dec[o+j];
        }
    }
    return new DataView( tmpBuffer.buffer );
}

I tested it on this image . The right result is on the left, the result of my code is on the right side.

image (2)

Loaders

Most helpful comment

Oh, I did not know there exists any open implementation of EXR format. I created my code by trial and error.

So here is a correct implementation, in case you want to use it in your library :) (use it the same way as uncompressZIP)

function uncompressPXR24( info ) {
    var compressed = info.array.slice( info.offset.value, info.offset.value + info.size );
    var inflate = new Inflate( compressed, { resize: true, verify: true } ); // eslint-disable-line no-undef
    var rawBuffer = new Uint8Array( inflate.decompress().buffer );

    var dec = tmpBuffer, w=width;
    for(var o=0; o<dec.length; o+=2*w) {
        for(var j=0; j<w; j++) {
            dec[o+2*j  ]=rawBuffer[o+j+w];
            dec[o+2*j+1]=rawBuffer[o+j];
        }
        var uarr = new Uint16Array(dec.buffer,o,w);
        for(var j=1; j<w; j++) uarr[j] = (uarr[j-1]+uarr[j])&0xffff;
    }
    return new DataView( tmpBuffer.buffer );
}

All 6 comments

/ping @sciecode

@photopea according to OpenEXR implementation, ZIP compression is indeed used for PXR24, but the predictor step is type and channel dependant. At a quick glance, I wasn't able to spot any similarity between your code and OpenEXR.

Try to double check if your implementation is indeed following Pxr24Compressor::uncompress.

Edit: Nevermind, I see the similarity now. I was looking at the wrong function. Hmm, I'll take a better look at this later tonight.

Oh, I did not know there exists any open implementation of EXR format. I created my code by trial and error.

So here is a correct implementation, in case you want to use it in your library :) (use it the same way as uncompressZIP)

function uncompressPXR24( info ) {
    var compressed = info.array.slice( info.offset.value, info.offset.value + info.size );
    var inflate = new Inflate( compressed, { resize: true, verify: true } ); // eslint-disable-line no-undef
    var rawBuffer = new Uint8Array( inflate.decompress().buffer );

    var dec = tmpBuffer, w=width;
    for(var o=0; o<dec.length; o+=2*w) {
        for(var j=0; j<w; j++) {
            dec[o+2*j  ]=rawBuffer[o+j+w];
            dec[o+2*j+1]=rawBuffer[o+j];
        }
        var uarr = new Uint16Array(dec.buffer,o,w);
        for(var j=1; j<w; j++) uarr[j] = (uarr[j-1]+uarr[j])&0xffff;
    }
    return new DataView( tmpBuffer.buffer );
}

Alrighty! Thanks for that. Apparently we have to deal with the uncompression step differently depending if the underlying data is HALF or FLOAT, but that's already a great step forward. Thanks for that @photopea.

Do you want to create a PR yourself? or would you prefer if I did it?

I don't use GIT, so you can do it :) If you have any EXR files which the code can not handle, share them wiht me and I will fix it :)

It is really hard to write a proper code without having actual files to test it on.

Yeah, I've been using the OpenEXR test files for that.

But, not worries. I'll prepare the PR until the end of the day. I'll make sure to ping you for testing as well 鉂わ笍

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yqrashawn picture yqrashawn  路  3Comments

boyravikumar picture boyravikumar  路  3Comments

fuzihaofzh picture fuzihaofzh  路  3Comments

makc picture makc  路  3Comments

jack-jun picture jack-jun  路  3Comments