My code reads an RGB image, processing it to produce floating-point results. How can I write these values as an image, maintaining these floating-point values, in Matlab 7.6.0 (R2008a)?
Floating point images may use 32-bit floats, or the 16-bit “half” format. The half format does not have as much dynamic range, but it is almost always enough for practical work even using High-Dynamic-Range images. Half-floats are half the size, only 16 bits, so you can fit more images into memory simultaneously.
Floating-point values. The core of PNG does not use floating-point numbers anywhere; it uses integers or, where applicable, fixed-point fractional values. However, special-purpose chunks may need to represent values that do not fit comfortably in fixed-point notation.
A 32-bit floating point image can represent 4.3 billion values per channel, and requires roughly twice the disk space as a 16-bit image. Few programs support 32-bit images.
In memory, a floating point number is represented similarly: One bit has the sign, some bits form the factor as a fixed-precision number (“mantissa”), the remaining bits form the exponent. Significant differences to base-10 engineering notation is that of course now the exponent has base 2.
It is actually possible to fit 64 bits of pixel data (i.e. the number of bits needed to represent a double-precision floating-point value) into certain image formats, specifically a PNG. And you can even recover the data exactly. The key is to encode everything as uint16
values and use a Truecolor RGB image (3 color planes of 16 bit data) along with an alpha transparency map (another 16 bits). Here's the encoding step:
data = rand(4); % Just some sample data, a small 4-by-4 matrix
hexData = num2hex(data(:)); % Get the 16 digit hex codes for each pixel
C = mat2cell(hexData, numel(data), [4 4 4 4]); % Split the hex codes into 4 groups of 4
C = cellfun(@(c) {uint16(hex2dec(c))}, C); % Convert each hex value into a 16 bit integer
colorData = reshape([C{1:3}], [size(data) 3]); % 4-by-4-by-3 uint16 color data
alphaData = reshape(C{4}, size(data)); % 4-by-4 uint16 alpha data
imwrite(colorData, 'double_data.png', 'Alpha', alphaData); % Save image
You now have a valid image file, although it'll probably looks like random garbage if you view it. Now, you can decode it like so:
[imColor, ~, imAlpha] = imread('double_data.png'); % Load image
imSize = size(imColor); % Get image size
imHex = [dec2hex(imColor(:, :, 1)) ... % Convert each uint16 to hex and concatenate
dec2hex(imColor(:, :, 2)) ...
dec2hex(imColor(:, :, 3)) ...
dec2hex(imAlpha)];
imdata = reshape(hex2num(imHex), imSize(1:2)); % Reproduce data
And an equality check:
>> isequal(imdata, data)
ans =
logical
1 % it's the same!
The number of bits used to represent each element of a digital image is called the bit-depth of the image. The bit-depth tells us the number of discrete levels which an element of the image can take. Whether these elements will be stored as an integral type or a floating-point type is irrelevant: the bit-depth determines exactly how many discrete levels there may be.
How the bit-depth is interpreted depends on whether an image is grayscale or color. For example, an 8-bit grayscale image will have intensities in [0,255], while a 24-bit color image will also have intensities in [0,255]. This nomenclature is used because storing a color pixel with 8-bit red, green and blue components requires 24-bits. In order to avoid confusion, color images are often called by the number of bits per color channel. For example, the PNG format supports up to 16 bits per channel, or 48-bits total for truecolor (RGB) with an alpha layer.
The documentation for imwrite lists the formats and the bit-depths available in MATLAB.
Saving a color image (MxNx3 matrix) from MATLAB with the highest level of precision:
%// Assume an image called 'im' of type double.
%// First normalize to fall into [0,1].
im = im - min(im(:)); %// Save these numbers somewhere
im = im / max(im(:)); %// if you need to recover the original values later!
%// Best PNG quality.
imwrite(im,'image.png','bitdepth',16);
If you need more precision, you must save your image in a general data format rather than a specialized image format.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With