TP-compression-streaming-in.../CompressionJPEG.m
2023-06-25 16:32:14 +02:00

122 lines
4.9 KiB
Matlab

% TP CoCodages JPEG et MPEG-2 - 3SN-M - 2022
%--------------------------------------------------------------------------
% Fonction de compression JPEG d'une image
%--------------------------------------------------------------------------
% [I_Codee,Poids,Compression,nb_coeffs_AC,nb_coeffs_DC] =
% CompressionJPEG(I_Origine,canal,methode,F_Qualite)
%
% sorties : I_Codee = image de DCT quantifiee
% Poids = poids de l'image d'origine en ko pour les differentes
% etapes de la compression
% Compression = taux de compression final
% nb_coeffs_AC = nombre de coefficients AC dans l'image compressee
% nb_coeffs_DC = nombre de coefficients DC dans l'image compressee
%
% entrees : I_Origine = image originale (ou residuelle)
% canal = canal pour le choix de la table de quantification :
% 'Luminance', 'Chrominance' ou 'Residu'
% methode = methode de calcul de la DCT : 'Matlab' ou 'Rapide'
% F_Qualite = facteur de qualite pour la compression
%--------------------------------------------------------------------------
% Fonctions a coder/utiliser : DCT2DParBlocs.m
% QuantificationDCT.m
% CodageEntropique.m
% CoefficientsACDC.m
%--------------------------------------------------------------------------
function [I_Codee, Poids, Compression, nb_coeffs_AC, nb_coeffs_DC] = CompressionJPEG(I_Origine, canal, methode, F_Qualite)
taille_bloc = 8;
sens = "Direct";
% calcul de la DCT
I_DCT = DCT2DParBlocs(sens, I_Origine, methode, taille_bloc);
% quantification
I_Codee = QuantificationDCT(sens, I_DCT, canal, F_Qualite, taille_bloc);
% calcul des coeffs AC DC
[Coeff_AC, Coeff_DC] = CoefficientsACDC(I_Codee, taille_bloc);
% bidule sur les coeffs
nb_coeffs_AC = length(Coeff_AC);
nb_coeffs_DC = length(Coeff_DC);
[Poids_AC, ~] = CodageEntropique(Coeff_AC);
[Poids_DC, ~] = CodageEntropique(Coeff_DC);
Poids.H_JPEG = Poids_AC + Poids_DC;
Poids.Origine = numel(I_Origine) / 1024;
Compression = 100 * (1 - Poids.H_JPEG / Poids.Origine);
end
%--------------------------------------------------------------------------
% Fonction de recuperation des coefficients AC/DC de la DCT par blocs
%--------------------------------------------------------------------------
%[Coeff_AC_Image, Coeff_DC_Image] = CoefficientsACDC(I_Quant, taille_bloc)
%
% sortie : Coeff_AC = vecteur reunissant tous les coefficients AC de
% l'image jusqu'au dernier coefficient non nul
% (taille variable)
% Coeff_DC = vecteur reunissant tous les coefficients DC de
% l'image (taille fixe)
%
% entree : I_Quant = Image de DCT quantifiee
% taille_bloc = taille des blocs pour la DCT (ici 8x8)
%--------------------------------------------------------------------------
function [Coeff_AC, Coeff_DC] = CoefficientsACDC(I_Quant, taille_bloc)
fun = @(block_struct) ParcoursBlocZigzag(block_struct.data, taille_bloc*taille_bloc);
zigzag = blockproc(I_Quant, [taille_bloc taille_bloc], fun);
% on réarange nos blocs
zigzag = reshape(zigzag', taille_bloc*taille_bloc, [])';
% on extrait les coeffs
Coeff_DC = zigzag(:, 1);
Coeff_AC = zigzag(:, 2:end);
% on suppr les zeros
Coeff_AC_nz = [];
for i = 1:size(Coeff_AC, 1)
last_non_zero = find(Coeff_AC(i, :), 1, 'last');
next_bloc = [Coeff_AC(i, 1:last_non_zero), 1000];
Coeff_AC_nz = cat(2, Coeff_AC_nz, next_bloc);
end
Coeff_AC = Coeff_AC_nz';
end
%--------------------------------------------------------------------------
% Fonction de parcours d'un bloc en zigzag pour recuperer les coefficients
% AC/DC de la DCT
%--------------------------------------------------------------------------
% Vecteur_zigzag = ParcoursBlocZigzag(Bloc_DCT,nb_pixels)
%
% sortie : Vecteur_zigzag = vecteur des coefficients DC/AC ordonnes du bloc
%
% entrée : Bloc_DCT = DCT du bloc courant
% nb_pixels = nombre de pixels dans le bloc
%--------------------------------------------------------------------------
function Vecteur_zigzag = ParcoursBlocZigzag(Bloc_DCT,nb_pixels)
% Initialisation du vecteur qui contiendra les coefficients
Vecteur_zigzag = zeros(1,nb_pixels);
% Remplissage en partant du debut et de la fin
for k = 1:nb_pixels/2
n = ceil(sqrt(2*k+1/4)-0.5);
temp = k - n*(n-1)/2;
if (mod(n,2) < 1)
i = temp;
else
i = n + 1 - temp;
end
j = n + 1 - i;
% Positionnement des coefficients dans le vecteur
Vecteur_zigzag(k) = Bloc_DCT(i,j);
Vecteur_zigzag(65-k) = Bloc_DCT(9-j,9-i);
end
end