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)?
6 Answers
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!

- 125,304
- 15
- 256
- 359
-
5Pics or it didn't happen. – Andras Deak -- Слава Україні May 10 '17 at 22:29
-
3@AndrasDeak: You mean you can't see the 16 pixel image in my post? It's right next to that period... or is it the period? – gnovice May 11 '17 at 14:01
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.

- 2,561
- 1
- 22
- 36
Image with floating point values can be written in tiff image format. Here is an example:
A=single(7.6*rand(10,10))
t = Tiff('test.tif', 'w');
tagstruct.ImageLength = size(A, 1);
tagstruct.ImageWidth = size(A, 2);
tagstruct.Compression = Tiff.Compression.None;
tagstruct.SampleFormat = Tiff.SampleFormat.IEEEFP;
tagstruct.Photometric = Tiff.Photometric.MinIsBlack;
tagstruct.BitsPerSample = 32;
tagstruct.SamplesPerPixel = 1;
tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
t.setTag(tagstruct);
t.write(A);
t.close();
B=imread('test.tif')

- 21
- 1
Following function writes a single-precision gray-scale or RGB image to a tif file. And you will find that these days, Windows explorer can handle the single-precision image very well if pixel values are in the range of (0,1). When you read it back, you can use imread
as usual.
function writeftif(outim,outfilename)
t = Tiff(outfilename,'w');
if size(outim,3)==3
t.setTag('Photometric',Tiff.Photometric.RGB);
elseif size(outim,3)==1
t.setTag('Photometric',Tiff.Photometric.MinIsBlack);
end
t.setTag('Compression',Tiff.Compression.None);
t.setTag('BitsPerSample',32);
t.setTag('SamplesPerPixel',size(outim,3));
t.setTag('SampleFormat',Tiff.SampleFormat.IEEEFP);
t.setTag('ImageLength',size(outim,1));
t.setTag('ImageWidth',size(outim,2));
t.setTag('PlanarConfiguration',Tiff.PlanarConfiguration.Chunky);
% Write the data to the Tiff object.
t.write(single(outim));
t.close();

- 20,215
- 33
- 138
- 240
If your RGB value is out of the range (0,1),just transform the RGB value between 0 and 1. If you want recover the original float value,you can save the transform value as part of the image file name.
-
The problem is that I want to save these values as an image with preserving these floating point values since when I use imwrite function the values will converted to unsigned integers. – Student Dec 22 '12 at 18:02
When you save an image, the viewer needs to know what is the full possible range of the values. The common convention is that is the values are float, the range is [0..1], when the values are uint8 the range is [0..255] etc.
When you save the image with float values like 2.34, you should ask yourself how the viewer will know how to interpret it?
My answer is: you can't. You should convert your values to a valid range and then save it. For example, if your float range is [0..10], you can multiply all the values by 1000 and save as uint16. That way you can (almost) preserve the accuracy of the float value.

- 439
- 4
- 11
-
6TIFF supports floating point images just fine. I couldn't care less what the viewer does with it; it's data, there's no good reason I shouldn't be able to have a pixel with a value of e.g. 2.34. If the pixel type is float, then the range is MIN_FLOAT to MAX_FLOAT. Oh, and yes, you can do this with the `Tiff` class. – Ed S. Jul 09 '15 at 00:11