pngread does not read 12bit gray images

Bill Denney bill at denney.ws
Mon Jul 14 17:54:08 CDT 2008


I assume that you meant to send this reply back to the list.  If not, 
I'm sorry for putting it back here.  Also, if the message below sounds 
harsh, please don't take it that way-- I just feel strongly about the 
subject of accurate data representation and I'm not convinced that the 
method you suggest will keep data in the most accurate format.

de Almeida, Valmor F. wrote:
>> -----Original Message-----
>> From: Bill Denney [mailto:wsloand at gmail.com] On Behalf Of Bill Denney
>> Sent: Friday, July 11, 2008 11:57 PM
>>
>> de Almeida, Valmor F. wrote:
>>     
>>>> -----Original Message-----
>>>> From: Søren Hauberg [mailto:soren at hauberg.org]
>>>> Sent: Friday, July 11, 2008 7:32 AM
>>>> ..snip..
>>>> I think that 12 bit images should be represented as 16 bit images that
>>>> happens to have a maximum value of 2^12 - 1.
>>>>         
>>> I tend to agree. The values should be read as they are.
>>>       
>> the same way) and the number in the image represents the distance from 0
>> to the maximum on that scale.
>>     
>
> That is fine. But the user should have the option of doing this 0-1 scaling from integer to double on his/her own.
>   

Hopefully it's not actually converting to a double (I would view that as 
a real problem).

>> If you use the method of having a value read from a 12 bit scale (x)
>> into a 16 bit scale (y), x/(2^12 - 1) should equal y/(2^16 - 1).  If you
>>     
>
> The point is that the max should be whatever is in the image and not be scaled to 2^16-1.
>
> I tend to agree with that because gray images of scientific importance are typically of low contrast and low SNR. Therefore I want to keep all the information intact when I read the image.

Having done scientific image analysis before, I realize that the work is 
often low contrast and that it is necessary to keep all information 
intact.  I would argue that putting 774 into a uint16 is not keeping all 
information intact while putting the bits that make up 774 into the 
leftmost bits of a uint16 is keeping the information intact and 
corresponds to what most image processing/manipulation tools expect.

Note the following:

octave-3.0.1.exe:1> x_uint12 = uint16(774)
x_uint12 = 774
octave-3.0.1.exe:2> x_uint16 = bitshift(x_uint12, 4)
x_uint16 = 12384

If you know that your image is 12 bit then just right shift the data by 4:
octave-3.0.1.exe:3> bitshift(x_uint16, -4)
ans = 774

As I have stated before, it is not possible to round trip the data 
through octave if it does not use the bit depth for the integer type 
(without adding additional metadata).  Try the following (untested, but 
it should work):

Y = imread("foo.png");
max(Y(:))
## You should see 12384 here
any(bitshift(Y, 12)(:))
## you should see 0 here indicating that the 4 least significant bits 
are all 0
Y12 = bitshift(Y, -4);
max(Y12(:))
## you should see 774 here
imwrite("foo12.png", Y12)
## foo12.png is now the image that you had originally requested that 
octave provide
imwrite("foo16.png", Y)
## foo16.png is the image that I think octave should provide (i.e. what 
it currently provides)

If you examine foo, foo12 and foo16.png in any (non-contrast adjusting) 
image viewer you should see that the original and 16 are the same while 
12 is much darker.  How would you propose to correct that without the 
addition of a 12 bit class (i.e. uint12) and without requiring 
additional metadata to imwrite?

Almost all of the scientific image analysis that I'm aware of works on 
contrast not on absolute numbers.  Also, if you need the actual original 
number and you know the bit depth of the original, you can always modify 
the original with a bit shift.

Have a good day,

Bill


More information about the Help-octave mailing list