compression/decodage.pas

251 lines
4.4 KiB
Plaintext

program decodage;
uses crt,dos,math;
type
liste=^cellule;
cellule=record
octet:byte;
freq:longword;
suiv:liste;
gauche:liste;
droite:liste;
end;
fichier=array of byte;
catalogue=array[0..255] of byte;
var p:fichier;l:liste;premier:byte;taille,index:longword;chemin:string;
function prefixe(ind:fichier):longword;
var s,i:longword;
begin
s:=0;
for i:=length(ind)-1 downto 0 do s:=(ind[i] div 2)*trunc(power(2,7*(length(ind)-1-i)))+s;
prefixe:=s;
end;
procedure importer(var p:fichier; var l:liste; var premier:byte;var chemin:string);
var f:file;i:longword;j,longueur:byte;ind:fichier;l1,l2:liste;
begin
write('Chemin du fichier : ');
readln(chemin);
assign(f,chemin);
reset(f,1);
writeln('Importation...');
blockread(f,longueur,1);
(*Pour éviter les problèmes avec longueur=0, on fera une boucle de 0 à longueur-1*)
longueur:=longueur-1;
new(l);
l^.suiv:=nil;
setlength(ind,0);
for j:=0 to longueur do
begin
l^.gauche:=nil;
l^.droite:=nil;
blockread(f,l^.octet,1);
repeat
begin
setlength(ind,length(ind)+1);
blockread(f,ind[length(ind)-1],1);
end;
until ind[length(ind)-1] mod 2 = 0;
l^.freq:=prefixe(ind);
setlength(ind,0);
new(l1);
l1^.suiv:=l;
l:=l1;
end;
l2:=l;
l:=l^.suiv;
dispose(l2);
blockread(f,premier,1);
i:=0;
setlength(p,filesize(f)-filepos(f));
while not eof(f) do
begin
blockread(f,p[i],1);
i:=i+1;
end;
close(f);
end;
function inserer(var l:liste; var l1:liste):liste;
begin
if l=nil then
begin
l1^.suiv:=nil;
inserer:=l1;
end
else
begin
if l1^.freq<=l^.freq then
begin
l1^.suiv:=l;
inserer:=l1;
end
else
begin
l^.suiv:=inserer(l^.suiv,l1);
inserer:=l;
end;
end;
end;
procedure arbre(var l:liste);
var l1:liste;
begin
if l^.suiv<>nil then
begin
new(l1);
l1^.gauche:=l;
l1^.droite:=l^.suiv;
l1^.freq:=l^.freq+l^.suiv^.freq;
l:=inserer(l^.suiv^.suiv,l1);
arbre(l);
end;
end;
function bit(b,position:byte):byte;
begin
bit:=(b div trunc(power(2,position)))-(2*(b div trunc(power(2,position+1))));
end;
procedure interpreter(l:liste;var p:fichier;premier:byte);
var m:byte;l1:liste;f:fichier;i:longword;
begin
m:=premier;
l1:=l;
setlength(f,0);
for i:=0 to length(p)-1 do
begin
repeat
begin
if bit(p[i],m)=0 then l1:=l1^.gauche else l1:=l1^.droite;
if ((l1^.gauche=nil) and (l1^.droite=nil)) then
begin
setlength(f,length(f)+1);
f[length(f)-1]:=l1^.octet;
l1:=l;
end;
m:=m-1;
end;
until m=255;
m:=7;
end;
p:=f;
setlength(f,0);
end;
procedure coder(p:fichier;taille:longword);
var ref,car:catalogue;i:longword;j,k,l:byte;f:fichier;
begin
for i:=0 to 255 do ref[i]:=i;
car:=ref;
setlength(f,taille);
for i:=0 to taille-1 do
begin
j:=p[i];
f[i]:=car[j];
l:=car[j];
for k:=j downto 1 do
begin
car[k]:=car[k-1];
end;
car[0]:=l;
end;
p:=f;
setlength(f,0);
end;
function prefixe(ind:fichier;taille:longword):longword;
var s,i:longword;
begin
s:=0;
for i:=taille-1 downto 0 do s:=(ind[i] div 2)*trunc(power(2,7*(taille-1-i)))+s;
prefixe:=s;
end;
procedure preliminaire(var f:fichier;var index:longword);
var ind,p:fichier;i,j:longword;
begin
i:=0;
setlength(ind,0);
repeat
begin
setlength(ind,i+1);
ind[i]:=f[i];
i:=i+1;
end;
until ind[i-1] mod 2 = 0;
index:=prefixe(ind,i);
setlength(ind,0);
setlength(p,length(f)-i);
for j:=i to length(f)-1 do p[j-i]:=f[i];
f:=p;
setlength(p,0);
end;
function decode(index,taille:longword;t:fichier):fichier;
var i,j,sum:longword;C,P:array of longword;S:fichier;
begin
setlength(C,256);
setlength(P,taille);
setlength(S,taille);
for i:=0 to 255 do C[i]:=0;
for i:=0 to taille-1 do
begin
P[i]:=C[t[i]];
C[t[i]]:=C[t[i]]+1;
end;
sum:=0;
for i:=0 to 255 do
begin
sum:=sum+C[i];
C[i]:=sum-C[i];
end;
i:=index;
for j:=taille-1 downto 0 do
begin
S[j]:=t[i];
i:=P[i]+C[t[i]];
end;
decode:=S;
end;
function nouv_chemin(chemin,nom:string):string;
var i:byte;s:string;
begin
s:=chemin;
i:=length(chemin);
while s[i]<>'/' do i:=i-1;
delete(s,i,length(chemin)-i+1);
nouv_chemin:=s+'/'+nom
end;
procedure ecrire(d:fichier;taille:longword;chemin:string);
var f1:file;nom:string;i:longword;
begin
write('Nom du fichier : ');
readln(nom);
assign(f1,nouv_chemin(chemin,nom));
rewrite(f1,1);
writeln('Écriture de la séquence...');
for i:=0 to taille-1 do
begin
blockwrite(f1,d[i],1);
end;
close(f1);
end;
begin
importer(p,l,premier,chemin);
arbre(l);
interpreter(l,p,premier);
taille:=length(p);
coder(p,taille);
preliminaire(p,index);
taille:=length(p);
p:=decode(index,taille,p);
writeln('ok');
ecrire(p,taille,chemin);
end.