openexr-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Openexr-devel] OpenEXR - lossless compression problems


From: Peter Hillman
Subject: Re: [Openexr-devel] OpenEXR - lossless compression problems
Date: Sun, 4 Dec 2016 00:33:39 +0000

Hi David,


Your code looks valid, and as the image looks quite close to correct it's unlikely there's a bug in your code.

Perhaps the difference you are seeing is due to the fact that OpenEXR's 16 bit half is a floating point number. Converting a 16 bit unsigned integer n to a half float using n/65535 will cause rounding error.


From a quick test it seems you get 7169 unique bit patterns in a half float with that approach, which means you are losing information. The other patterns used by 16 bit half mainly store negative numbers and numbers above 1, which you aren't using here. These come about because OpenEXR is intended for storing HDR images. With a 16 bit unsigned int sRGB PNG, the darkest grey is 20 stops darker than the maximum white; with a 16 bit half linear OpenEXR that's closer to 40 stops.


The 8 bit version of n/255 will also cause rounding error, but in that case each input value is represented uniquely and you can fix the error by rounding to the nearest integer when you denormalize.


The openexr.com website has some sample HDR images you could use to experiment with OpenEXR compression schemes, but it is hard to make a rigorous comparison of PNG (for example) to OpenEXR because they set out to achieve different things working with different kinds of image data.


Your second question:


I got the idea that the compression is done in writePixels method. Is that’s right? If it’s true, is there any possibility to compress image in memory without writing it to file?


Yes, this is correct-writePixels is the only access to the compression schemes from the API. It is possible to generate an OpenEXR file entirely in memory, but is non-trivial: you have to subclass OStream and override the methods to write data into your memory array rather than to file. If you need to read it back, you need to make an IStream too.

You then pass an instance of your new OStream to the OutputFile constructor when you write it. The OpenEXR library will call your methods when it wants to write data. You might start here:

https://github.com/openexr/openexr/blob/develop/OpenEXR/IlmImfExamples/lowLevelIoExamples.cpp

Actually, if you just want to know how big the file would be with a given scheme, you could be sneaky and not store the image at all: just subclass OStream with a class that has its own "file pointer" which is read by readp(), set by seekp() and incremented by write(). You'll also need to track the maximum value the "file pointer" ever has, which would be the file size you need (not the final value of "file pointer") Doing this won't let you analyse errors in lossy schemes, but would let you measure the lossless schemes' efficiency.



From: Openexr-devel <openexr-devel-bounces+address@hidden> on behalf of David Kuťák <address@hidden>
Sent: Sunday, 4 December 2016 8:40 a.m.
To: address@hidden
Subject: [Openexr-devel] OpenEXR - lossless compression problems
 

Hello,

 

I am currently working on my bachelor thesis in which I am comparing image compression algorithms (available in different image file formats).

For my work, only file formats supporting lossless compression and 16 bit depth are appropriate.

During my exploration of possible formats, I found an OpenEXR and decided to include it in my tests.

However, I am not able to  make it work properly.

 

The input image and output image (created during compression) are not same – the colors seem to be different (shifted).

I thought it might be gamma problem but even after gamma correction, I am not able to retrieve correct output image.

Although visually the image seems to be very close to the input one (after gamma correction), there is still a minor difference which is unacceptable.

 

So I’d like to ask you for a help – what I am doing is written below (some undefined wars like imageWidth, etc. are correct for sure).

 

1) I create my output file

     RgbaOutputFile outputFile(argv[3], imageWidth, imageHeight, WRITE_RGB, 1.0f,

                                               V2f(0, 0), 1.0f, INCREASING_Y, compressionType, globalThreadCount());

 

2) Then I create a pixelData vector

    std::vector<Rgba> pixelData(imageWidth * imageHeight);

 

3) I fill this vector with data retrieved from my test images (these data are pixel values (i.e. numbers from interval <0,255/65535> – depending on bit depth – which I normalize to inverval <0,1.0> and pass to half ctor and then as an Rgba struct to appropriate pos in pixelData vector).

 

4) Then I set framebuffer and write pixels to file (shown in code below). I think that my problem occurs somewhere in those two methods (EXR must be doing some operations with pixel data).

outputFile.setFrameBuffer(pixelData.data(), 1, imageWidth);

outputFile.writePixels(imageHeight);

 

To sum up my problem – is this the correct way to pass image data to OpenEXR and retrieve the same image (but in EXR format)? I really don’t know why the color problem appears.

 

Another question I’d like to ask is that I got the idea that the compression is done in writePixels method. Is that’s right? If it’s true, is there any possibility to compress image in memory without writing it to file?

 

Thank you for your help!

 

David


reply via email to

[Prev in Thread] Current Thread [Next in Thread]