File Exchange

image thumbnail

Medical Image Reader and Viewer

version 3.9 (917 KB) by Josh Schaefferkoetter
A toolbox to handle reading, viewing, and writing dicom images, supporting simultaneous PET/MR


Updated 23 Mar 2018

View License

This toolbox can read and write medical imaging data in dicom format with the 'readImages' function. The output of this function is a structure containing attributes of the image or volume. This structure can then be used as input into other functions in the toolbox.
This toolbox supports:
- reading and writing of dicom data
- mapping of volume voxel locations
- oblique slice alignment and registration
- manual 3D image rotation
- selecting and extracting single voxel coordinates
- drawing 2D or 3D region-of-interest masks
- coregistered image viewing supports PET/CT and PET/MR

CT = readImages([CT_ImageDirectoryPath]);
PET = readImages([PET_ImageDirectoryPath]);
coords = VolumeViewer3D(PET,CT,'getCoords');
mask = VolumeViewer3D(PET,CT,'drawROI');

Cite As

Josh Schaefferkoetter (2020). Medical Image Reader and Viewer (, MATLAB Central File Exchange. Retrieved .

Comments and Ratings (70)

I am a biomedical engineering student at Rowan University. My capstone project surrounds the task of finding the volume of a spatious gap within subchondral bone. I have tried several volume rendering toolboxes including, the image processing toolbox, volume viewer, and color thresholder. These can all segment a dicom image based on a manually set threshold. However, these toolboxes cannot creat ROIs, meaning that when an image is segmented, due to the grayscale nature of dicom files, the entire image is highlighted. I am yet to find a program that can perform these three tasks, create a ROI, threshold the ROI, and produce an output volume for the ROI. Does anyone know of a file exchange or toolbox that could assist? I have tried creating my own code to perform these tasks. However, I have been unable to interact with dicom images on my own. I have only been able to create a video player that displays my dicom directory. Any help is greatly appreciated!

Ram Sub

Hi Josh,
thx for the prompt response!
tried it - see below..cleared workspace, all variables... just pointed to one "pet.dcm" file in the "PETscans" folder (that worked with VolumeViewer3D) but I get the following error when pointing to a specific file or the folder.
(there may be something specific with my computer or installation - might be better to connect offline)
>> PET = readImages('pet.dcm')
File read error, try again with another file
[ ]

>> PET = readImages('pet.dcm')
File read error, try again with another file
[ ]

>> PET = readImages ('C:\PETscans')
File read error, try again with another file
[ ]

Hi Ram,
Try pointing "readImages" to a specific file, rather than the folder. If that doesn't work, try to remove all unnecessary dicom files from the directory, so it only finds one simple series (or slice even);

Ram Sub

Hi Josh,
thanks...the following steps (shown in section 1) worked for me for both MR and PET images, however, to use the "transformVoxelSpace(PET, MR)" I am getting the error as shown in section 2, with the same .dcm file .. if I understand correctly, I have to succeed with "readImages" command to use any or all the other commands -right ?
thanks, Ram

*****section 1*****
[MR1, map] = dicomread('sub-OAS30001_ses-d0757_run-01_T1w.dcm');
MR1V = squeeze(MR1);
VolumeViewer3D (MR1V)

*****section 2****
>> MR1J = readImages ([‘filepathname'])
Slices belonging to one series in the current directory may have different sizes
MR1J =
struct with fields:
nSeries: 0

Hi Ram,
I guess your MR series must contain multiple slices/volumes of the same spatial location, e.g. 4D dynamic, multiple B values, etc. and so the viewer will only show the last instance. The first error you get it for the display range, if your loaded image is all zeros, for example (put a break point at line 3868 and see what is the value of "handles.display.images.cLim", then work back from there). I think the viewer can handle mixing 3D and 2D data, but in case it can't, you can do this

newPET = transformVoxelSpace(PET, MR);

This will extract the PET slice corresponding to your single MR slice in a new variable.

Ram Sub

Hi Josh, thanks for this detailed package. I have two questions...

1. I have read the dicomfile from a MR session. However, I get the following error.
>> VolumeViewer3D(MR)
Displaying last frame of dynamic series
Error using
Error setting property 'CLim' of class 'Axes':
Value must be a 1x2 vector of numeric type in which the second element is larger than
the first and may be Inf

Error in VolumeViewer3D>setDisplayWindow (line 3868)

Error in VolumeViewer3D>loadVolume (line 3366)

Error in VolumeViewer3D (line 431)
2. Once the above error is resolved... how do I fuse the image slices from a PET session, which has 25 slices (.dcm) files and the MR has one .dcm file.


ilke tunali

Is there a way to export the co-registered image?


Thanks Josh!

Hi Sonal,
Search for the string 'Resize' in VolumeViewer3D.m and enable it for the main figure.


Hey Josh, how can I enable the maximize button on the gui window?

Every time I restart the Matlab I keep getting this error and no code is changed

Error in VolumeViewer3D>initiateObject (line 7267)
if ~isempty(test)

Error in VolumeViewer3D>formatFigure (line 1937)
f = initiateObject('3DviewerFig','figure',str);

Error in VolumeViewer3D>initialSetup (line 1558)
handles.figure.f1 = formatFigure(handles.figure.figPos);

Error in VolumeViewer3D (line 184)

Dear all,

this is my code to view CT image by slice
P = zeros(256, 256, 72);
for K = 1 : 72
petname = sprintf('I4%03d.dcm', K);
P(:,:,K) = dicomread(petname);

then, this is my code for view SPECT image by slice,

Noted: all my 512 slice SPECT image stored in one file.
[spect map]=dicomread('128x128');
info = dicominfo('128x128');

Anybody can help me to fuse both SPECT and CT images?

Jie Deng

Huan Liu

Hi Josh,thank you very much for your reply. I will follow your help and have a careful look at the function "coregisterLocs". Thank you very much.

Hi Huan,
The image volumes are interpolated on a new set of mutual points, which are rotated and resampled, but not translated. The program finds the rotation matrix that transforms the orientation defined by the "Image Orientation Patient" (axes-cosine vector) from one image volume to the other. It then resamples both images to the same pixel grid in that space. Check the function "coregisterLocs" for an idea.

Huan Liu

Hi Josh,I encountered a problem when I read your code and used image for testing,after PET and MRI images are registered , according to the way of planning system,how to obtain translation and rotation?Looking forward to your reply!Thanks very much.

It's a simple conversion but you need the information about injected dose, uptake time etc. See the function 'calculateSUV' for an idea...

Dan Smith

I'm trying to take a .mat file converted from a DICOM image and convert back the SUV values that were changed upon the conversion to show up in the mat file. Can you help?

Hello. I just tried this toolbox and I encountered this problem when I read in DICOM format images. I didnt change anything. Can u help me ?

Attempt to execute SCRIPT test as a function:
C:\Users\ariuka\Desktop\diplom\my code\test.m

Error in VolumeViewer3D>initiateObject (line 7267)
if ~isempty(test)

Error in VolumeViewer3D>formatFigure (line 1937)
f = initiateObject('3DviewerFig','figure',str);

Error in VolumeViewer3D>initialSetup (line 1558)
handles.figure.f1 = formatFigure(handles.figure.figPos);

Error in VolumeViewer3D (line 184)

Error in test (line 4)
tic; VolumeViewer3D(PET); toc

There will only be an output if you pass 'getCoords' or 'drawROI' arguments. In these cases, the output will match the space of the first input (not the "aligned" space used for viewing, for example if using the 'align' argument). When running the tool, read the printed statements displayed in the command window - they should help you to understand what the program is doing.

yes sir, i have corrected that problem( i was reading the images with readDicomImages and now i have used readImages).
the output of 'align' or 'trim' is not giving registered images
i have 23 mri image sequences and 47 pet image sequences. both mri and pet are of dicom standard. do i need to apply any other step to successfully implement registration.

Your inputs are not correct. Were the mr1 and pet1 structures returned by the function 'readImages'?

Sir i am unable to get the coordinates, the following error is displayed:
coords = VolumeViewer3D(mr1,pet1,'getCoords');
Image data is not defined in (structure) input 1 ignoring (structure) input 1
Image data is not defined in (structure) input 2 ignoring (structure) input 2
Undefined function or variable "siz".

Error in VolumeViewer3D (line 361)
if ~(numel(size(inStruct.locX))==numel(siz) && all(size(inStruct.locX)==siz)) || ...

This toolbox was designed to show the coregistered slices in a common display axis, so the volumes are interpolated to share the same image matrix and pixel dimensions. By default, the target interpolation points are generated by using the finest resolution between the 2 volumes (found independently in each dimension), and if the final calculated matrix is too big, it is downsampled to produce more manageable data. You can avoid this downsampling by passing the argument 'full' as an additional input to VolumeViewer3D; then the full size interpolation matrix will be used. In this case, the original data will still be interpolated, but the coregistered data will have higher resolution - this may help the issue your are facing.

We are using Medical Image Reader and Viewer to coregister FDG-PET and CT Perfusion datasets. The registration works very well, but we are now realizing that the original resolution and matrix size is modified and interpolated. It would be very helpful for us, if the original resolutions and matrix sizes could be preserved. Do you see a possibility to do this? Thx

both of VolumeViewer3D(PET,CT) and VolumeViewer3D(PET) give me the voxel count (in side the box (Bq/ml:)), not SUV value; what is the solution to this problem?

put a breakpoint on the 2nd line of calculateSUV function. Then call "parseInputs(varargin{:});" at the command line and see what is the error. PM me if you need more help

Thanks @Josh to replay me ,,,,, i am try it but it failed so try to putting the all parameters (injection dose , start injection time, aquestion time, half life time for FDG, scale factor, dose calibration factor ) from dicom header and try to test it but it also not work internal the viewer ...... can you help me and tell me steps to how it work.

Hi Mahmoud,
It's likely that you are missing something needed to compute the SUV conversion factor. Put a breakpoint at the beginning of the function "calculateSUV" to make sure all the necessary information is being passet to it.

Thanks for the availability this toolbox but how using SUV function to show the SUV internal the Volume Viewer in place of Bq/ml.


Huan Liu

Hi Josh,thanks for your reply.I'm so sorry I do not have your email,Can you give me your email address,I sent email to you,thanks!

Hi Huan,
I never received a message from you. Either contact me directly or turn on the option for me to contact you directly.

Huan Liu

Hi Josh,I encountered this problem when I read in DICOM format images,I read images with the folder that you wrote,I've tried it many times and it has always been this error.The error as follow:
E: \ Softwale \ R2014a \ toolbox \ dirart_programs_06_02_2011 \ dirart_programs_06_02_2011 \ support_programs \ matlab levelset toolbox \ test.m
Error VolumeViewer3D> StartObject (line 7256)
if ~ isempty (test)
Error VolumeViewer3D> formatFigure (line 1931)
f = GetObject ('3DviewerFig', 'figure', str);
Error VolumeViewer3D> initialSetup (line 1552)
handles.figure.f1 = formatFigure (handles.figure.figPos);
Error VolumeViewer3D (line 184)
initialSetup (inStruct);
Examples (line 21)
Can you help me analyze what went wrong?
Can you give me a help?Thanks!

Huan Liu

Huan Liu

Ok, thanks a lot ,I've sent you an email at fileexchange.Please give me a help for the work,thanks very much!

It's not clear what you are doing - have you modified the code? Please contact me directly if you need more help

Huan Liu

Hi Josh,I downloaded your Medical Image Reader and Viewer code, I imported the image but there was an error trying to execute SCRIPT test as a function:
E: \ Softwale \ R2014a \ toolbox \ dirart_programs_06_02_2011 \ dirart_programs_06_02_2011 \ support_programs \ matlab levelset toolbox \ test.m

Error VolumeViewer3D> StartObject (line 7256)
if ~ isempty (test)

Error VolumeViewer3D> formatFigure (line 1931)
f = GetObject ('3DviewerFig', 'figure', str);

Error VolumeViewer3D> initialSetup (line 1552)
handles.figure.f1 = formatFigure (handles.figure.figPos);

Error VolumeViewer3D (line 184)
initialSetup (inStruct);

Examples (line 21)
tic; VolumeViewer3D (PET); toc
Can you help me solve it?

HiJosh and everyones, i have face this problem? please help me

VolumeViewer3D(p, c)
coregistering volumes...
Cannot find an exact (case-sensitive) match for 'Settings'

The closest match is: settings in C:\New folder\pet\settings.m

Error in VolumeViewer3D>initialSetup (line 1535)
s = Settings;

Error in VolumeViewer3D (line 184)

At line 230 in dicm_hdr, the operation s.PixelData.Start = p.iPixelData; creates the structure field 'PixelData' within structure 's'. Since your version is complaining, try to add the following line just before this, at line 229

s.PixelData = struct;

Let me know if this works. If it does, I'll make the change and update the version - if not, try to share your data so I can attempt to reproduce the error on my end.

Jie Deng

Hi Josh, it says 'File read error, try again with another file', followed by a pop up window for single file selection. When I select a single .dcm file, here is the error msg. They are GE PET images.

Field assignment to a non-structure array object.

Error in dicm_hdr (line 230)
s.PixelData.Start = p.iPixelData;

Error in readImages>parseInputs (line 363)
test = dicm_hdr([imageDir imageFiles{1}]);

Error in readImages (line 87)
inStruct = parseInputs(varargin{:});

What is the problem you are having? Put a breakpoint on the line containing the call to 'readDicomImages' then call it from the command line to produce the error.

Jie Deng

Thanks for building and sharing this toolbox, very helpful! I am currently using 2017a version but encountered a problem reading images using 'readImages', do you have any idea why?

Trina Kok


you can do this easily (e.g. if your mask has the same dimensions as PET.volumes):

mask = logical(mask);
VolumeViewer3D(PET, mask);


Sorry Josh, i have presented my question badly. In fact, I have already my mask and I'd like to show it together with PET-CT scan,for example, with "contour" function. But i'm not sure where i should add these codes in your original codes.
Thank you :)


For example, say you want make a mask of an image 'Im', matching its dimensions, [imX, imY, imZ], for all pixels above 'threshold' in a 11x11x11 box centered on [x, y, z], you could do something like this:

mask = false(imX, imY, imZ);
mask(x - 5 : x + 5, y - 5 : y + 5, z - 5 : z + 5) = true;
mask = mask & Im > threshold;


Thanks for the reponse. I have fixed missed information in my dicom file :) And SUV works well! I'm now trying to add a contour mask on the image. Hope for suggestions, thank you :)


Thanks Yuntao. The viewer shows PET SUV by default, but it must have all the required information from the Dicom, i.e. injection and scan times, subject mass, image quantification units, and radiotracer. Put a breakpoint on the call to 'calculateSUV', then call it manually from the prompt. This will point to the problem.


Thank you Josh Schaefferkoetter. That's a great job which helps me a lot on my project. I think it will be better if the toolbox can also show the suv value :)

Amazing contribution Josh. This tool helped me a lot :)!


The function was looking for a dicom field that did not exist in those TCIA images. I added a check to avoid this - try the new version. Thanks for pointing this out.


Hi, nice toolbox!

I tried to read in an image from The Cancer Imaging Archive (TCIA) but was unable to. The message is 'File read error, try again with another file'. The message is repeated for any single slice I choose in the series.

The data can be retrieved here:, Subject ID: QIN-HEADNECK-0003

Josh, thank you for the hint. I just doubled each font size and now I have a nice display. I am using your viewer on my iMac 27" with 2560 x 1440 pixels. The original fonts display was really tiny and hard to read. Now it works fine.

Thank your for this helpful toolbox which I am using for my research work!


Thanks for the feedback. The viewer was tested at high DPI and normal 1080 resolution. What size is your display?

The quick fix would be to do a ctrl-F search through VolumeViewer3D.m for 'FontSize' and change all the necessary field values. Let me know which value works best for the screen you are using.

Is there any chance to increase the font size of the sliders, value outputs and handles in the 3D Viewer window? Unfortunately on my machine everything is pretty small on the screen. But besides that drawback the 3D Viewer is superb!

I'll consider adding these to the next version. Thanks for the feedback!

Just in case it is useful for others,
With Matlab2014a I needed to add a try/catch in VolumeViewer3D.m (line 3372)
if s.matlab.desktop.HighDPISupport
hAxOffset = 0.0005;
vAxOffset = 0.0005;
hAxOffset = 0.0007;
vAxOffset = 0.001;

Very useful tool. I had to adapt it to read GE images from the cancer imaging archive, because some tags in the dicom info are vendor-specific. I used the dictionary from
I changed in all cases:
dict = dicm_dict('GE');
meta = dicm_hdr([imageDir '\' imageFile], dict);
instead of:
meta = dicominfo([imageDir '\' imageFile]);

Where/how should I share the data?

Thanks for the feedback. I wrote the code to prompt for new image data if any errors were found, this is convenient but makes it tricky to troubleshoot - maybe I'll think of a different way to handle this... In the meantime, if you can share your dicom data, I'll take a look.

Please ignore that last comment, I pressed enter by mistake. The current version does not seem to work for me, using the readImages function, even if I provide the directories it opens a file finder, and whenever I select a file it tells me there is a "File read error, try again with another file."

Hello, getting a file read error

The output variable is now initialized as a structure so should fix the problem. Let me know if it still doesn't work.

Looks nice program, but I have a similar problem as payam. After loading GE images with MATLAB 2015b:
Field assignment to a non-structure array object.

Error in VolumeViewer3D>parseInputs (line 397)
out.modality = 'VOL';

Error in VolumeViewer3D (line 36)
inStruct = parseInputs(varargin);

I loaded several PET studies from the TCIA site, including the phantom data, and found a small bug related to the GE and Philips series naming convention; I couldn't reproduce your error though. With which specific data sets were you having issues?

The toolbox seems good.
I have tried to read a PET volume from TCIA ( using readImages. I faced this error:

Field assignment to a non-structure array object.

Error in readImages (line 82)
out.nSeries = nSeries;

Also the same error for phantom images. I am using Matlab 2015b.



Version check for high DPI displays

fixed high DPI display bug

bug with reading dicom

small bug with writing dicom

fixed bug for reading dicom files with no extension

performance tweaks

updated examples

faster image coregistration

minor improvements

incomplete filename bug fix

ability to combine 2D and 3D, and volume and mask inputs

improved input handling

improved input and error handling


corrected dicom tag writing

UI formatted for high DPI displays

updated examples

updated examples

Ability to draw and output 2D or 3D mask

output structure initialization

modified coregistration

GE and Philips series naming convention bug fix

minor tweaks

fixed smoothing functionality

small bug fix

minor tweaks and enhancements

updated examples

faster and more accurate interpolation

performance improvements

bug fixes

improved handling of large image matrices

faster and more efficient memory handling

MATLAB Release Compatibility
Created with R2017a
Compatible with any release
Platform Compatibility
Windows macOS Linux

Inspired by: freezeColors / unfreezeColors, xiangruili/dicm2nii