function dctdemo(action,s);
%DCTDEMO Demonstrates 2-D DCT Image Compression.

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

% Possible actions:
% initialize

% button callbacks:
% apply
% help

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

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

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

    %====================================
    % The Apply button
    labelStr='Apply';
    callbackStr='dctdemo(''apply'')';
    yPos=frmBottom+frmHeight-btnHt-spacing;
    helpHndl=uicontrol( ...
        'Style','pushbutton', ...
        'Units','normalized', ...
        'Position',[left yPos btnWid btnHt], ...
        'String',labelStr, ...
        'Callback',callbackStr);

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

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

    %===================================
    % Set up scroll bar
    barHeight = 0.04; barWidth = btnWid+2*frmBorder;
    sbBottom=top-barWidth-2*barHeight;
	sbLeft = left-frmBorder;
    textWidth = barWidth/2;
    scrollPos = [sbLeft sbBottom barWidth barHeight];
    callbackStr = 'dctdemo(''slide'')';
    hSlider = uicontrol( ...
		'Style','slider', ...
        'Units','normalized', ...
		'Position',scrollPos, ...
		'Value',64, ...
		'min',1, ...
		'max',64, ...
        'Interruptible','no', ...
        'Callback',callbackStr);
    % Left and right range indicators
    c = get(gcf,'Color');
    if [.298936021 .58704307445 .114020904255]*c'<.5,
      fgColor = [1 1 1];
    else
      fgColor = [0 0 0];
    end
    rangePos = [sbLeft sbBottom-barHeight textWidth barHeight];
    uicontrol( ...
		'Style','text', ...
        'Units','normalized', ...
		'Position',rangePos, ...
		'Horiz','left', ...
		'Background',c, ...
        'Foreground',fgColor, ...
		'String','1');
    rangePos = [sbLeft+barWidth/2 sbBottom-barHeight textWidth barHeight];
    uicontrol( ...
		'Style','text', ...
        'Units','normalized', ...
		'Position',rangePos, ...
		'Horiz','right', ...
		'Background',c, ...
        'Foreground',fgColor, ...
		'String','64');

    %==================================
    % Set up the 8-by-8 array
    aPos = [sbLeft sbBottom+2*barHeight barWidth barWidth];
    h8x8 = axes( ...
        'Units','normalized', ...
        'Position',aPos, ...
        'XTick',[],'YTick',[], ...
        'ydir','reverse', ...
        'Box','on', ...
        'xlim',[1 9], ...
        'ylim',[1 9], ...
        'clim',[0 1], ...
        'aspect',[1 1]);
    title('DCT coefficients')
  
    %==================================
    % Set up the image axes
    axHeight = (top-(frmBottom-frmBorder)-3*spacing)/2;
    hNewImage = axes(...
        'Units','normalized', ...
        'Position',[0.1 frmBottom-frmBorder .6 axHeight], ...
        'XTick',[],'YTick',[], ...
        'Box','on');
    hTrueImage = axes(...
        'Units','normalized', ...
        'Position',[0.1 top-axHeight .6 axHeight], ...
        'XTick',[],'YTick',[], ...
        'Box','on');
    set(figNumber,'defaultaxesposition',[0.10 0.1 0.60 0.85])
    set(figNumber, ...
	'Visible','on');

    set(gcf,'Pointer','watch');
    drawnow
    load trees
    I = imresize(ind2gray(X,map),.5,'nearest');
    axes(hTrueImage), imshow(I,64), title('Original Image')
    axes(hTrueImage)
    axes(h8x8), hSurf=surface(ones(9),'face','flat','edge',[1 1 1]/2);
    axes(hTrueImage)
    set(gcf,'Pointer','arrow');
    hndlList = [hTrueImage hNewImage h8x8 hSlider hSurf];

    set(figNumber, ...
	'UserData',hndlList);
    dctdemo('apply')
    return
end

% Protect against possible deletion all the whole figure
danger = strcmp(get(gcf,'NextPlot'),'replace');

if strcmp(action,'apply'),
    set(gcf,'Pointer','watch');
    drawnow
    if danger, 
      set(gcf,'nextplot','add');
      h = get(gcf,'children');
      for i=1:length(h),
        if strcmp(get(h(i),'type'),'axes'), axes(h(i)), cla, end
      end
    end
    axHndl=gca;
    hndlList=get(gcf,'Userdata');
    hTrueImage=hndlList(1);
    hNewImage=hndlList(2);
    h8x8=hndlList(3);
    hSlider=hndlList(4);
    hSurf=hndlList(5);

    imageDCT = get(hTrueImage,'UserData');
    if isempty(imageDCT),  % Create imageDCT and DCTvar if necessary
      dctdemo('makedct')
      imageDCT = get(hTrueImage,'UserData');
    end
    
    % Determine 8x8 image
    mask = get(hSurf,'Cdata');

	% Get 8-by-8 DCT matrix
    dctm = dctmtx2(8);

    % Reconstruct and display image
%   newImage = blkproc(imageDCT,[8 8],'idct2(x.*P1)',mask(1:8,1:8));
    newImage = ...
      blkproc(imageDCT,[8 8],'P1*(x.*P2)*P3',dctm.',mask(1:8,1:8),dctm);
    axes(hNewImage), imshow(newImage,64), title('Reconstructed image')
    axes(hTrueImage)
    drawnow

    set(gcf,'Pointer','arrow');
    return

elseif strcmp(action,'slide'),
    if danger, 
      set(gcf,'nextplot','add');
      h = get(gcf,'children');
      for i=1:length(h),
        if strcmp(get(h(i),'type'),'axes'), axes(h(i)), cla, end
      end
    end
    axHndl=gca;
    hndlList=get(gcf,'Userdata');
    hTrueImage=hndlList(1);
    hNewImage=hndlList(2);
    h8x8=hndlList(3);
    hSlider=hndlList(4);
    hSurf=hndlList(5);

    if isempty(get(hTrueImage,'UserData')), 
      set(gcf,'Pointer','watch');
      dctdemo('makedct')
      set(gcf,'Pointer','arrow');
    end

    axHndl=gca;
    v = 64-floor(get(hSlider,'value'));
    var = get(hSlider,'UserData');
    DCTvar = var(1,:); order = var(2,:);

    % Determine 8x8 image and display
    mask = ones(8,8); mask(order(1:v)) = zeros(1,v);
    im8x8 = zeros(9,9); im8x8(1:8,1:8) = mask;
    set(hSurf,'Cdata',im8x8)
    return

elseif strcmp(action,'makedct')
    axHndl=gca;
    hndlList=get(gcf,'Userdata');
    hTrueImage=hndlList(1);
    hNewImage=hndlList(2);
    h8x8=hndlList(3);
    hSlider=hndlList(4);
    hSurf=hndlList(5);

    axes(hTrueImage)
	I = getimage(hTrueImage);
    if isempty(I), 
      disp([7,'Figure must contain an image for demo.']), return
    end
    if ~isgray(I),
      if isind(I),
        I = ind2gray(I,colormap);
      else
        I = mat2gray(I);
      end
      axes(hTrueImage), imshow(I,64)
    end
    title('Original Image')

	% Get 8-by-8 DCT matrix
    dctm = dctmtx2(8);

%    imageDCT = blkproc(I,[8 8],'dct2');
    imageDCT = blkproc(I,[8 8],'P1*x*P2',dctm,dctm.');
    DCTvar = im2col(imageDCT,[8 8],'distinct').';
    n = size(DCTvar,1);
    DCTvar = (sum(DCTvar.*DCTvar) - (sum(DCTvar)/n).^2)/n;
    [dum,order] = sort(DCTvar);
    set(hTrueImage,'UserData',imageDCT)
    set(hSlider,'UserData',[DCTvar;order])
    return


elseif strcmp(action,'info'),
    set(gcf,'pointer','arrow')
    ttlStr = get(gcf,'Name');
    hlpStr1 = ...
        ['                                               '  
         ' This demo lets you explore image compression  '  
         ' using the 2-D DCT.  The original image is     '
         ' transformed in 8-by-8 blocks and then inverse '
         ' transformed in 8-by-8 blocks to create the    '
         ' reconstructed image.  The inverse DCT is      '
         ' performed using the subset of DCT coefficients'
         ' that are shown in white.                      '
         '                                               '
         ' Use the slider to select a subset of the DCT  '
         ' coefficients and then press the APPLY button  '
         ' to produce the cooresponding reconstructed    '
         ' image.  The DCT coefficients with small       '
         ' variance are thrown away first.  As you will  '
         ' find out when playing with the demo, these    '
         ' small variance coefficients have little effect'
         ' on the reconstructed image.                   '];
    hlpStr2 = ...
        ['                                               '
         ' Try to find out how few coefficients are      '
         ' needed to create a reasonable approximation   '
         ' to the original!                              '
         '                                               '
         ' You can install your own image as the original'
         ' image using IMSHOW from the command line.     '
         ' The DCT coefficients and reconstructed image  '
         ' will update, and color images will be         '
         ' converted to gray when you press APPLY.       '
         '                                               '
         ' File name: dctdemo.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') ...
            '; dctdemo(''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('; dctdemo(',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, ...

set(gcf,'pointer','arrow')
