function firdemo(action,s);
%FIRDEMO Demonstrates 2-D FIR filtering in the Image Processing Toolbox.

%	Copyright (c) 1993 by The MathWorks, Inc.
%	$Revision: 1.5 $  $Date: 1993/10/21 12:59:32 $

% Possible actions:
% initialize
% window
% lowpass
% operation
% cutoff
% order

% button callbacks:
% radio
% apply
% info
% close


if nargin<1,
    action='initialize';
end;

if strcmp(action,'initialize'),
    figNumber=figure( ...
        'Name','2-D FIR Filtering Demo', ...
        'NumberTitle','off');

    %==================================
    % Set up the image axes
    axes( ...
        'Units','normalized', ...
        'Position',[0.10 0.35 0.60 0.6], ...
        'XTick',[],'YTick',[], ...
        'Box','on');
    set(figNumber,'defaultaxesposition',[0.10 0.1 0.60 0.80])
    imageHndl = subplot(2,1,1);
    set(gca, ...
        'Units','normalized', ...
        'XTick',[],'YTick',[], ...
        'Box','on');
    filterHndl = subplot(2,2,3);
    set(gca, ...
        'Units','normalized', ...
        'XTick',[],'YTick',[], ...
        'Box','on');
    responseHndl = subplot(2,2,4);
    set(gca, ...
        'Units','normalized', ...
        'XTick',[],'YTick',[], ...
        'Box','on');

    %====================================
    % Information for all buttons (and menus)
    labelColor=[0.8 0.8 0.8];
    yInitPos=0.90;
    menutop=0.95;
    btnTop = 0.6;
    top=0.75;
    left=0.785;
    btnWid=0.175;
    btnHt=0.06;
    textHeight = 0.05;
    textWidth = 0.07;
    % Spacing between the button and the next command's label
    spacing=0.019;
    
    %====================================
    % The CONSOLE frame
    frmBorder=0.019; frmBottom=0.04; 
    frmHeight = 0.92; frmWidth = btnWid;
    yPos=frmBottom-frmBorder;
    frmPos=[left-frmBorder yPos frmWidth+2*frmBorder frmHeight+2*frmBorder];
    h=uicontrol( ...
        'Style','frame', ...
        'Units','normalized', ...
        'Position',frmPos, ...
	'BackgroundColor',[0.45 0.45 0.45]);

    %====================================
    % The RESTORE IMAGE button
    btnNumber=1;
    yPos=menutop-(btnNumber-1)*(btnHt+spacing);
    labelStr='Restore image';
    callbackStr='firdemo(''restore'')';
    
    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    restoreHndl=uicontrol( ...
        'Style','pushbutton', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'Enable','on', ...
        'String',labelStr, ...
        'Callback',callbackStr);

    %====================================
    % The LOWPASS Menu
    menuNumber=2;
    yPos=menutop-(menuNumber-1)*(btnHt+spacing);
    labelStr='lowpass|highpass';
    callbackStr='firdemo(''design'');';
    
    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    lowHndl=uicontrol( ...
        'Style','popupmenu', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'String',labelStr, ...
        'Interruptible','yes', ...
        'Callback',callbackStr);

    %====================================
    % The Window Menu
    menuNumber=3;
    yPos=menutop-(menuNumber-1)*(btnHt+spacing);
    labelStr=str2mat('Bartlett','Hamming','Hanning','Blackman');
    callbackStr='firdemo(''design'')';

    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    windHndl=uicontrol( ...
        'Style','popupmenu', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'String',labelStr, ...
        'Interruptible','yes', ...
        'Callback',callbackStr);

    %===================================
    % Cutoff label and text field
    top = yPos - btnHt - spacing;
    labelWidth = frmWidth-textWidth-.01;
    labelBottom=top-textHeight;
	labelLeft = left;
    labelPos = [labelLeft labelBottom labelWidth textHeight];
    h = uicontrol( ...
		'Style','text', ...
        'Units','normalized', ...
		'Position',labelPos, ...
        'Horiz','left', ...
        'String','Cutoff', ...
        'Interruptible','no', ...
		'BackgroundColor',[0.45 0.45 0.45], ...
        'ForegroundColor','white');
	% Text field
    textPos = [labelLeft+labelWidth labelBottom textWidth textHeight];
    callbackStr = 'firdemo(''cutoff'')';
    cutoffHndl = uicontrol( ...
		'Style','edit', ...
        'Units','normalized', ...
		'Position',textPos, ...
		'Horiz','right', ...
		'Background','white', ...
        'Foreground','black', ...
		'String','0.5','Userdata',0.5, ...
        'callback',callbackStr);

    %===================================
    % Filter order label and text field
    labelBottom=top-2*textHeight-spacing;
	labelLeft = left;
    labelPos = [labelLeft labelBottom labelWidth textHeight];
    h = uicontrol( ...
		'Style','text', ...
        'Units','normalized', ...
		'Position',labelPos, ...
        'String','Order', ...
        'Horiz','left', ...
        'Interruptible','no', ...
		'Background',[0.45 0.45 0.45], ...
        'Foreground','white');
	% Text field
    textPos = [labelLeft+labelWidth labelBottom textWidth textHeight];
    callbackStr = 'firdemo(''order'')';
    orderHndl = uicontrol( ...
		'Style','edit', ...
        'Units','normalized', ...
		'Position',textPos, ...
		'Horiz','center', ...
		'Background','white', ...
        'Foreground','black', ...
		'String','11','Userdata',11, ...
        'Callback',callbackStr);

    %====================================
    % fsamp2 radio button
    btnTop = labelBottom-spacing;
    btnNumber=1;
    yPos=btnTop-(btnNumber-1)*(btnHt+spacing);
    labelStr='fsamp2';
    callbackStr='firdemo(''radio'',1);';

    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    btn1Hndl=uicontrol( ...
        'Style','radiobutton', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'String',labelStr, ...
        'value',1,'Userdata',1, ...
        'Callback',callbackStr);

    %====================================
    % fwind1 radio button
    btnTop = labelBottom-spacing;
    btnNumber=2;
    yPos=btnTop-(btnNumber-1)*(btnHt+spacing);
    labelStr='fwind1';
    callbackStr='firdemo(''radio'',2);';

    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    btn2Hndl=uicontrol( ...
        'Style','radiobutton', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'String',labelStr, ...
        'value',0, ...
        'Callback',callbackStr);

    %====================================
    % fwind2 radio button
    btnNumber=3;
    yPos=btnTop-(btnNumber-1)*(btnHt+spacing);
    labelStr='fwind2';
    callbackStr='firdemo(''radio'',3);';
    
    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    btn3Hndl=uicontrol( ...
        'Style','radiobutton', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'String',labelStr, ...
        'Callback',callbackStr);

    %====================================
    % ftrans2 radio button
    btnNumber=4;
    yPos=btnTop-(btnNumber-1)*(btnHt+spacing);
    labelStr='ftrans2';
    % Setting userdata to -1 (=stop) will stop the demo.
    callbackStr='firdemo(''radio'',4);';
    
    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    btn4Hndl=uicontrol( ...
        'Style','radiobutton', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'String',labelStr, ...
        'Callback',callbackStr);

    %====================================
    % The APPLY FILTER button
    btnNumber=5;
    yPos=btnTop-(btnNumber-1)*(btnHt+spacing);
    labelStr='Apply filter';
    callbackStr='firdemo(''apply'')';
    
    % Generic button information
    btnPos=[left yPos-btnHt btnWid btnHt];
    applyHndl=uicontrol( ...
        'Style','pushbutton', ...
        'Units','normalized', ...
        'Position',btnPos, ...
        'Enable','on', ...
        'String',labelStr, ...
        'Callback',callbackStr);

    %====================================
    % The INFO button
    labelStr='info';
    callbackStr='firdemo(''info'')';
    helpHndl=uicontrol( ...
        'Style','pushbutton', ...
        'Units','normalized', ...
        'Position',[left frmBottom+btnHt+spacing btnWid btnHt], ...
        'String',labelStr, ...
        'Callback',callbackStr);

    %====================================
    % The CLOSE button
    labelStr='Close';
    callbackStr='close(gcf)';
    closeHndl=uicontrol( ...
        'Style','pushbutton', ...
        'Units','normalized', ...
        'Position',[left frmBottom btnWid btnHt], ...
        'String',labelStr, ...
        'Callback',callbackStr);

    hndlList=[imageHndl filterHndl responseHndl lowHndl ...
              cutoffHndl orderHndl windHndl btn1Hndl btn2Hndl btn3Hndl ...
              btn4Hndl applyHndl helpHndl closeHndl];
    set(figNumber, ...
	'Visible','on', ...
	'UserData',hndlList);

    set(gcf,'Pointer','watch');
    drawnow
    load trees
    I = imresize(ind2gray(X,map),.5,'nearest');
    axes(imageHndl)
    imshow(I,64),title('Original image')
    set(imageHndl,'Userdata',I)
    firdemo('design')
    set(gcf,'Pointer','arrow');
    return

elseif strcmp(action,'cutoff'),
    v = get(gco,'Userdata');
    s = get(gco,'String');
    vv = eval(s,num2str(v));
    if vv>1 | vv<0, vv = v; end
    vv = round(vv*100)/100;
    set(gco,'Userdata',vv,'String',num2str(vv))
    firdemo('design')
    return

elseif strcmp(action,'order'),
    v = get(gco,'Userdata');
    s = get(gco,'String');
    vv = eval(s,num2str(v));
    if vv<5, vv = v; end
    vv = round((vv-1)/2)*2+1;
    set(gco,'Userdata',vv,'String',num2str(vv))
    firdemo('design')
    return

elseif strcmp(action,'radio'),
    axHndl=gca;
    hndlList=get(gcf,'Userdata');
    for i=8:11,
      set(hndlList(i),'value',0) % Disable all the buttons
    end
    set(hndlList(s+7),'value',1) % Enable selected button
    set(hndlList(8),'Userdata',s) % Remember selected button
    firdemo('design')
    return

elseif strcmp(action,'design'), % Design filter
    set(gcf,'Pointer','watch');
    axHndl=gca;
    hndlList=get(gcf,'Userdata');
    imageHndl = hndlList(1);
    filterHndl = hndlList(2);
    responseHndl = hndlList(3);
    lowHndl = hndlList(4);
    cutoffHndl = hndlList(5);
    orderHndl = hndlList(6);
    windHndl = hndlList(7);
    btn1Hndl = hndlList(8);
    btn2Hndl = hndlList(9);
    btn3Hndl = hndlList(10);
    btn4Hndl = hndlList(11);

    edgecolor = get(gca,'colororder'); edgecolor = edgecolor(1,:);
    
    order = get(orderHndl,'UserData'); % Filter order
    cutoff = get(cutoffHndl,'UserData'); % Filter cutoff frequency

    % Create desired frequency response
    [f1,f2] = freqspace(order,'meshgrid');
    d = find(f1.^2+f2.^2 < cutoff^2);
    Hd = zeros(order);
    Hd(d) = ones(size(d));
    if get(lowHndl,'value')==2, Hd = 1-Hd; end % If highpass
%    axes(desiredHndl), hndl=mesh(f1,f2,Hd); set(hndl,'edge',edgecolor)
%    title('Desired frequency response')

    method = get(btn1Hndl,'Userdata');

    % Get window if necessary
    if method==2 | method==3, % Get window
      wind = get(windHndl,'value');
      windows = get(windHndl,'string');
      w = eval([lower(deblank(windows(wind,:))) '(' num2str(order) ')']);
    end
      
    % Design filter
    if method==1,
      h = fsamp2(Hd);
    elseif method==2,
      h = fwind1(Hd,w);
    elseif method==3,
      h = fwind2(Hd,w*w');
    elseif method==4,
      F = [0 cutoff-0.05 cutoff+0.05 1];
      M = [1 1 0 0];
      if get(lowHndl,'value')==2, M = 1-M; end
      h = ftrans2(remez(order-1,F,M));
    end
    axes(filterHndl), hndl = mesh(h); set(hndl,'edge',edgecolor)
    set(filterHndl,'xlim',[1 order],'ylim',[1 order])
    title('Filter coefficients')

    % Compute frequency response
    axes(responseHndl), freqz2(h,32,32)
    set(get(gca,'ch'),'edge',edgecolor), title('Frequency response')
    set(responseHndl,'zlim',[0 1.2])
    axes(imageHndl)
    set(gcf,'Pointer','arrow');
    return

elseif strcmp(action,'apply')
    set(gcf,'Pointer','watch');
    axHndl=gca;
    hndlList=get(gcf,'Userdata');
    imageHndl = hndlList(1);
    filterHndl = hndlList(2);
    responseHndl = hndlList(3);
    I = get(imageHndl,'Userdata');
    J = getimage(imageHndl);
    if isempty(I),
      if isempty(J), 
        disp([7,'Figure must contain an image for demo.']), return
      end
      if isgray(J),
        I = J;
      elseif isind(I),
        I = ind2gray(J,colormap);
      else
        I = mat2gray(J);
      end
    end
    h = get(get(filterHndl,'ch'),'zdata');
    J = mat2gray(filter2(h,I));
    axes(imageHndl), imshow(J,64), title('Filtered original image')
    set(imageHndl,'Userdata',I)
    set(gcf,'Pointer','arrow');
    return

elseif strcmp(action,'restore'),
    set(gcf,'Pointer','watch');
    axHndl=gca;
    hndlList=get(gcf,'Userdata');
    imageHndl = hndlList(1);
    I = get(imageHndl,'Userdata');
    J = getimage(imageHndl);
    if isempty(I),
      if isempty(J), 
        disp([7,'Figure must contain an image for demo.']), return
      end
      if isgray(J),
        I = J;
      elseif isind(I),
        I = ind2gray(J,colormap);
      else
        I = mat2gray(J);
      end
    end
    axes(imageHndl), imshow(I,64), title('Original image')
    set(imageHndl,'Userdata',I)
    set(gcf,'Pointer','arrow');

elseif strcmp(action,'info'),
    set(gcf,'pointer','arrow')
	ttlStr = get(gcf,'Name');
	hlpStr1= [...
         ' This demo lets you explore 2-D FIR filters.  By '  
         ' changing the cuttoff frequency and filter order '  
         ' you can design your own filter.  The designed   '  
         ' filter''s coefficients and frequency response    '  
         ' are shown in the two axes at the bottom of the  '  
         ' figure.  The filter is designed using the method'
		 ' selected in one of the radio buttons.           '  
         '                                                 '  
         ' When the APPLY FILTER button is pressed the     '  
         ' filter is applied to the original image and the '  
         ' result is displayed.  To see the original image,'  
         ' press the RESTORE IMAGE button.                 '];
	hlpStr2 = [...
         '                                                 '  
         ' The top menu controls whether a high pass or    '  
         ' low pass filter is designed.  The next menu     '  
         ' lets you choose among various window            '  
         ' functions.  The window functons are used only   '
		 ' if FWIND1 or FWIND2 is chosen as the design     '
		 ' method.                                         '
         '                                                 '
		 ' You can change the cutoff frequency or filter   '
		 ' order by editing the numbers displayed. Only    '
		 ' odd sized orders and cutoff frequencies         '
		 ' between 0.0 and 1.0 are valid for this demo.    '
         '                                                 '  
         ' You can install your own image as the original  '
         ' image using IMSHOW from the command line.       '
		 ' Color images will be converted to gray          '
		 ' automatically.                                  '
		 '                                                 '
         ' Filename: firdemo.m                             '];

    myFig = gcf;
    helpfun(ttlStr,hlpStr1,hlpStr2);

    % Protect against gcf changing -- Change close button behind
    % helpfun's back
    ch = get(gcf,'ch');
    for i=1:length(ch),
      if strcmp(get(ch(i),'type'),'uicontrol'),
        if strcmp(lower(get(ch(i),'String')),'close'),
          callbackStr = [get(ch(i),'callback') ...
            '; firdemo(''closehelp'',' num2str(myFig) ')'];
          set(ch(i),'callback',callbackStr)
          return
        end
      end
    end
    return

elseif strcmp(action,'closehelp'),
    % Restore close button help behind helpfun's back
    ch = get(gcf,'ch');
    for i=1:length(ch),
      if strcmp(get(ch(i),'type'),'uicontrol'),
        if strcmp(lower(get(ch(i),'String')),'close'),
          callbackStr = get(ch(i),'callback');
          k = findstr('; firdemo(',callbackStr);
          callbackStr = callbackStr(1:k-1);
          set(ch(i),'callback',callbackStr)
          break;
        end
      end
    end
    ch = get(0,'ch');
    if ~isempty(find(ch==s)), figure(s), end % Make sure figure exists

end    % if strcmp(action, ...lose all
