Writing 3D array to BMP file

I have a data structure which contains a 3D array (852x512x16) of MRI image data. I need to export this image as a .bmp file. I tried doing this with the save() function (commented below) which seemed to work, but the 3rd party app (Materialise Mimics) that I need to use to process the image said the file type was not recognized, even though the software is definitely capable of working with bmp files (I've done so with other files). To verify that the issue was the file and not the program I tried viewing the bmp in ImageJ and was thrown an error: "java.lang.ArithmeticException: / by zero".
I then tried using the imwrite() function instead but received an error.
clear; clc; close all;
load('PatientImages_1_T2.mat') % load data structure
img=(PatientImages.originalimage(:,:,:)); % extract all 16 slices from struct
% img is now an 852 x 512 x 16 array
filename='patient1_t2';
%save('patient1_t2.bmp','img'); % file not recognized by Mimics
imwrite(img,filename,'bmp')
Error message:
"Error using writebmp (line 27)
Invalid dimensions for X.
Error in imwrite (line 566)
feval(fmt_s.write, data, map, filename, paramPairs{:});
Error in struct2bmp (line 7)
imwrite(img,filename,'bmp')"
I'm assuming from the error message that the problem is that my image has multiple slices and is a z-stack. Do I need to do some kind of operation slice by slice and then collate them together in one bmp at the end somehow?

 Accepted Answer

DGM
DGM on 26 Jul 2021
Edited: DGM on 26 Jul 2021
imwrite() doesn't support multipage/multiframe BMP files, because (as far as I know), the format specification for BMP doesn't allow such a thing to exist. If I'm wrong about that, feel free to correct me.
If you must use BMP, multipage/multiframe data would be written to a set of single-page files (possibly organized by directory or filename prefix). Otherwise, just use a TIFF container or something that can support such data.
imwrite(imgstack(:,:,1),'multipage.tif') % write the first image
imwrite(imgstack(:,:,2),'multipage.tif','writemode','append') % append the second image
readbackimgstack = cat(3,imread('multipage.tif',1),imread('multipage.tif',2)); % read back both and concatenate
Compared to BMP, TIFF is generally more flexible and offers other useful options (e.g. lossless compression). If you're worried about general portability of the file, bear in mind that most browsers/viewers don't support mutiframe images in any format other than GIF anyway -- and no, that's not a recommendation to use GIF. Whatever format you use for arbitrary volumetric data likely won't be widely compatible with casual image viewers.

5 Comments

JSC
JSC on 26 Jul 2021
Edited: JSC on 26 Jul 2021
Thanks for the detailed response. I was instructed to export the images as BMPs so my current understanding is that other filetypes won't work for the image processing (segmentation) we'll do later.
Are you saying that it's not possible to have a single BMP with multiple slices, and that I would need to export individual slices and try to group them with folders/filenames?
Also, am I understanding correctly that your code above would only work for a TIFF and not BMPs?
DGM
DGM on 27 Jul 2021
Edited: DGM on 27 Jul 2021
The above code example just works for TIFF (and GIF).
Like I said, from my reading of the format info for BMP, there doesn't appear to be an intended means for storing more than 3 8-bit pages; certainly, imwrite() only supports 3. If there is a way to make a mulfiimage BMP, as can be done with JPG, I don't know of it and imwrite() doesn't support it.
I don't know what software only supports BMP as input, but the particular format being used should be irrelevant for image processing purposes -- so long as it's both supported and the conversion is lossless. The latter point is why you'd want to avoid formats like JPG (lossy compression) and GIF (only supports indexed images).
Continuing on that point, there is one other point that I didn't think to bring up. A lot of medical images (at least a lot that I've handled) are 16-bit data. If yours are 16-bit you want to preserve the intensity resolution, you'd need to consider that when picking a format. Imwrite() doesn't support 16-bit grayscale BMP output, but it does for PNG and TIFF.
JSC
JSC on 27 Jul 2021
Edited: JSC on 27 Jul 2021
Thanks for elaborating. We definitely do want a lossless format. I'm not sure about my images being 16-bit or 8-bit since they were given to me as 3D arrays (type double) inside .mat files and I'm not sure how to check their bitness, but it sounds like I can't use imwrite() anyway if it's limited to 3 slices.
Thanks for your help, I'll have to speak to my boss about single-slice BMPs or trying TIFFs instead. I'm sure the software excepts numerous file types, but I was instructed to make them BMPs so I wanted to try to stick to that.
If you really want to stick to double, you might be ready for extra fun. Off the top of my head, the only regular format that supports floating point data is TIFF, but it takes some extra wrangling to get it to work and other applications may not be able to read it.
The original image data was almost certainly integer-class, but I don't know what's happened to it since. If I had to guess, I'd say it probably started life as int16 or uint16 data in a DICOM file.
Good to know, thanks!

Sign in to comment.

More Answers (0)

Categories

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

Products

Release

R2021a

Asked:

JSC
on 26 Jul 2021

Commented:

JSC
on 27 Jul 2021

Community Treasure Hunt

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

Start Hunting!