3

I want to open and read a .raw image in MATLAB. My file can be downloaded here. I have tried the following three code snippets, but neither gives the expected results.

Code Snippet #1

    row=576;  col=768;
    fin=fopen('m-001-1.raw','r');
    I=fread(fin,row*col,'uint8=>uint8'); 
    Z=reshape(I,row,col);
    Z=Z';
    k=imshow(Z);

It shows this picture:

first

Code Snippet #2

    f=fopen('m-001-1.raw');
    a=fread(f);
    input_img = reshape(a,768, 576, 3);
    input_img = imrotate(input_img, -90);
    imwrite(input_img, 'm-001-1.jpg'); 

This saves a blank (just white) image in .jpg format.

Code Snippet #3

    id = fopen('m-001-1.raw', 'r');
    x = fread(id, [576,768], 'short');

When I use imshow(x), this picture shows:

third

How do I read this picture correctly?

rayryeng
  • 102,964
  • 22
  • 184
  • 193

2 Answers2

6

Your row/col sizes are reversed. Since MATLAB arrays are column-major, and raster images are usually stored row-major, you need to read the image as a [col row] matrix, then transpose it.

row=576;  col=768;
fin=fopen('m-001-1.raw','r');
I=fread(fin, [col row],'uint8=>uint8'); 
Z=I';
k=imshow(Z)

The image replication is happening because you're short 768-576 = 192 pixels per line, so each line is progressively off that amount. After 4 lines, you've made up the difference (4*192 = 768), so you have a 4-image replication.

Peter
  • 14,559
  • 35
  • 55
4

Peter's code (thanks btw!) works assuming that your image is grayscale. For colour images, what you need to do is read in all of the bytes as a single 1D array as we can't use fread to read the data is in as a 3D matrix (at least not to my knowledge...). After, we then reshape it so that it becomes a 3D matrix. After we reshape the matrix, notice that this is the transposed result. As such, we will have to either transpose each channel independently, or you can cleverly combine flipdim and imrotate to do the 3D transpose for us. I would rotate the image so that it's 90 degrees clockwise, but this would make the image mirror reflected across the columns. I then use flipdim with the second parameter as 2 as I want to mirror reflect across the columns to get the original image back.

As such, what you would actually have to do is this:

row=576;  col=768;
fin=fopen('m-001-1.raw','r');
I=fread(fin, col*row*3,'uint8=>uint8'); %// Read in as a single byte stream
I = reshape(I, [col row 3]); %// Reshape so that it's a 3D matrix - Note that this is column major
Ifinal = flipdim(imrotate(I, -90),2); % // The clever transpose
imshow(Ifinal);
fclose(fin); %// Close the file

What I get is this image:

enter image description here


Alternatively, you can certainly use Peter's code, but you would use it so that you would reconstruct the image one colour plane at a time. In other words, you can do this:

row=576;  col=768;
fin=fopen('m-001-1.raw','r');
I1=fread(fin, [col row],'uint8=>uint8'); %// Red channel
I2=fread(fin, [col row],'uint8=>uint8'); %// Green channel
I3=fread(fin, [col row],'uint8=>uint8'); %// Blue channel
I1 = I1.'; I2 = I2.'; I3 = I3.'; %// Transpose each channel separately
Ifinal = cat(3, I1, I2, I3); %// Create 3D matrix
imshow(Ifinal);
fclose(fin);

You'll get exactly the same image as above.

rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • 2
    thank you for your help it's second time you help me. – Simin Soleymanpour Sep 06 '14 at 15:06
  • How would one generalize this to an n x m image? That is, if the dimensions are not previously known. Is that possible? – marcman Mar 29 '16 at 19:04
  • @marcman No it isn't. That's the point of a RAW image. It stores the raw pixels themselves without any header information. You need to know how many rows and columns there are before hand. – rayryeng Mar 29 '16 at 19:12
  • @rayryeng: That makes sense. I guess a hack would be to `size(imread(img))` first? Also I would think `permute(img, [2,1,3])` would work as well for the transpose. Or `flip(permute(img, [2,1,3,]), 2)` if that mirroring is necessary – marcman Mar 29 '16 at 19:17
  • @marcman I actually in the middle of changing my post to do the transpose that way... this is an old post. Thanks. – rayryeng Mar 29 '16 at 19:20
  • @marcman Yes... that would be a good "hack", but that's assuming you have one of the images already loaded in memory. Is this the case? I'm assuming you don't know anything before hand. – rayryeng Mar 29 '16 at 19:21
  • @rayryeng: Well not necessarily. It would certainly add some overhead because you're also doing a standard `imread` call on the raw file. But it should get the job done I guess. My understanding is that the dimensions on `imread('image.raw')` will match up with the correct dimensions (source: [this post](http://photo.net/digital-darkroom-forum/00Z2YR)) – marcman Mar 29 '16 at 19:30