image read and write problem

Sometimes imwrite and imread work OK, but often not. In that case in stead of numbers between 0 and 255 (RGB tif file) all numbers become 0 or 255. Nothing in between. I can't find a problem and I can't find a system in what's going wrong. Any hints? You can see in the picture waht happens. It's a very tiny tif-file, all code you can see and after write and read it's damaged. Only red shown, blue and green the same.

7 Comments

imwrite would write binary images that way for most image types.
What else to use? (Sometimes the same code works OK, after imwrite and imread the files are the same.)
Weia's "Answer" moved here:
All documentation suggests to use imwrite... Why doesn't it work? I'm quite desperate.
Weia, make it easy for us to help you. Attach your srijf2 variable in a .mat file. An image does me no good in replicating your code. I don't want to type all that in, so please just give it to me in a .mat file.
save('answers.mat', 'srijf2');
Also tell us what the class of srijf2 is. Is it uint8? Or is it double?
It's not yet a mat-file. I wanted to check things in the timeline, made a tiny tif in Photoshop, used imwrite to get code in the timeline, did imwrite, imread again, worked correctly. Then I took aray code which represents the picture, changed a few numbers in a text programm, pasted this back:
srijf2(:,:,1)=[173,173,173,173,173,173,173,173
0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0
38,38,38,138,38,38,38,38
255,255,255,255,255,255,255,255
255,255,255,255,255,255,255,255]
srijf2(:,:,2)=[12,12,12,12,12,12,12,12
0,0,0,0,0,0,0,0
153,153,153,153,153,153,153,153
218,218,218,118,218,218,218,218
255,255,255,255,255,255,255,255
102,102,102,102,102,102,102,102]
srijf2(:,:,3)=[173,173,173,173,173,173,173,173
255,255,255,255,255,255,255,255
255,255,255,255,55,255,255,255
38,38,38,38,38,38,38,38
0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0]
Then continued with imwrite, imread again and the file had become binary, only numbers 0 and 255 and nothing in between. Like the screen picture above.
Strange is that sometimes this test worked and sometimes not.
The class of the file, I do not know. Just a tif from Photoshop.

Sign in to comment.

 Accepted Answer

srijf2(:,:,1)=[173,173,173,173,173,173,173,173
0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0
38,38,38,138,38,38,38,38
255,255,255,255,255,255,255,255
255,255,255,255,255,255,255,255]
That creates double precisions numbers, class double(). When you imwrite() data that is class double() then it assumes the dynamic range is 0 (black) to 1 (full intensity), and scales and converts to uint8, like uint8(srijf2 * 255) . Because of saturation of the uint8 range, that is going to give you all 0 or 255.
Do not double() integer images unless you know exactly what you are doing. Use im2double() if you need to convert from integer images to double precision images.

15 Comments

Thanks! That are things I do not know anaything about and I have no intentions whatsoever. I supposed that imread delivers a file imwrite asks for. How to let imread deliver a file imwrite needs??
Weia Reinboud
Weia Reinboud on 14 Jul 2020
Edited: Weia Reinboud on 14 Jul 2020
This is just testing how it works. Later I'll use a bigger file, which Photoshop says is RGB/8#. Whatever that may be.
This is part of the file info:
BitDepth: 24
ColorType: 'truecolor'
FormatSignature: [73 73 42 0]
ByteOrder: 'little-endian'
NewSubFileType: 0
BitsPerSample: [8 8 8]
Compression: 'Uncompressed'
PhotometricInterpretation: 'RGB'
Imwrite uses Compression: 'PackBits'
The original file was uncompressed.
Has that to do with the problem?
I get this message after efforts to make things single.
"Writing single image data to a TIFF file is not supported with IMWRITE. Use Tiff instead."
Ununderstandable...
You had been doing something like
Img = imread('some_file');
Img_d = double(Img);
% some processing here on Img_d such as wavelet compression and decompression
% producing srijf2 as output
imwrite(srijf2, 'srijf2.tif')
The problem with this is that the processing you are doing on the double() of Img, is resulting in srijf2 being double(), but when you imwrite() double, MATLAB expects the range of data to be 0 to 1 and does the transformation I mentioned earlier uint8(srijf2 * 255)
Producing srijf2 as single instead of double will not help. The problem that you are representing values that are in the range 0 to 255 (or so) as floating point, but MATLAB expects floating point to be in the range 0 to 1.
You should do something like
srijf2_u8 = uint8(srijf2);
imwrite(srijf2_u8, 'srijf2.tif');
I agree but I never saw where she said she directly assigned the values like that, or that she passed srijf2 into double() after getting it from the tiff file with imread() (not sure how she got it). I got the impressions she just read in a 24 bit uint8 tiff file from disk that was created with Photoshop:
srijf2 = imread('srijf2.tif');
srijf2
and then this shows up in the command windowl
srijf2(:,:,1)=[173,173,173,173,173,173,173,173
0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0
38,38,38,138,38,38,38,38
255,255,255,255,255,255,255,255
255,255,255,255,255,255,255,255]
srijf2(:,:,2)=[12,12,12,12,12,12,12,12
0,0,0,0,0,0,0,0
153,153,153,153,153,153,153,153
218,218,218,118,218,218,218,218
255,255,255,255,255,255,255,255
102,102,102,102,102,102,102,102]
srijf2(:,:,3)=[173,173,173,173,173,173,173,173
255,255,255,255,255,255,255,255
255,255,255,255,55,255,255,255
38,38,38,38,38,38,38,38
0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0]
so I assume that all those were uint8 numbers just like they had come out of the tiff file. But then she said she had an error where it said the class was single, so she must have done something to it. If she just directly assigned the values (like where she says "changed a few numbers in a text program"), then they would be double, not single, because assigning numbers (even integers) to a new variable will make the variable double because that's the default in MATLAB. If you then cast that to uint8, it will clip numbers to between 0 and 255 but it will not make non-0 and non-255 numbers (like 38, 173, etc.) into 0 or 255. It will just round them to the nearest uint8 integer (which is the same number in your case).
However if they came from imread() via Photoshop they would be uint8. And again, the values would not change.
What does this say if you put it right before imwrite()
whos srijf2
fprintf('The class of srijf2 is %s.\n', class(srijf2));
I'll try some more things. I did nothing with the numbers, only imread and imwrite, which I expected to be complementary.
Can you attach an image that you are getting the 0 255 behaviour on?
Weia Reinboud
Weia Reinboud on 20 Jul 2020
Moved: DGM on 20 Feb 2023
Thanks all! Things remain single when change of numbers is done within Matlab. And that's all I need.
I did a test with changing numbers outside Matlab, and although everything for the eye was OK it nevertheless had become class double. The simple test made everything complex...!
I can go to work now, but nevertheless like to know: how to undouble such an array with numbers 0...255
Walter Roberson
Walter Roberson on 20 Jul 2020
Moved: DGM on 20 Feb 2023
uint8() the array ?
Weia Reinboud
Weia Reinboud on 20 Jul 2020
Moved: DGM on 20 Feb 2023
After converting to single, imwrite goes wrong, I get this message:
"
Error using writetif (line 93)
Writing single image data to a TIFF file is not supported with IMWRITE. Use Tiff instead. Type "help Tiff"
for more information.
"
Problems are not yet over. I have written a Matlab programm which imread a tif, manipulates all pixels and makes an array 'cupoltje' by filling it with color indexes (R, G, B). This array has correct values from 0-255. Then imwrite does not complain, but the written file is binary, most pixels are 0 or 255. Below code how cupoltje is filled, shown and written.
Inside the programm cupoltje has to be made single I suppose? But cupoltje=single(cupoltje); does not work, imwrite does not accept that. Message: "Writing single image data to a TIFF file is not supported with IMWRITE. Use Tiff instead. Type "help Tiff" for more information."
for aa=1:138
for bb=1:95
cupoltje(aa,bb,1)=kleurR(aa,bb);
cupoltje(aa,bb,2)=kleurG(aa,bb);
cupoltje(aa,bb,3)=kleurB(aa,bb);
end
end
cupoltje
imwrite(cupoltje,'cupoltje.tif','tif');
No, you should have done
cupoltje = uint8(cupoltje); % or cupoltje = uint8(255 * mat2gray(cupoltje));
NOT
cupoltje=single(cupoltje); % Single won't work.
Not sure why you did that when we and MATLAB have already told you single won't work. Why didn't you convert to uint8?
Weia Reinboud
Weia Reinboud on 21 Jul 2020
Moved: DGM on 20 Feb 2023
It works! (I don't see in the above where this same conversion is given.)

Sign in to comment.

More Answers (0)

Categories

Find more on Convert Image Type in Help Center and File Exchange

Asked:

on 13 Jul 2020

Moved:

DGM
on 20 Feb 2023

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!