Matlab Codes:
function JPEG_Compressor (filename,quant_multiple)
% JPEG image compression program for graylevel image only
% This program compresses a graylevel image using the JPEG algorithm
% Parameter:
% -- filename, e.g. filename = 'D:\tigerGraylevel.jpg';
% -- quant_multiple, i.e.,set the multiplier to change size of quant. levels,and vary quant_mult from 0.1 to 3 (see jpeg.results file)
%%
%{ [X, map] = imread(...) reads the indexedimage in filename into X andits associated colormap into map.
% Colormap valuesin the image file are automatically rescaled into the range [0,1]. }
orig_img = imread(filename); % image matrix was stored in variable X
% image colormap is stored in variable map
orig_img = double(orig_img); %Convert image to double precision which is needed for the following calculations
blocksize = 8; % set the size of chunks to take the DCT of ( =< 8)
DCT_quantizer = ... % levels for quantizing the DCT block (8x8 matrix)
[ 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 104 113 92; ...
49 64 78 87 103 121 120 101; ...
72 92 95 98 112 100 103 99 ];
[rows, cols] = size(orig_img); % finds image's rows and columns
colors = max(max(orig_img)); % find the maximum intensity value in the original image
% Introduction
str = char( ...
'CpE 645 Image Processin Final Project Changjiang Cai', ...
'This program implements the JPEG data compression algorithm.');
ssdisp(0, str);
%{
fprintf(fileID,formatSpec,A1,...,An) appliesthe formatSpec to all elements of arrays A1,...An,
in column order, and writes the data to a text file. fprintf uses the encoding scheme
specified in the call to fopen
%}
fprintf (1, 'Image used: %s\n', filename);
fprintf (1, 'Its size is: %dx%d\n', rows, cols);
fprintf (1, 'Number of colors (guess): %d\n', colors);
fprintf (1, 'DCT block size: %dx%d\n', blocksize, blocksize);
fprintf (1, 'Quant. size multiplier: %d\n', quant_multiple);
% Display the original image
figure
ax(1) = subplot(1,2,1);
image(orig_img)
title('Original image')
% Prepare image for transform
% Level-shift the image (center intensity values around 0)
% {B = ceil(A) rounds the elements of A to the nearest integers greater thanor equal to A.
% For complex A,the imaginary and real parts are rounded independently.}
orig_img = orig_img - ceil(colors/2);
% Replicate edges of image to make its dimensions a multiple of blocksize
% {B = floor(A) rounds the elements of A to the nearest integers less thanor equal to A.
% For complex A,the imaginary and real parts are rounded independently.}
% the number of coloums to be padded
pad_cols = (1 - (cols/blocksize - floor(cols/blocksize))) * blocksize;
% the above formula may produce this result: when cols = 8, blocksize = 8,then pad_cols = 8
% thus, if this case happens, we have to make pad_cols be 0, compulsively.
if pad_cols == blocksize, pad_cols = 0; end
% the number of rows to be padded
pad_rows = (1 - (rows/blocksize - floor(rows/blocksize))) * blocksize;
if pad_rows == blocksize, pad_rows = 0; end
% duplicate the last column for padding new columns
for extra_cols = 1:pad_cols
orig_img(1:rows, cols+extra_cols) = orig_img(1:rows, cols);
end
cols = cols + pad_cols; % orig_img is now pad_cols wider
% duplicate the last row for padding new rows
for extra_rows = 1:pad_rows
orig_img(rows+extra_rows, 1:cols) = orig_img(rows, 1:cols);
end
rows = rows + pad_rows; % orig_img is now pad_rows taller
% the 1-D DCT transform matrix
DCT_trans = dctmtx(blocksize);
% Take DCT of blocks of size blocksize
fprintf(1, '\nFinding the DCT and quantizing...\n');
starttime = cputime; % "cputime" is an internal cpu time counter
jpeg_img = orig_img - orig_img; % zero the matrix for the compressed image
for row = 1: blocksize: rows-blocksize+1
for col = 1: blocksize: cols-blocksize+1
% take a block of the image:
DCT_matrix = orig_img(row: row + blocksize-1, col: col + blocksize-1);
% perform the transform operation on the 2-D block
DCT_matrix = DCT_trans*DCT_matrix*DCT_trans';
% quantize it (levels stored in DCT_quantizer matrix):
DCT_matrix = floor (DCT_matrix ...
./ (DCT_quantizer(1:blocksize, 1:blocksize) * quant_multiple) + 0.5);
% place it into the compressed-image matrix:
jpeg_img(row: row + blocksize-1, col: col + blocksize-1) = DCT_matrix;
end
end
fprintf(1, ' CPU time used: %1.3f\n', (cputime - starttime))
% Reverse the process (take the Inverse DCT)
fprintf(1, 'Reconstructing quantized values and taking the inverse DCT...\n');
starttime = cputime;
recon_img = orig_img - orig_img; % zero the matrix for the reconstructed image
for row = 1: blocksize: rows-blocksize+1
for col = 1: blocksize: cols-blocksize+1
% take a block of the image:
IDCT_matrix = jpeg_img(row: row + blocksize-1, col: col + blocksize-1);
% reconstruct the quantized values:
IDCT_matrix = IDCT_matrix ...
.* (DCT_quantizer(1:blocksize, 1:blocksize) * quant_multiple);
% perform the inverse DCT:
IDCT_matrix = DCT_trans' * IDCT_matrix * DCT_trans;
% place it into the reconstructed image:
recon_img(row: row + blocksize-1, col: col + blocksize-1) = IDCT_matrix;
end
end
fprintf(1, ' CPU time used: %1.3f\n', (cputime - starttime))
% Restore image to normal
% Level-shift the image back
recon_img = recon_img + ceil(colors/2);
orig_img = orig_img + ceil(colors/2);
% Clip off padded rows and columns
rows = rows - pad_rows;
cols = cols - pad_cols;
orig_img = orig_img(1:rows, 1:cols);
recon_img = recon_img(1:rows, 1:cols);
% Display image
ax(2) = subplot(1,2,2);
image(recon_img)
title('Decompressed JPEG image')
linkaxes(ax,'xy')
axis(ax,'image')
% Calculate the root-mean-square error
fprintf(1, 'Calculate the root-mean-square error...\n');
error = orig_img -recon_img;
e = reshape(error,1,[]);
e_rms = sqrt((e*e')/64);
fprintf(1, '\nThe root-mean-square error (RMSE) is: %1.3f\n\n', e_rms);
% Calculate signal-to-noise ratio
fprintf(1, 'Finding the signal-to-noise ratio...\n');
starttime = cputime;
PSNR = 0; % Peak-Signal-to-Noise Ratio of the reconstructed image
for row = 1:rows
for col = 1:cols
PSNR = PSNR + (orig_img(row, col) - recon_img(row, col)) ^ 2;
end
end
PSNR = 10 * log10 ((255^2) / (1 / (((rows + cols) / 2) ^ 2) * PSNR));
% (averaged rows and cols together)
fprintf(1, ' CPU time used: %1.3f\n', (cputime - starttime))
fprintf(1, '\nThe signal-to-noise ratio (PSNR) is: %1.3f dB\n\n', PSNR);
end