function varargout = imlook3d(varargin)
% IMLOOK3D M-file for imlook3d.fig
%      IMLOOK3D, by itself, creates a new IMLOOK3D or raises the existing
%      singleton*.
%
%      H = IMLOOK3D returns the handle to a new IMLOOK3D or the handle to
%      the existing singleton*.
%
%      IMLOOK3D('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in IMLOOK3D.M with the given input arguments.
%
%      IMLOOK3D('Property','Value',...) creates a new IMLOOK3D or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before imlook3d_OpeningFunction gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to imlook3d_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% EXAMPLE:
%  Let us first load the mri image in Matlab using
%  >load mri;
%  and then run imlook3d
%  >imlook3d(squeeze(D)); % squeeze removes singleton dimensions
%
% Descriptions of Menus
% 
% ImFile:
% 
% -READ FROM WORKSPACE: Reads or displays images existing in the 
%  workspace(base).
% 
% -READ A STACK (DISK): Reads (displays)slices of images into a 3D array creating
%  a 3D image. It reads them from the disk. A file browser pups up and 
%  allows the user to pick up the first file in the series. It reads all
%  the files in the directory that has similar names except a suffix 
%  changing for each file. 
% 
%  For example: slice01.tif, slice01.tif,...,slice0N.tif 
% 
% -READ DICOM SERIES: 
%  Reads/displays series of DICOM images into a 3D array. A file browser 
%  pups up and allows users to select the first file in the series. 
%  It reads all the files in the directory that has similar names 
%  except a suffix changing for each file. 

% -SAVE SLICE AS TIFF:
%  Saves the current slice as a tiff image.

% -SAVE INTO WORKSPACE: This saves displayed 3D image into workspace as
%  a 3D variable. This may be useful to save the 3D image that is 
%  read by "read a stack (disk)".
%
% ImTools:
% 
% -PIXVAL: Allows looking at pixel intensities.
% -HISTOGRAM: Displays the histogram of the current image (slice).
% -PROFILE: Allows plotting intensity profiles across the image in an
%  interactive manner.
% -ADJUST INTENSITY RANGE: Allows adjusting the intensity range for 
%  the current slice. 
% -GLOBAL INTENSITY WINDOWING:
%  If not checked,not global, the intensity limits are set to [min(currentslice)
%  max(currentslice)]
%  
% VIEW MENU:
% 
%  This pup-up menu allows users to change the view of the image 
%  from transverse to sagittal or coronal views. It assumes that
%  original image is in transverse mode. 
%

% Copyright(c) Omer Demirkaya
% Last Modified by GUIDE v2.5 22-May-2007 21:27:00
% Begin initialization code - DO NOT EDIT

% This entire code or part of it could be modified and used if the due 
% credit to the original author is given.
%------------------------------------------------------------------

gui_Singleton = 0;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @imlook3d_OpeningFcn, ...
    'gui_OutputFcn',  @imlook3d_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if nargin & isstr(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end
if isempty(varargin)
    disp('There was no image to display');
    disp('USAGE: >>imlook3d(img) or use ImFile menu to load an image');
    varargin{1,1} = zeros(32,32);
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before imlook3d is made visible.
function imlook3d_OpeningFcn(hObject, eventdata, handles, varargin)
% Choose default command line output for imlook3d
if isempty(varargin{:})
    return;
end
handles.output = hObject;
Std.Interruptible = 'off';
Std.BusyAction = 'queue';
Ax       = Std; 
Ax.Units = 'Pixels'; 
Ax.ydir  = 'reverse';
Ax.XLim  = [.5 128.5]; 
Ax.YLim  = [.5 128.5]; 
Ax.XTick = []; 
Ax.YTick = [];
Ax.CLimMode = 'auto';

set(handles.axes1,Ax);

Img = Std;Img.CData = [];Img.Xdata = [];Img.Ydata = [];
Img.CDataMapping = 'Scaled';
Img.Erasemode = 'none';
handles.image = Img;
inpargs = varargin{:};
[r,c,z] = size(inpargs);
handles.image.CData     = inpargs;
handles.imSize          = [r,c,z];
handles.viewtype        = 1;
handles.imageModality   = [];
handles.hText           = [];
handles.global_windowing= 0;
handles.SliceThickness  = [];
handles.imageInfo       = [];
handles.currentSliceNumber = 1;
handle.image.SliceSensitivityFactor =[];

handles.oimage = handles.image;
cimg = handles.image.CData(:,:,1);
% Create image object and set the properties
handles.ImgObject = image(Img,'Parent',handles.axes1);
set(handles.SliceNumEdit,'String',1);
set(handles.figure1,'Colormap',gray,'Units','Pixels');
% Set the properties of the axes
cclim =[min(cimg(:)) max(cimg(:))];
if (cclim(2)>0 & cclim(2)-cclim(1) ~= 0)
    set(handles.axes1,'CLim',cclim,...
        'PlotBoxAspectRatio',[c r 1]);
end
set(handles.axes1,'XLim',[1 c],'Ylim',[1 r],...
    'PlotBoxAspectRatio',[c r 1]);
set(handles.ImgObject,'Xdata',[1 c],'Ydata',[1 r],'CData',cimg);
drawnow
% Set the slider's value and step size
if z > 1
    turnDisplayButtons(handles,'on')
    set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
        1,'SliderStep',[1.0/double(z-1) 1.0/double(z-1)]);
end
% Define the line and associate it with the context menu
set(handles.ImgObject,'UIContextMenu',handles.ImMaps);
% Update handles structure
%--------------------------------------------------------------------------
%% Set appdata for the inntensity adjustment GUI
setappdata(0  ,  'hMainGui'    , gcf);
hMainGui = getappdata(0, 'hMainGui');
maxINT = max(max(max(handles.image.CData)));
minINT = min(min(min(handles.image.CData)));
intensityParam = struct('lowerLimit',cclim(1),'upperLimit',cclim(2),...
    'maxIntensity', maxINT, 'minIntensity',minINT);
handles.intensityParam = intensityParam;
setappdata(hMainGui,  'intensityParam'  ,intensityParam);
%% Read and display logo image
% ----------------------------------------------------------------
fdir = which('imlook3d');
txt = [fdir(1:end-10) '\imlook3d.png'];
imlogo = imread(txt);
Sz= size(imlogo);
flogo = figure('Position',[10000 10000 Sz(2) + 4 Sz(1) + 4],'name','Imlook3D',...
    'numbertitle','off','menubar','none');
movegui(flogo,'center');
set(flogo,'Units', 'pixels');
image(imlogo(:,:,1:3))
set(gca, ...
    'Visible', 'off', ...
    'Units', 'pixels', ...
    'Position', [2 2 Sz(2) Sz(1)]);
text(220,16,'3D Image Display Tool','Fontsize',12);
text(130,355,'Version 1.2: Copyright 2006, Omer Demirkaya','Fontsize',8);
pause(3);delete(flogo);clear imlogo
%% ------------------------------------
%--------------------------------------------------------------------------
guidata(hObject, handles);
%--------------------------------------------------------------------------
% --- Outputs from this function are returned to the command line.
function varargout = imlook3d_OutputFcn(hObject, eventdata, handles)
 varargout{1} = handles.output;
% --- Executes during object creation, after setting all properties.
function SliceNumSlider_CreateFcn(hObject, eventdata, handles)
usewhitebg = 1;
if usewhitebg
    set(hObject,'BackgroundColor',[.9 .9 .9]);
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

% --- Executes on slider movement.
%------------------------------------------------------------
function SliceNumSlider_Callback(hObject, eventdata, handles)
NewVal= round(get(hObject,'Value'));
cimg = handles.image.CData(:,:,NewVal);
if ~(handles.global_windowing)
    cclim = [min(cimg(:)) max(cimg(:))];
    if (cclim(2)>0 & cclim(2)-cclim(1) ~= 0)
        set(handles.axes1,'CLim',[min(cimg(:)) max(cimg(:))])
    end
else
    set(handles.axes1,'CLim',[handles.intensityParam.lowerLimit  handles.intensityParam.upperLimit])
end  
set(handles.ImgObject,'Cdata',cimg);
set(handles.SliceNumEdit,'String',num2str(NewVal));
drawnow
guidata(hObject, handles);
% --- Executes during object creation, after setting all properties.
function SliceNumEdit_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end
%--------------------------------------------------------------------------
function SliceNumEdit_Callback(hObject, eventdata, handles)
z= size(handles.image.CData,3);
strg = get(hObject,'String');
if str2num(strg)>=1 & str2num(strg)<=z
    set(handles.SliceNumSlider,'Value',str2num(strg));
    cimg = handles.image.CData(:,:,str2num(strg));
    set(handles.ImgObject,'Cdata',cimg);
    handles.currentSliceNumber = str2num(strg);
    drawnow
end
if ~(handles.global_windowing)
    cclim = [min(cimg(:)) max(cimg(:))];
    if (cclim(2)>0 & cclim(2)-cclim(1) ~= 0)
        set(handles.axes1,'CLim',[min(cimg(:)) max(cimg(:))])
    end
else
    set(handles.axes1,'CLim',[handles.intensityParam.lowerLimit  handles.intensityParam.upperLimit])

end 
guidata(hObject, handles);
% --------------------------------------------------------------------
% --------------------------------------------------------------------
function changeColorMaps_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function petColormaps_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function CTcolormaps_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
% --------------------------------------------------------------------
function Hot_Callback(hObject, eventdata, handles)
htable = feval('hot');
set(handles.figure1,'Colormap',htable); 
if handles.imSize(3)> 1 
    set(handles.SliceNumEdit,'BackgroundColor',[.1 .1 .1],'ForegroundColor','r');
end
guidata(hObject, handles);
% --------------------------------------------------------------------
function Gray_Callback(hObject, eventdata, handles)
htable = feval('gray');
set(handles.figure1,'Colormap',htable);
if handles.imSize(3)> 1 
    set(handles.SliceNumEdit,'BackgroundColor','k','ForegroundColor','w');
end
guidata(hObject, handles);
% --------------------------------------------------------------------
function InvGray_Callback(hObject, eventdata, handles)
htable = 1-feval('gray');
set(handles.figure1,'Colormap',htable);
if handles.imSize(3)> 1 
    set(handles.SliceNumEdit,'BackgroundColor','w','ForegroundColor','k');
end
guidata(hObject, handles);
% --------------------------------------------------------------------
function Jet_Callback(hObject, eventdata, handles)
htable = feval('jet');
set(handles.figure1,'Colormap',htable);
if handles.imSize(3)> 1 
    set(handles.SliceNumEdit,'BackgroundColor','b','ForegroundColor','y');
end
guidata(hObject, handles);
% --------------------------------------------------------------------
function boneWindow_Callback(hObject, eventdata, handles)
handles.intensityParam.lowerLimit = -250;
handles.intensityParam.upperLimit = 1250;
set(handles.axes1,'CLim',[-300 1250])
guidata(hObject,handles);
% --------------------------------------------------------------------
function lungWindow_Callback(hObject, eventdata, handles)
handles.intensityParam.lowerLimit = -2500;
handles.intensityParam.upperLimit = 1100;
set(handles.axes1,'CLim',[-2500 1100])
guidata(hObject,handles);
% --------------------------------------------------------------------
function mediasitnalWindow_Callback(hObject, eventdata, handles)
handles.intensityParam.lowerLimit = -450;
handles.intensityParam.upperLimit = 350;
set(handles.axes1,'CLim',[-450 350])
guidata(hObject,handles);
% --------------------------------------------------------------------
%---------------------------------------------------------
% Callbacks for imtoolsmenu
%----------------------------------------------------------
function imToolsMenu_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function imPixval_Callback(hObject, eventdata, handles)
if isempty(handles.hText)
handles.hText = impixelinfoval(handles.figure1,handles.ImgObject);
set(handles.hText,'FontWeight','bold');
set(handles.hText,'FontSize',10);
else
    delete(handles.hText);
    handles.hText =[];
end
guidata(hObject, handles);
% --------------------------------------------------------------------
function imHistogram_Callback(hObject, eventdata, handles)
myhistogram(1)
%-------------------------------------------------------------
function imProfile_Callback(hObject, eventdata, handles)
improfile;
title('Intensity profile');
ylabel('Intensity');
xlabel('Pixel position');
%------------------------------------------------
% Histogram function
% -----------------------------------------------
function myhistogram(htype)
img = getimage(gcbf);
if (htype==1)
    figure;hist(double(img(:)),64);
    title('Slice histogram');
    ylabel('Frequency');
    xlabel('Intensity');
elseif (htype == 2)
    figure;hist(log(double(img(:))+1),64);     
else
    htype = 0;
end
return;

% --- Executes during object creation, after setting all properties.
function popup_view_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end
%-------------------------------------------------------------
% --- Executes on selection change in popup_view.
%-------------------------------------------------------------
function popup_view_Callback(hObject, eventdata, handles)
v = get(hObject,'value');
if v ~=1
    nimg = convert_view(handles.oimage.CData,v);
else
    nimg = handles.oimage.CData;
end
[r,c,z]=size(nimg);
handles.image.CData = nimg;
handles.image.Xdata = [1 c];
handles.image.Ydata = [1 r];
handles.viewtype = v;
handles.imSize = [r,c,z];
reset(handles.axes1); axis off;
set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
    round(z/2),'SliderStep',[1.0/double(z-1) 1.0/double(z-1)]);
set(handles.ImgObject,'Xdata',[1 c],'Ydata',[1 r]);
% Set the properties of the axes

set(handles.axes1,'XLim',[1 c],'YLim',[1 r],'PlotBoxAspectRatio',[c r 1]);

if ~isempty(handles.imageInfo)
    Sthick = handles.imageInfo.SliceThickness;
    if v == 2
        psize = handles.imageInfo.PixelSpacing(1);
        set(handles.axes1,'DataAspectRatio',[1 psize/Sthick  1]);
    elseif v == 3
        psize = handles.imageInfo.PixelSpacing(2);
        set(handles.axes1,'DataAspectRatio',[1 psize/Sthick  1]);
    else
        psize = handles.imageInfo.PixelSpacing;
        set(handles.axes1,'DataAspectRatio',[psize(1) psize(2)  1]);
    end
end
set(handles.SliceNumEdit,'String',num2str(round(z/2)));
cimg = handles.image.CData(:,:,round(z/2));
handles.currentSliceNumber = round(z/2);
set(handles.ImgObject,'Cdata',cimg);
guidata(hObject, handles);
drawnow
%-------------------------------------------------------------
% function s= convert_view(img,desired_view)
% img: input image
% It assumes that the original image is in transverse view(1)
% 1: transverse, 2: coronal, 3: sagittal views
% s: output image
function s= convert_view(img,desired_view)
[r,c,z]=size(img);
switch desired_view
    case 2
        s = permute(img,[3 2 1]);
        s=flipdim(s,1);
    case 3
        s = permute(img,[3 1 2]);
        s=flipdim(s,1);
    otherwise;
end
% --------------------------------------------------------------------
function readOrdinaryImageSeries_Callback(hObject, eventdata, handles)
[filename, pathname] = uigetfile({'*.*'},'Image');
if isequal(filename,0)|isequal(pathname,0)
    setstatus('File not found');
else
    cd(pathname)
    k = findstr(filename,'.');
    fnames = dir(['*' filename(k+1:end)]);
    timg = imread(filename);
    [r,c,z] = size(timg);
    numSlices = size(fnames,1);
    nimg = zeros([r,c,numSlices]);
    if z == 3
        hw=warndlg('Color images will be converted to gray');
        uiwait;
        nimg(:,:,1) = rgb2gray(timg);
    else
        nimg(:,:,1) = timg;
    end
    hwb = waitbar(0,'Reading Images, please wait...');
    for i=2:numSlices
        waitbar(i/numSlices, hwb);
        timg = imread(fnames(i).name);
        [r,c,z] = size(timg);
        if z == 3
            nimg(:,:,i) = rgb2gray(timg);
        else
            nimg(:,:,i) = timg;
        end
    end
    close(hwb);
    clear timg;
    [r,c,z]=size(nimg);
    handles.image.CData = nimg;
    handles.image.Xdata = [1 c];
    handles.image.Ydata = [1 r];
    handles.imSize = [r,c,z];
    handles.SliceThickness = 1;
    if z==1
        sliderStep = 1;
    else
        sliderStep = 1.0/double(z-1);
    end
    set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
        round(z/2),'SliderStep',[sliderStep sliderStep]);
    set(handles.ImgObject,'Xdata',[1 c],'Ydata',[1 r]);
    % Set the properties of the axes
    set(handles.axes1,'XLim',[1 c],'YLim',[1 r],'PlotBoxAspectRatio',[c r 1]);
    set(handles.SliceNumEdit,'String',num2str(round(z/2)));
    cimg = handles.image.CData(:,:,round(z/2));
    set(handles.ImgObject,'Cdata',cimg);
    handles.oimage = handles.image;
    guidata(hObject, handles);
    clear nimg;
    if z > 1
        turnDisplayButtons(handles,'on');
        set(handles.popupmenu_imageModality,'visible','off');
    end
    drawnow  
end
% --------------------------------------------------------------------
function saveImageIntoWorkspace_Callback(hObject, eventdata, handles)
assignin('base','IIMG',handles.image.CData);
% --------------------------------------------------------------------
function imfileMenu_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function ImMaps_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
% --------------------------------------------------------------------
function readWorkspaceImage_Callback(hObject, eventdata, handles)
Vars = evalin('base','who;');
if ~isempty (Vars)
    [s,v] = listdlg('PromptString','Select an image:',...
        'SelectionMode','single',...
        'Listsize',[150,200],...
        'ListString',Vars);
    if (v)
        imlook3d(evalin('base',Vars{s}));
    end
else
    disp('No workspace variable');
end

% --------------------------------------------------------------------
% Reads series of dicom images into a 3D array
% --------------------------------------------------------------------
function readDicomPETSeries_Callback(hObject, eventdata, handles)
[filename, pathname] = uigetfile({'*.dcm';'*.*'},'Image');
if isequal(filename,0)|isequal(pathname,0)
    setstatus('File not found');
else
    cd(pathname)
    k = findstr(filename,'.');
    fnames = dir([filename(1:2) '*']);
    info = dicominfo(filename);
    r = info.Width;
    c = info.Height;
    numSlices = length(fnames);
    nimg = zeros([r,c,numSlices]);
    hw = waitbar(0,'Reading volume image, please wait...');
    for i=1:numSlices
        info = dicominfo(fnames(i).name);
        nimg(:,:,info.ImageIndex) = info.RescaleSlope*dicomread(info)+info.RescaleIntercept;
        waitbar(i/numSlices,hw);
    end
    close(hw);
    
    fields = {'Filename','FileModDate','FileSize','ImageType','Width','Height','BitDepth',...
        'NumberOfFrames','Rows','Columns','BitsAllocated','SmallestImagePixelValue',...
        'LargestImagePixelValue','PixelDataGroupLength','StudyDescription','SeriesDescription',...
        'StudyID','ImageID','PatientID','SliceThickness','StudyDate','AcquisitionDate',...
        'AcquisitionTime','PixelSpacing'};
    
    myinfo = keepfield(info,fields);
    
    handles.imageInfo = myinfo;
 
    [r,c,z]=size(nimg);
    handles.image.CData = nimg;
    handles.image.Xdata = [1 c];
    handles.image.Ydata = [1 r];
    handles.imSize = [r,c,z];
    set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
        round(z/2),'SliderStep',[1.0/double(z-1) 1.0/double(z-1)]);
    set(handles.ImgObject,'Xdata',[1 c],'Ydata',[1 r]);
    % Set the properties of the axes
    set(handles.axes1,'XLim',[1 c],'YLim',[1 r],'PlotBoxAspectRatio',[c r 1]);
    set(handles.SliceNumEdit,'String',num2str(round(z/2)));
    cimg = handles.image.CData(:,:,round(z/2));
    set(handles.ImgObject,'Cdata',cimg);
    handles.oimage = handles.image;
    guidata(hObject, handles);
    clear nimg;
    if z>1
        turnDisplayButtons(handles,'on')
    end
    handles.imageModality = 1;
    set(handles.popupmenu_imageModality,'visible','on');
    set(handles.popupmenu_imageModality,'value',1);
    drawnow  
end
% --------------------------------------------------------------------
function saveCurrentSlice_Callback(hObject, eventdata, handles)
[filename, pathname,filterindex] = uiputfile({'*.png';'*.tif';'*.jpg'},'Image');
fformat = {'png','tif','jpg'}; 
if isequal(filename,0) | isequal(pathname,0)
    warndlg('No file name entered!');
else
    I= getframe(handles.axes1);
    I=frame2im(I);
    buffer=pwd;
    cd(pathname);
    imwrite(I,filename,fformat{filterindex});
    cd(buffer);
end
% --------------------------------------------------------------------
function adjust_intensity_window_Callback(hObject, eventdata, handles)
setappdata(0  ,  'hMainGui'    , gcf);
hMainGui = getappdata(0, 'hMainGui');
maxINT = max(max(max(handles.image.CData)));
minINT = min(min(min(handles.image.CData)));
cclim = get(handles.axes1,'CLim');
intensityParam = struct('lowerLimit',cclim(1),'upperLimit',cclim(2),'maxIntensity',maxINT, 'minIntensity',minINT);
setappdata(hMainGui,  'intensityParam', intensityParam);
adjustIntensityRangeGui;
uiwait;
hMainGui = getappdata(0,'hMainGui');
handles.intensityParam = getappdata(hMainGui,  'intensityParam');
guidata(hObject, handles);
% -----------------------------------------------------------------
function global_intensity_windowing_Callback(hObject, eventdata, handles)
str = get(gcbo,'Checked');
if strcmp(str,'off')
    handles.global_windowing =1;
    set(gcbo,'Checked','on');
else
    handles.global_windowing =0;
    set(gcbo,'Checked','off');
end
guidata(hObject,handles);
% --------------------------------------------------------------------
function renderVolume_Callback(hObject, eventdata, handles)
img= handles.image.CData;
if size(img,3) > 1
    prompt = {'Enter Lower Threshold:','Enter Upper Threshold:'};
    dlg_title = 'Enter Thresholds'; num_lines = 1; def = {'1','2'};
    answer = inputdlg(prompt,dlg_title,num_lines,def);
    T(1) = str2num(answer{1,1});
    T(2) = str2num(answer{2,1});
    nimg = img >= T(1) & img <= T(2);
    s = size(img);
    vlim=[1 s(2) 1 s(1) 1 s(3)];
    figure;
    % set(get(hndl,'CurrentAxes'),'YDir','rev');
    [x y z D] = subvolume(nimg,vlim);
    p = patch(isosurface(x,y,z,D,0),'FaceColor','r','EdgeColor','none');
    p2 = patch(isocaps(x,y,z,D,0),'FaceColor','interp','EdgeColor','none');
    set(gca,'XTick',[],'YTick',[],'ZTick',[],'Box','on','Color','c');
    isonormals(x,y,z,D,p);
    axis tight;
    daspect([1 1 1])
    lighting gouraud
else
    msgbox('This is not a volume image','Error','modal');
end

% --------------------------------------------------------------------
% READS CT DICOM IMAGES
% --------------------------------------------------------------------
function readDicomCTSeries_Callback(hObject, eventdata, handles)
[filename, pathname] = uigetfile({'*.dcm';'*.*'},'Image');
if isequal(filename,0)|isequal(pathname,0)
    setstatus('File not found');
else
    cd(pathname)
    k = findstr(filename,'.');
    fnames = dir(['*' filename(k(end)+1:end)]);
    info = dicominfo(filename);
    r = info.Width;
    c = info.Height;
    numSlices = length(fnames);
    nimg = zeros([r,c,numSlices]);
    hwb = waitbar(0,'Reading Images, please wait...');
    for i=1:numSlices
        waitbar(i/numSlices, hwb);
        info = dicominfo(fnames(i).name);
        nimg(:,:,i) = info.RescaleSlope*dicomread(info)+info.RescaleIntercept;
    end
    close(hwb);
    
    fields = {'Filename','FileModDate','FileSize','ImageType','Width','Height','BitDepth',...
        'NumberOfFrames','Rows','Columns','BitsAllocated','SmallestImagePixelValue',...
        'LargestImagePixelValue','PixelDataGroupLength','StudyDescription','SeriesDescription',...
        'StudyID','ImageID','PatientID','SliceThickness','StudyDate','AcquisitionDate','AcquisitionTime','PixelSpacing'};
    
    myinfo = keepfield(info,fields);
    handles.imageInfo = myinfo;
    
    [r,c,z]=size(nimg);
    handles.image.CData = nimg;
    handles.image.Xdata = [1 c];
    handles.image.Ydata = [1 r];
    handles.imSize = [r,c,z];
    set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
        round(z/2),'SliderStep',[1.0/double(z-1) 1.0/double(z-1)]);
    set(handles.ImgObject,'Xdata',[1 c],'Ydata',[1 r]);
    % Set the properties of the axes
    set(handles.axes1,'XLim',[1 c],'YLim',[1 r],'PlotBoxAspectRatio',[c r 1]);
    set(handles.SliceNumEdit,'String',num2str(round(z/2)));
    cimg = handles.image.CData(:,:,round(z/2));
    set(handles.ImgObject,'Cdata',cimg);
    handles.oimage = handles.image;
    guidata(hObject, handles);
    clear nimg;
    handles.imageModality = 4;
    if z>1
        turnDisplayButtons(handles,'on')
    end
    handles.imageModality = 2;
    set(handles.popupmenu_imageModality,'visible','on');
    set(handles.popupmenu_imageModality,'value',2);
    drawnow  
end
% --------------------------------------------------------------------
function imageProcessMenu_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function imageThresholdManual_Callback(hObject, eventdata, handles)
img = getimage(gcbf);
th = cell2mat(inputdlg('Enter Threshold','Threshold',1,{'100'}));
if ~isempty(th)
    th = str2num(th);
    figure;imagesc(img>th);axis image;axis off
    title('Thresholded Image');
end
% --------------------------------------------------------------------
function automatedThresholding_Callback(hObject, eventdata, handles)
img = getimage(gcbf);
th=otsu_th(single(img(:)),64);
figure;imagesc(img>th);axis image;axis off
title('Thresholded Image');
% --------------------------------------------------------------------
% READS DICOM IMAGE SINGLE OR VOLUME
% --------------------------------------------------------------------
function readSingleDicomImage_Callback(hObject, eventdata, handles)
[filename, pathname] = uigetfile({'*.dcm';'*.*'},'Image');
if isequal(filename,0)|isequal(pathname,0)
    setstatus('File not found');
else
    cd(pathname)
    info = dicominfo(filename);  
    if isfield(info,'NumberOfSlices')
        z = info.NumberOfSlices;
    elseif isfield(info,'NumberOfFrames')
        z = info.NumberOfFrames;
    end
    if isfield(info,'SliceThickness')
        handles.SliceThickness= info.SliceThickness;
    end 
    % Reading dicom image
    nimg = squeeze(dicomread(info));
    [r,c,z]=size(nimg);
    handles.image.CData = nimg;
    handles.image.Xdata = [1 c];
    handles.image.Ydata = [1 r];
    handles.imSize = [r,c,z];
    
    if z >1
        turnDisplayButtons(handles,'on');
        set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
            round(z/2),'SliderStep',[1.0/double(z-1) 1.0/double(z-1)]);
        set(handles.SliceNumEdit,'String',num2str(round(z/2)));
        turnDisplayButtons(handles,'on');
        cimg = handles.image.CData(:,:,round(z/2));
    else
        turnDisplayButtons(handles,'off');
        cimg = handles.image.CData;
    end
    fields = {'Filename','FileModDate','FileSize','ImageType','Width','Height','BitDepth',...
        'NumberOfFrames','Rows','Columns','BitsAllocated','SmallestImagePixelValue',...
        'LargestImagePixelValue','PixelDataGroupLength','StudyDescription','SeriesDescription',...
        'StudyID','ImageID','PatientID','SliceThickness','StudyDate','AcquisitionDate','AcquisitionTime','PixelSpacing'};
    myinfo = keepfield(info,fields);
    handles.imageInfo = myinfo;
   
    % Set the properties of the axes and image object
    set(handles.ImgObject,'XData',[1 c],'YData',[1 r],'CData',cimg);
    set(handles.axes1,'XLim',[1 c],'YLim',[1 r],'PlotBoxAspectRatio',[c r 1],'DataAspectRatio',...
        [1 info.PixelSpacing(2)/info.PixelSpacing(1)  1]);
    handles.oimage = handles.image;
    guidata(hObject, handles);
    clear nimg;
    drawnow  
end
% --------------------------------------------------------------------
% --- Executes on selection change in popup_flip.
function popup_flip_Callback(hObject, eventdata, handles)
v = get(hObject,'value');
switch v
    case 1
       handles.image.CData = flipdim(handles.image.CData,2);
    case 2
        handles.image.CData = flipdim(handles.image.CData,1);
    case 3
        handles.image.CData = flipdim(handles.image.CData,3);
    case 4
    handles.image.CData = handles.oimage.CData;
    otherwise
end
guidata(hObject,handles);

% --- Executes during object creation, after setting all properties.
function popup_flip_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function turnDisplayButtons(handles,bmode)
set(handles.SliceNumSlider,'visible',bmode);
set(handles.SliceNumEdit,'visible',bmode);
set(handles.popup_view,'visible',bmode);
set(handles.popup_flip,'visible',bmode);
set(handles.text1,'visible',bmode);
set(handles.text2,'visible',bmode);
set(handles.text3,'visible',bmode);
set(handles.popup_flip,'visible',bmode);     
return


% --------------------------------------------------------------------
function helpCallback_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
% --------------------------------------------------------------------
function helpMenu_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function helpAboutImlook3d_Callback(hObject, eventdata, handles)
s = sprintf(['IMLOOK3D: 3D Image Display Tool\n',...
    'Version 1.2, Copyright (2006 - Inf and Beyond)\n',...
    'Omer Demirkaya, KFSH&RC']);
msgbox(s,'About IMLOOK3D Tool','modal');
% --------------------------------------------------------------------
function helpDisclaimer_Callback(hObject, eventdata, handles)
s = {'This SOFTWARE DOES NOT (A) MAKE ANY WARRANTY, EXPRESS OR IMPLIED',
    'WITH RESPECT TO THE USE OF THE INFORMATION PROVIDED HEREBY; NOR (B)', 
    'GUARANTEE THE ACCURACY,COMPLETENESS,USEFULNESS,OR ADEQUACY OF ANY',
    'RESOURCES, INFORMATION,SYSTEM,PRODUCT,OR PROCESS AVAILABLE - AT OR', 
    'THROUGH THIS SOFTWARE.'};
msgbox(s,'Disclaimer','modal');

% --------------------------------------------------------------------
function imageInformation_Callback(hObject, eventdata, handles)
if ~isempty(handles.imageInfo)
    imageinfo(handles.imageInfo);
else
    msgbox('There is no image or no information about it','Image Info..','modal');
end

% --------------------------------------------------------------------
function readSingleOrdinaryImage_Callback(hObject, eventdata, handles)
[filename, pathname] = uigetfile({'*.*'},'Image');
if isequal(filename,0)|isequal(pathname,0)
    setstatus('File not found');
else
    cd(pathname)
    info = imfinfo(filename);  
    [img, map]=imread(filename);
    [r,c,z] = size(img);
    handles.image.CData = img;
    handles.image.Xdata = [1 c];
    handles.image.Ydata = [1 r];
    handles.imSize = [r,c,z];
    
    if z > 1   % single slice
    set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
        round(z/2),'SliderStep',[1.0/double(z-1) 1.0/double(z-1)]);
    set(handles.SliceNumEdit,'String',num2str(round(z/2)));
    turnDisplayButtons(handles,'on');
    cimg = handles.image.CData(:,:,round(z/2));
    else
        turnDisplayButtons(handles,'off');
        cimg = handles.image.CData;
    end
    handles.imageInfo = info;
   % Set the properties of the axes and image object
    set(handles.ImgObject,'XData',[1 c],'YData',[1 r],'CData',cimg);
    set(handles.axes1,'XLim',[1 c],'YLim',[1 r],'PlotBoxAspectRatio',[c r 1],'DataAspectRatio',[1 1 1]);
    handles.oimage = handles.image;
    guidata(hObject, handles);
    clear nimg;
    drawnow  
end
% --------------------------------------------------------------------
% SMOOTH IMAGE
% --------------------------------------------------------------------
function smoothVolume_Callback(hObject, eventdata, handles)
if size(handles.image.CData,3) > 1
h = waitbar(0,'Smoothing, please wait...');
handles.image.CData= smooth3(handles.image.CData,'gaussian');
close(h);
set(handles.ImgObject,'Cdata',handles.image.CData(:,:,handles.currentSliceNumber));
guidata(hObject,handles);
end
% --------------------------------------------------------------------
% Voxel dimensions
% --------------------------------------------------------------------
function voxelSize_Callback(hObject, eventdata, handles)
prompt = {'X Size:','Y Size:', 'Z Size'};
dlg_title = 'Enter Voxel Sizes'; num_lines = 1; def = {'1','1','1'};
answer = inputdlg(prompt,dlg_title,num_lines,def);
if ~isempty(answer)
    voxdim(1) = str2num(cell2mat(answer(1,1)));
    voxdim(2) = str2num(cell2mat(answer(2,1)));
    voxdim(3) = str2num(cell2mat(answer(3,1)));
    bw = voxdim > 0; % checking for zero or negative
    if prod(double(bw))
        handles.imageInfo.PixelSpacing(1) = voxdim(1);
        handles.imageInfo.PixelSpacing(2) = voxdim(2);
        handles.imageInfo.SliceThickness  = voxdim(3);
        if handles.viewtype == 2
            set(handles.axes1,'DataAspectRatio',[1 voxdim(1)/voxdim(3)  1]);
        elseif handles.viewtype == 3
            set(handles.axes1,'DataAspectRatio',[1 voxdim(2)/voxdim(3)  1]);
        else
            set(handles.axes1,'DataAspectRatio',[1 voxdim(2)/voxdim(1)  1]);
        end

    end
end
guidata(hObject,handles);
% --------------------------------------------------------------------
% Horizontal Profile
% --------------------------------------------------------------------
function horizontalProfile_Callback(hObject, eventdata, handles)
h = warndlg('Double-click on the row','Pixel Selection');
uiwait;
[c,r,P] = impixel;
f = get(findobj(gcf,'Type','image'));
txt = ['Profile for row: ' num2str(r)];
figure;
plot(f.CData(r,:));title(txt);xlabel('Pixel location');ylabel('Intensity');
% --------------------------------------------------------------------
% Vertical Profile
% --------------------------------------------------------------------
function verticalProfile_Callback(hObject, eventdata, handles)
h = warndlg('Double-click on the column','Pixel Selection');
uiwait;
[c,r,P] = impixel;
f = get(findobj(gcf,'Type','image'));
txt = ['Profile for column: ' num2str(c)];
figure;
plot(f.CData(:,c));title(txt);xlabel('Pixel location');ylabel('Intensity');

% --------------------------------------------------------------------
% --- Executes during object creation, after setting all properties.
% --------------------------------------------------------------------
function popupmenu_imageModality_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
% --------------------------------------------------------------------
% --- Image modality selection
% --------------------------------------------------------------------
function popupmenu_imageModality_Callback(hObject, eventdata, handles)
imMod = get(hObject,'value');
handles.imageModality = imMod;

% --------------------------------------------------------------------
%  Executes MATLAB IMTOOL 
% --------------------------------------------------------------------
function imtoolMATLAB_Callback(hObject, eventdata, handles)
f = get(findobj(gcf,'Type','image'));
imtool(f.CData,[min(f.CData(:)) max(f.CData(:))]);
% --------------------------------------------------------------------
%  helpMenu on Imlook3D
% --------------------------------------------------------------------
function helpIMLOOK3D_Callback(hObject, eventdata, handles)
warndlg('Under Construction and needs help :)');
% --------------------------------------------------------------------
%  Reading MRI images
% --------------------------------------------------------------------
function readDICOMMRISeries_Callback(hObject, eventdata, handles)
[filename, pathname] = uigetfile({'*.dcm';'*.*'},'Image');
if isequal(filename,0)|isequal(pathname,0)
    setstatus('File not found');
else
    cd(pathname)
    k = findstr(filename,'.');
    fnames = dir(['*' filename(k+1:end)]);
    info = dicominfo(filename);
    r = info.Width;
    c = info.Height;
    numSlices = length(fnames);
    nimg = zeros([r,c,numSlices]);
    hwb = waitbar(0,'Reading Images, please wait...');
    for i=1:numSlices
        waitbar(i/numSlices, hwb);
        info = dicominfo(fnames(i).name);
        nimg(:,:,i) = dicomread(info);
    end
    close(hwb);
    
    fields = {'Filename','FileModDate','FileSize','ImageType','Width','Height','BitDepth',...
        'NumberOfFrames','Rows','Columns','BitsAllocated','SmallestImagePixelValue',...
        'LargestImagePixelValue','PixelDataGroupLength','StudyDescription','SeriesDescription',...
        'StudyID','ImageID','PatientID','SliceThickness','StudyDate','AcquisitionDate','AcquisitionTime','PixelSpacing'};
    
    myinfo = keepfield(info,fields);
    handles.imageInfo = myinfo;
    
    [r,c,z]=size(nimg);
    handles.image.CData = nimg;
    handles.image.Xdata = [1 c];
    handles.image.Ydata = [1 r];
    handles.imSize = [r,c,z];
    set(handles.SliceNumSlider,'Min',1,'Max',z,'Value',...
        round(z/2),'SliderStep',[1.0/double(z-1) 1.0/double(z-1)]);
    set(handles.ImgObject,'Xdata',[1 c],'Ydata',[1 r]);
    % Set the properties of the axes
    set(handles.axes1,'XLim',[1 c],'YLim',[1 r],'PlotBoxAspectRatio',[c r 1]);
    set(handles.SliceNumEdit,'String',num2str(round(z/2)));
    cimg = handles.image.CData(:,:,round(z/2));
    set(handles.ImgObject,'Cdata',cimg);
    handles.oimage = handles.image;
    guidata(hObject, handles);
    clear nimg;
    if z>1
        turnDisplayButtons(handles,'on')
    end
    handles.imageModality = 4;
    set(handles.popupmenu_imageModality,'visible','on');
    set(handles.popupmenu_imageModality,'value',4);
    drawnow  
end

% --------------------------------------------------------------------
function cropVolume_Callback(hObject, eventdata, handles)
% hObject    handle to cropVolume (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

[I,rect] = imcrop; 
s = handles.image.CData;
switch handles.viewtype
    case 1
        [r,c,z]  = size(s); 
        oimg = crop3d(s,rect,[1 z]);
    case 2
%         s = permute(img,[3 2 1]);
%         s = flipdim(s,1);
        [r,c,z]  = size(s); 
        oimg = crop3d(s,rect,[1 z]);
    case 3
%         s = permute(img,[3 1 2]);
%         s = flipdim(s,1);
        [r,c,z]  = size(s); 
        oimg = crop3d(s,rect,[1 z]);
    otherwise;
end
imlook3d(oimg);



