% Usage: [x2,P] = jpegdemo(x,r)
% Simple JPEG compression demo.  Input argument x is an M by N 
% array of numbers, either uint8 or double (converted to double
% below). Argument "r" is for scaling the quantization matrix as 
% in book.  Uses quantization matrix from book. Output is M by N 
% array "x2", simulated compressed/decompressed image as an array 
% of doubles, and also "P", fraction of non-zero block DCT 
% coefficients (as a crude measure of compression).  Calls the routine
% blkidct2().

% If you don't have the signal processing toolbox substitute kdct() 
% for dct().

function [x2,P] = jpegdemo(x,r)

T = r*[16 11 10 16 24 40 51 61; 12 12 14 19 26 58 60 55; 
    14 13 16 24 40 57 69 56; 14 17 22 29 51 87 80 62;
    18 22 37 56 68 109 103 77; 24 35 55 64 81 194 113 92;
    49 64 78 87 103 121 120 101; 72 92 95 98 121 100 103 99];

 m=8; n=8; %Really, the blocksize m,n can be anything.
 
 % Extend image x so dimensions divisible by m, n.
 [M0,N0] = size(x); M=M0; N=N0;
 blocksM = ceil(M/m); blocksN = ceil(N/n);
 M = m*blocksM; N = n*blocksN;
 for k=(M0+1):M %Extend each column
     x(k,:) = x(M0,:);
 end
 for k=(N0+1):N %Extend each row
     x(:,k) = x(:,N0);
 end
 
 Y = zeros(M,N); %Storage for block DCT
 
 %Arrays for 8x8 DCT; straight matrix multiply is faster than dct2.
 C1 = dct(eye(m));
 C2 = dct(eye(n))';
 
 %Block DCT code, quantization
 for i=1:blocksM
     for j=1:blocksN
         
         %Pick off each 8 x 8 block, put in "Z"
         e = (i-1)*m+1;
         f = (j-1)*n+1;
         Z = double(x(e:(e+m-1),(f:f+n-1)));
         
         %Compute DCT of block
         Q = C1*Z*C2;
         
         %Quantize (quant. matrix already scaled), install in Y.
         Q2 = T.*round(Q./T);
         Y(e:(e+m-1),(f:f+n-1)) = Q2;
         
         end;
     end;
     
 P = sum(sum(sign(abs(Y))))/M/N;
 
 %Inverse block DCT
 Y = double(blkidct2(Y,m,n));
 
 %Pick off original image dimensions, return as a double
 x2 = Y(1:M0,1:N0);

                   
