% Usage: [x2,P] = jpegprogressive(x,r,p)
% Simple JPEG compression/progressive transmission demo. Input
% argument x is an M by N array of numbers (can be uint8 or double,
% it's converted to a double below) assumed to encode grayscale image
% on 0 to 255 range. Argument "r" is for scaling the quantization
% matrix as in book. Uses quantization matrix from book.
% Argument "p" is a sort of frequency limit that uses ONLY DCT 2D
% frequencies which satisfy k + l <= p to reconstruct. Choose
% 0<=p<=14. With p=14 this is equivalent to "jpegdemo". With p=0
% we have reconstruction from DC coefficients only.
% 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).
function [x2,P] = jpegprogressive(x,r,p)
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 dct.
C1 = dct(eye(m));
C2 = dct(eye(n))';
%Construct mask B for zeroing out all but desired DCT coefficients, to
%simulate progressive transmission
B = ones(m,n);
for i=1:m
q=max(p+3-i,1);
B(i,q:n) = 0.0;
end;
%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);
Q2 = Q2.*B; %Use only coefficients that satisfy resolution limits.
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
x2 = double(Y(1:M0,1:N0));