If you want to know how JPEG/MPEG quantization works, after each 8 x 8 block has its DCT computed, there is a single quantization matrix applied to each of these DCT coded blocks.
How the quantization works is that the quantization matrix is also 8 x 8. A quantized DCT block is calculated by doing a point by point division between the original DCT block and the quantization matrix. After, the values are rounded to the nearest integer to allow for efficient compression. If you want to convert the DCT coefficients (after quantization) into a binary sequence, the coefficients are reordered into a 1D stream (array) of coefficients by accessing the coefficients within the block in zig-zag order. After this reordering, Huffman encoding or some kind of lossless compression algorithm is employed.
A common quantization matrix in the JPEG standard is the following. This is to achieve a 50% image quality after quantization (using MATLAB syntax):
quant_matr = [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];
Once you have this quantization matrix, you can do something like this in MATLAB. Let's assume that in
is an 8 x 8 DCT encoded block.
in = double(in); % // Ensure double precision
out = round(in ./ quant_matr);
Now, if you want to recover the quantized block to ultimately recover the reconstructed DCT block, you would simply do a point by point multiplication and truncate any decimals that result.
Let's assume that in
is an 8 x 8 quantized block. You can do something like this in MATLAB:
in = double(in); % // Ensure double precision
out = floor(in .* quant_matr);
Bear in mind that this is lossy compression as you will not be able to get the original DCT block back because of the quantization. A full MATLAB function script that encapsulates this idea could look something like this:
function [out] = JPEGQuantize(in, flag)
[M,N] = size(in);
if(M ~= 8 && N ~= 8)
error('Image must be an 8 x 8 patch');
end
if(nargin == 1)
flag = 0;
elseif(nargin == 2)
if(strcmpi(flag,'f'))
flag = 0;
elseif(strcmpi(flag,'b'));
flag = 1;
else
error('Please specify the right parameter for quantization: (f)wd or (b)wd');
end
else
error('Please specify the right amount of parameters');
end
% // Ensure double precision
in = double(in);
quant_matr = [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];
if(flag == 0) % Quantize
out = round(in ./ quant_matr);
else
out = floor(in .* quant_matr); % Truncate any decimals
end
You would run this script with 2 parameters:
- An 8 x 8 DCT block, whether it was quantized or not
- A flag:
flag=f
is for going forwards (Original to quantized) andflag=b
is for going backwards (Quantized to reconstructed)
The output is either the quantized block or the reconstructed block, depending on what you specified for flag
.
If you want more information, check out the following links:
- http://en.wikipedia.org/wiki/Quantization_matrix#Quantization_matrices
- http://cs.stanford.edu/people/eroberts/courses/soco/projects/data-compression/lossy/jpeg/coeff.htm
Link #2 has a different quantization matrix so that the quality of the reconstructed image is higher. You choose different quantization matrices for higher quality, but obviously the image size will be greater as there is less to exploit when performing lossless compression.