function varargout = droste_gui(varargin)
% Apply the Droste Effect to an image.
%
% The Droste Effect is when an image recursively includes itself. The basic
% method is to insert a scaled copy of the image, but more interesting
% results can be achieved via conformal mapping.
%
% by Steve Hoelzer
%
% 2009-05-13
% Last Modified by GUIDE v2.5 06-May-2009 15:37:38
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @droste_gui_OpeningFcn, ...
'gui_OutputFcn', @droste_gui_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
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 droste_gui is made visible.
function droste_gui_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to droste_gui (see VARARGIN)
% Choose default command line output for droste_gui
handles.output = hObject;
% put GUI in center of screen
s = get(0,'ScreenSize');
p = get(handles.figure1,'Position');
p = [round((s(3)-p(3))/2), round((s(4)-p(4))/2), p(3), p(4)];
set(handles.figure1,'Position',p);
% init paths
handles.lastloadpath = [];
handles.lastsavepath = [];
% tell user how to start
set(handles.notifytext,'String',sprintf('Choose\nsource\nimage'),'Visible','On')
% Update handles structure
guidata(hObject, handles)
% --- Outputs from this function are returned to the command line.
function varargout = droste_gui_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in load.
function load_Callback(hObject, eventdata, handles)
% hObject handle to load (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% choose image
[filename,pathname] = uigetfile('*','Choose an image file...',handles.lastloadpath);
if filename == 0
return
end
% read image
img = imread([pathname filename]);
% convert from 8-bit to truecolor
img = double(img) / 255;
% show new image in the GUI
set(handles.figure1,'CurrentAxes',handles.axes1)
imshow(img,'InitialMagnification','fit')
% store image data
handles.img = img;
% % set image data and droste region
% handles.img = img;
% handles.reg = [size(img,2)/4, size(img,1)/4, size(img,2)/2, size(img,1)/2];
% Update handles structure
handles.lastloadpath = pathname;
guidata(hObject, handles)
% go to edit region mode
set(handles.editregion,'Enable','On')
editregion_Callback(handles.editregion, eventdata, handles)
% --- Executes on button press in mouseselect.
function mouseselect_Callback(hObject, eventdata, handles)
% hObject handle to mouseselect (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% get state of notify text
state = get(handles.notifytext);
% let the user know that something is happening
set(handles.notifytext,'String',sprintf('Click\nand\ndrag...'),'Visible','On')
drawnow
try
waitforbuttonpress;
point1 = get(handles.axes1,'CurrentPoint'); % coords of button down
point1 = point1(1,1:2); % extract x and y
rbbox; % return figure units
point2 = get(handles.axes1,'CurrentPoint'); % coords of button up
point2 = point2(1,1:2); % extract x and y
handles.reg = round([min([point1;point2]), abs(point1-point2)]);
setregion(handles)
end
% reset notify text
set(handles.notifytext,'String',state.String,'Visible',state.Visible)
% --- Executes on slider movement.
function zoom_Callback(hObject, eventdata, handles)
% hObject handle to zoom (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.zoom,0.1,4,0.01)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function zoom_CreateFcn(hObject, eventdata, handles)
% hObject handle to zoom (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on slider movement.
function hshift_Callback(hObject, eventdata, handles)
% hObject handle to hshift (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.hshift,-1,1,0.01)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function hshift_CreateFcn(hObject, eventdata, handles)
% hObject handle to hshift (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on slider movement.
function vshift_Callback(hObject, eventdata, handles)
% hObject handle to vshift (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.vshift,-1,1,0.01)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function vshift_CreateFcn(hObject, eventdata, handles)
% hObject handle to vshift (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on slider movement.
function rotate_Callback(hObject, eventdata, handles)
% hObject handle to rotate (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.rotate,-180,180,1)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function rotate_CreateFcn(hObject, eventdata, handles)
% hObject handle to rotate (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on slider movement.
function nspirals_Callback(hObject, eventdata, handles)
% hObject handle to nspirals (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.nspirals,-5,5,1)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function nspirals_CreateFcn(hObject, eventdata, handles)
% hObject handle to nspirals (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on slider movement.
function ncopies_Callback(hObject, eventdata, handles)
% hObject handle to ncopies (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.ncopies,1,6,1)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function ncopies_CreateFcn(hObject, eventdata, handles)
% hObject handle to ncopies (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on slider movement.
function maxrecur_Callback(hObject, eventdata, handles)
% hObject handle to maxrecur (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.maxrecur,0,20,1)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function maxrecur_CreateFcn(hObject, eventdata, handles)
% hObject handle to maxrecur (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on slider movement.
function aafactor_Callback(hObject, eventdata, handles)
% hObject handle to aafactor (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
update_slider(handles.aafactor,0,8,0.1)
update_preview(handles)
% --- Executes during object creation, after setting all properties.
function aafactor_CreateFcn(hObject, eventdata, handles)
% hObject handle to aafactor (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
% --- Executes on button press in save.
function save_Callback(hObject, eventdata, handles)
% hObject handle to save (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% choose where to save file
[filename,pathname] = uiputfile('*.png','Save image...',[handles.lastsavepath 'droste']);
if filename == 0
return
end
% let the user know that something is happening
set(handles.notifytext,'String','Saving...','Visible','On')
drawnow
% compute droste image
if get(handles.widthsource,'Value')
w = [];
else
w = str2double(get(handles.widthpx,'String'));
end
img = do_droste(handles,w);
% write image file
imwrite(img,[pathname filename],'png')
% Update handles structure
handles.lastsavepath = pathname;
guidata(hObject, handles)
set(handles.notifytext,'Visible','Off')
% --- Executes on button press in widthsource.
function widthsource_Callback(hObject, eventdata, handles)
% hObject handle to widthsource (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of widthsource
set(handles.widthcustom,'Value',~get(hObject,'Value'))
% --- Executes on button press in widthcustom.
function widthcustom_Callback(hObject, eventdata, handles)
% hObject handle to widthcustom (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of widthcustom
set(handles.widthsource,'Value',~get(hObject,'Value'))
function widthpx_Callback(hObject, eventdata, handles)
% hObject handle to widthpx (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of widthpx as text
% str2double(get(hObject,'String')) returns contents of widthpx as a double
v = str2double(get(hObject,'String'));
v = round(v);
v = max(v,1);
set(hObject,'String',sprintf('%i',v))
set(handles.widthsource,'Value',0)
set(handles.widthcustom,'Value',1)
% --- Executes during object creation, after setting all properties.
function widthpx_CreateFcn(hObject, eventdata, handles)
% hObject handle to widthpx (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% --- Executes on button press in reset.
function reset_Callback(hObject, eventdata, handles)
% hObject handle to reset (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
set(handles.zoom,'Value',1)
set(handles.hshift,'Value',0)
set(handles.vshift,'Value',0)
set(handles.rotate,'Value',0)
set(handles.nspirals,'Value',1)
set(handles.ncopies,'Value',1)
set(handles.maxrecur,'Value',10)
set(handles.aafactor,'Value',1)
update_preview(handles)
% Update the image with new droste effect params
function update_slider(h,vmin,vmax,vstep)
v = get(h,'Value');
v = min(v,vmax);
v = max(v,vmin);
v = round(v/vstep) * vstep;
set(h,'Value',v);
% Update the image with new droste effect params
function update_preview(handles)
% make sure image and region are defined
if ~isfield(handles,'img') || isempty(handles.img) ...
|| ~isfield(handles,'reg') || isempty(handles.reg)
return
end
% let the user know that something is happening
set(handles.notifytext,'String','Updating...','Visible','On')
drawnow
% % show current value of params
% fprintf('\n')
% fprintf(' zoom = %1.2f\n',get(handles.zoom,'Value'))
% fprintf(' hshift = %1.2f\n',get(handles.hshift,'Value'))
% fprintf(' vshift = %1.2f\n',get(handles.vshift,'Value'))
% fprintf(' rotate = %1.2f\n',get(handles.rotate,'Value'))
% fprintf('nspirals = %1.2f\n',get(handles.nspirals,'Value'))
% fprintf(' ncopies = %1.2f\n',get(handles.ncopies,'Value'))
% fprintf('maxrecur = %1.2f\n',get(handles.maxrecur,'Value'))
% fprintf('aafactor = %1.2f\n',get(handles.aafactor,'Value'))
% compute droste effect
p = get(handles.axes1,'Position');
img = do_droste(handles,p(3));
% show image in the GUI
set(handles.notifytext,'Visible','Off')
set(handles.figure1,'CurrentAxes',handles.axes1)
imshow(img,'InitialMagnification','fit')
% Compute droste effect for the specified width
function img = do_droste(handles, w)
if isempty(w)
img = droste_effect(handles.img, handles.reg, ...
'zoom', get(handles.zoom,'Value'), ...
'hshift', get(handles.hshift,'Value'), ...
'vshift', get(handles.vshift,'Value'), ...
'rotate', get(handles.rotate,'Value'), ...
'nspiral', get(handles.nspirals,'Value'), ...
'ncopies', get(handles.ncopies,'Value'), ...
'maxrecur', get(handles.maxrecur,'Value'), ...
'aafactor', get(handles.aafactor,'Value'));
else
img = droste_effect(handles.img, handles.reg, ...
'zoom', get(handles.zoom,'Value'), ...
'hshift', get(handles.hshift,'Value'), ...
'vshift', get(handles.vshift,'Value'), ...
'rotate', get(handles.rotate,'Value'), ...
'nspiral', get(handles.nspirals,'Value'), ...
'ncopies', get(handles.ncopies,'Value'), ...
'maxrecur', get(handles.maxrecur,'Value'), ...
'width', w, ...
'aafactor', get(handles.aafactor,'Value'));
end
% --- Executes on button press in demo.
function demo_Callback(hObject, eventdata, handles)
% hObject handle to demo (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% construct a demo image
img = zeros(600);
img(181:421,181:421) = 1;
img(201:400,201:400) = 0;
for i = 39:40:size(img,1)-2
img(i:i+2,:) = 1;
img(:,i:i+2) = 1;
end
% set image data and droste region
handles.img = img;
handles.reg = [201 201 200 200];
% show demo image in the GUI
set(handles.figure1,'CurrentAxes',handles.axes1)
imshow(img,'InitialMagnification','fit')
% Update handles structure
guidata(hObject, handles)
setregion(handles)
% go to edit region mode
set(handles.editregion,'Enable','On')
editregion_Callback(handles.editregion, eventdata, handles)
% --- Executes on mouse press over axes background.
function axes1_ButtonDownFcn(hObject, eventdata, handles)
% hObject handle to axes1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
function regleft_Callback(hObject, eventdata, handles)
% hObject handle to regleft (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of regleft as text
% str2double(get(hObject,'String')) returns contents of regleft as a double
handles.reg(1) = str2double(get(hObject,'String'));
setregion(handles)
% --- Executes during object creation, after setting all properties.
function regleft_CreateFcn(hObject, eventdata, handles)
% hObject handle to regleft (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
function regtop_Callback(hObject, eventdata, handles)
% hObject handle to regtop (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of regtop as text
% str2double(get(hObject,'String')) returns contents of regtop as a double
handles.reg(2) = str2double(get(hObject,'String'));
setregion(handles)
% --- Executes during object creation, after setting all properties.
function regtop_CreateFcn(hObject, eventdata, handles)
% hObject handle to regtop (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
function regwidth_Callback(hObject, eventdata, handles)
% hObject handle to regwidth (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of regwidth as text
% str2double(get(hObject,'String')) returns contents of regwidth as a double
handles.reg(3) = str2double(get(hObject,'String'));
setregion(handles)
% --- Executes during object creation, after setting all properties.
function regwidth_CreateFcn(hObject, eventdata, handles)
% hObject handle to regwidth (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
function regheight_Callback(hObject, eventdata, handles)
% hObject handle to regheight (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of regheight as text
% str2double(get(hObject,'String')) returns contents of regheight as a double
handles.reg(4) = str2double(get(hObject,'String'));
setregion(handles)
% --- Executes during object creation, after setting all properties.
function regheight_CreateFcn(hObject, eventdata, handles)
% hObject handle to regheight (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% --- Executes on button press in editregion.
function editregion_Callback(hObject, eventdata, handles)
% hObject handle to editregion (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
hg = [handles.zoom, ...
handles.hshift, ...
handles.vshift, ...
handles.rotate, ...
handles.nspirals, ...
handles.ncopies, ...
handles.maxrecur, ...
handles.aafactor, ...
handles.reset, ...
handles.widthcustom, ...
handles.widthsource, ...
handles.widthpx, ...
handles.save];
hr = [handles.mouseselect, ...
handles.regleft, ...
handles.regtop, ...
handles.regwidth, ...
handles.regheight];
% flip between edit and set region modes
mode = get(handles.editregion,'UserData');
switch mode
case 0
% change state to edit region
set(handles.editregion,'String','Set')
set(handles.editregion,'UserData',1)
set(hg,'Enable','Off')
drawnow
set(handles.figure1,'CurrentAxes',handles.axes1)
imshow(handles.img,'InitialMagnification','fit')
set(handles.notifytext,'String','Set region','Visible','On')
set(hr,'Enable','On')
case 1
% change state to set region
set(handles.editregion,'String','Edit')
set(handles.editregion,'UserData',0)
set(hg,'Enable','On')
set(hr,'Enable','Off')
set(handles.notifytext,'Visible','Off')
update_preview(handles)
end
% --- Executes on button press in editregion.
function setregion(handles)
reg = handles.reg;
reg = round(reg);
reg = max(reg,1);
reg(1) = min(reg(1),size(handles.img,2));
reg(2) = min(reg(2),size(handles.img,1));
reg(3) = min(reg(3),size(handles.img,2)-reg(1));
reg(4) = min(reg(4),size(handles.img,1)-reg(2));
set(handles.regleft,'String',sprintf('%i',reg(1)))
set(handles.regtop,'String',sprintf('%i',reg(2)))
set(handles.regwidth,'String',sprintf('%i',reg(3)))
set(handles.regheight,'String',sprintf('%i',reg(4)))
handles.reg = reg;
% Update handles structure
guidata(handles.figure1, handles)