Nouvelle algorithme de compression

Résolu/Fermé
LaPatate64 Messages postés 5 Date d'inscription dimanche 10 février 2013 Statut Membre Dernière intervention 12 février 2013 - 10 févr. 2013 à 15:04
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 - 2 avril 2013 à 20:26
Bonjour,

Je vien de creer en java un outil de compression et je souhaite avoir votre avis sur ses performances (non en vitesse mais en puissance de compression) pour l'instant l'engin est tres lent et peut compresser 800 Ko en quelques secondes, il n'y a pas de gestion du multi Thread. Voici le lien vers les sources : https://github.com/LaPatate64/Compressor

A voir également:

3 réponses

KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
10 févr. 2013 à 18:38
Quand on regarde ta classe ByteBuffer, on voit immédiatement pourquoi tes performances sont mauvaises, le dimensionnement de ton byte[] data est trop strict, sauf erreur, tu as toujours data.length==stackSize, ce qui signifie que tu fais sans arrêt des opérations de copier/coller des données (regarde push, pop, et remove)

Pour améliorer la vitesse, il faut que tu limites le nombre de ces copier-coller, en t'autorisant d'avoir data.length>stackSize, et augmenter de manière importante la taille du buffer (x2 par exemple) lorsque tu le redimensionnes, afin d'éviter d'avoir à l'agrandir trop souvent. De plus, quand tu enlèveras des données, ne changes pas de tableau, ça ne sert à rien.

Par exemple tu peux faire une fonction ensureCapacity qui augmentera ton tableau en taille si nécessaire. Idéalement, c'est la seule méthode qui devrait modifier la taille du tableau, les autres méthodes devrait l'appeler pour augmenter la mémoire. Au passage, il serait plus performant d'utiliser les méthodes de Arrays plutôt que de réimplémenter à la main les copies. Enfin, quelques constructeurs seraient les bienvenus, en particulier pour initialiser le ByteBuffer avec une capacité donnée.

Il faudrait passer en revue toutes tes méthodes pour les optimiser avec les modifications, je t'en donne juste quelques unes pour voir comment ça marche :

private byte[] data;
private int stackSize;
private int stackCapacity;

public ByteBuffer()
{
    stackSize = 0;
    stackCapacity = 128;
    data = new byte[128];
}

public ByteBuffer(int capacity)
{
    stackSize = 0;
    stackCapacity = capacity;
    data = new byte[capacity];
}

public ByteBuffer(byte[] value)
{
    stackCapacity = stackSize = value.length;
    data = Arrays.copyOf(value, stackCapacity);
}

private void ensureCapacity(int minimalCapacity)
{
    if (stackCapacity < minimalCapacity)
    {
        do stackCapacity *= 2;
        while (stackCapacity < minimalCapacity);
        
        data = Arrays.copyOf(data, stackCapacity);
    }
}

public void clear()
{
    stackSize = 0;
}

public void push(byte number) 
{
    ensureCapacity(stackSize+1);
    data[stackSize]=number;
    stackSize++;
}

public void push(byte[] number)
{
    ensureCapacity(stackSize+number.length);
            
    for (int a=stackSize, b=0; b != number.length; a++, b++)
        data[a] = number[b];
    
    stackSize += number.length;
}

Pour ton algorithme de compression, quelques explications de ta méthode serait plus qu'utile pour faire des remarques objectives. Sinon, on pourra juste optimiser le programme mais pas la compression en elle même.
1
LaPatate64 Messages postés 5 Date d'inscription dimanche 10 février 2013 Statut Membre Dernière intervention 12 février 2013
10 févr. 2013 à 20:54
Merci de ta reponse,

J'avai prevu un systeme en multi thread ou mieux, une syteme en opencl.
pour le ByteBuffer je l'ai juste créé vite fait je vai faire des optimistation et reuploader tou sa.
Voici une image du fonctionnement :
http://imageshack.com/f/65explicationcompresseurp
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138 > LaPatate64 Messages postés 5 Date d'inscription dimanche 10 février 2013 Statut Membre Dernière intervention 12 février 2013
10 févr. 2013 à 21:14
Mais, pourquoi-donc utiliser 6 entrées pour le dictionnaire, au lieu de 8 par exemple? Puisqu'en binaire tout se joue à la puissance deux, mieux vaut s'aligner et ne pas s'embêter avec des chiffres qui rentrent dedans que difficilement...
Et puis en quelque sorte ce principe est déjà employé, mais en plus... abouti! C'est le principe de base de l'algorithme lzw, auquel je te propose de t'intéresser:
https://fr.wikipedia.org/wiki/Lempel-Ziv-Welch
0
LaPatate64 Messages postés 5 Date d'inscription dimanche 10 février 2013 Statut Membre Dernière intervention 12 février 2013 > LaPatate64 Messages postés 5 Date d'inscription dimanche 10 février 2013 Statut Membre Dernière intervention 12 février 2013
11 févr. 2013 à 19:20
@nicocorico:

Pour les 6 entrées si tu fait reference a l'image j'ai pris 6 caractere au hasard, le dictionnnaire peut contenir 256 entrées.
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 11/02/2013 à 20:48
Oui je vois, tu sembles vouloir exploiter l'idée que les octets à compresser n'utilisent qu'une petite partie des 256 valeurs possibles...ou du moins je crois, car tu dis que ton dictionnaire peut s'étendre jusqu'à 256 valeurs, mais dans ce cas il contiendrait simplement les valeurs de 0 à 255, à quoi servirait-il?
Et il faut pas se leurrer, il n'y a aucune chance que la fourchette de valeurs soit si limité, ou bien dans ce cas il faut les compresser dès l'origine plutôt que d'utiliser un principe de compression plus universel...
Et c'est très bien de chercher par soi-même et il faut que tu continues dans cette voie, cependant il faut aussi savoir s'inspirer de ce qui existe déjà...tu penses bien que nombreux sont ceux qui ont réfléchi à ce sujet, et le fait de bien étudier les algorithmes que d'autres ont imaginé te permettra de comprendre les pièges, les limites et les possibilités de la compression de données. Je te propose de creuser le lien que je t'ai passé, tu y apprendra directement le principe que tu vas finir par obtenir en cherchant dans la voie que tu as empruntée!

Le chêne aussi était un gland, avant d'être un chêne
1
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
11 févr. 2013 à 20:59
Tiens, à propos de personnes qui cherche, est-ce que tu connais (si ça existe) un algo "optimal" de compression, peu importe sa complexité.
Bien sûr ça n'aurait aucun intérêt puisqu'on se retrouverait avec des temps de compression bien trop coûteux, mais juste sur le principe d'avoir une archive "minimale".
Hier, je pensais à un truc assez "simple", avec une complexité O(N^3) voire O(N^4), il faudrait que je mette ça sur papier pour mieux voir ce que ça donnerait ^^
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
11 févr. 2013 à 21:17
Non non j'en connais aucun, et à ma connaissance le principe de compression sans perte est très vite limité, pour autant que je sache -n'étant pas scolaire- il semble se cantonner à quelques algo finalement relativement simples d'approche! Et il y a une raison à cela, l'algo lzw est excellent et très simple, tout en restant nettement améliorable mais au prix de gros efforts et autant d'incertitude de résultats. Pour rester sans perte, l'idée de tirer des suites et de les répéter semble être la voie universelle, et ne serait-ce que pour optimiser le choix des chaines, l'ampleur des calculs à mener est astronomique! Il faudrait se pencher sur les principes statistiques pour en savoir plus...
Et de là à déduire la sève ultime, le petit tas incompressibles d'informations cohérentes contenues dans un fichier, j'ignore si c'est possible, sans doute seulement en théorie, celle de l'entropie par exemple!
En tout cas toute idée à ce propos m'intéresse, si elle reste abordable sans être trop matheux toutefois!
Déjà le terme de complexité en O(N^3) ou O(N^4) échappe à ma compréhension!
0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
11 févr. 2013 à 21:48
O(N^3) c'est une manière de représenter la complexité d'un algorithme "au pire cas".
C'est à dire ici que si j'ai un algorithme O(N^3), pour N bits à compresser, il nécessitera au pire cas N^3 calculs, ça correspondrait grosso-modo à un algorithme basé sur 3 boucles imbriquées :

for (int a=0; a<n; a++)
for (int b=0; b<n; b++)
for (int c=0; c<n; c++)
    // bloc d'instruction

C'est à dire que pour 1000 bits, il me faudrait 1000^3 calculs, et qu'à chaque fois que je multiplie par 2 ma taille du fichier, je multiplie par 8 la durée de l'algorithme !!!

Par exemple les tris par bulle est lent car en O(N^2) alors que le tri par fusion est l'un des plus rapide car en O(N.log N).

Je pense que la plupart des algorithmes de compression doivent être assez proche de O(N), c'est à dire qu'on lit une fois les données. Evidemment là, on ne parle que du temps de compression, pas de sa qualité. Et même si des algos comme LZW sont bons en O(N), ils seront surement moins bons face à des algos en O(N^2), O(N^3), etc. qui prendront plus de temps à chercher de meilleurs arrangements. Même si je suis bien conscient que la rapidité d'exécution est plus que vitale !
0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
12 févr. 2013 à 00:14
Voici l'algorithme auquel je pensais. Mes idées sont moins confuses une fois sur papier, mais ça reste un brouillon. Remarque : j'ai une façon très personnelle d'écriture un algo ;-)

Soit T le tableau de bits à compresser.

Définitions :

   E est le nombre de bits nécessaires à la représentation des indices de T.
   
   D est un doublon dans T s'il existe plusieurs occurrences distinctes de D dans T.
   
   N(D) est le nombre d'occurrences de D dans T.
   
   L(D) est la longueur de D (en bits)
   
   A(D) est l'"aire" de D : A(D)=N(D)*L(D)
   
   P(D) est la liste de positions des occurrences de D dans T

Exemple :

   T = 11100110
   E = 3
   D = 110
   N = 2
   L = 3
   A = 6
   P = {1,5}

Principe de la compression :

   On choisit un doublon D, et on supprime toutes ses occurrences dans les données.
   Enfin, on ajoute un en-tête qui indique la position de toutes ces occurrences.
   Cette compression n'a d'intérêt que si l'on trouve un doublon suffisamment grand et/ou nombreux.
   Un doublon est intéressant si L > E(2+N)/(N-1). Exemples : N=2 et L>4E, N=4 et L>2E...

Définitions :

   H(D) est un en-tête de remplacement de D, il est constitué de :
      - Un entier 'E bits' de valeur N(D)
      - Un entier 'E bits' de valeur L(D)
      - La liste d'entiers 'E bits' de valeurs P(D)
      - La valeur de D
   
   K(D) est la taille de H(D) : K(D) = [2+N(D)]*E + L(D)
   
   Q(D) est la qualité de D : Q(D) = A(D)-K(D)
   
   U(D) est le tableau T dont on a enlevé toutes les occurrences de D.
   
   C(D) est la compression de T, constitué de H(D) suivi de U(D).

Exemple :

   H = 2 / 3 / 1,5 / 110 --> 010 011 001 101 110
   K = 15
   Q = -11 : NB. dans cet exemple le doublon n'a aucun intérêt (Q<0)
   U = 10
   C = 01001100110111010

Algorithme de compression :

   I = 0
   Chercher D dans T tel que Q(D) est maximale
   Si Q(D)>0
      Remplacer T par C(D)
      I++
      Recommencer

Définitions :

   I est le nombre de fois où l'algorithme a été effectué.

   F est le fichier résultat de la compression du tableau T par cette méthode. Il contient :
      - Un entier 8 bits de valeur E
      - Un entier 8 bits de valeur I
      - Le tableau T résultant des I opérations.

Algorithme de décompression :

   Décomposer le tableau T en H et U.
   Insérer dans U les N valeurs de D aux positions P.
   Remplacer T par U.
   Recommencer I fois.

D'après moi (à vue de nez), la recherche d'un doublon nécessite 3 boucles portant sur l'indice de début de la première occurrence, l'indice de début d'un doublon, et sur l'indice qui parcourt les deux doublons pour les comparer. C'est pour ça que je parlais de O(N^3), même si en réalité, ce sera moins. De plus comme on "recommence I fois" je parlais éventuellement d'un O(N^4), même si bien sûr on ne recommencera pas N fois.

PS. Je ne sais pas encore comment trouver le "meilleur" doublon, mais j'avoue ne pas m'être trop creusé la tête non plus dessus. Une méthode simple mais coûteuse serait de chercher tous les doublons possibles... de toute façon j'ai posé que le coût de la recherche n'était pas un problème ^^
0
LaPatate64 Messages postés 5 Date d'inscription dimanche 10 février 2013 Statut Membre Dernière intervention 12 février 2013
12 févr. 2013 à 18:33
pas mal j'y a pas pensé ^^
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 1/04/2013 à 18:10
Bon j'y reviens un peu!
J'ai pensé à une technique toute simple et relativement rapide permettant de déterminer toutes les répétitions de suites d'octets d'un fichier. En fait il suffit de répertorier les suites déjà rencontrées sous forme d'arbre, et pour chaque nouvelle recherche on trouve la meilleure chaine existante, puis on détermine le nombre d'octets en commun au-delà des bornes de la meilleure chaine initiale... Chaque chaine ajoute donc un ou plusieurs octets à sa chaine parente, sa taille s'arrêtant au premier octet différent, donc pour chaque chaine on détermine bel et bien la plus longue chaine lui correspondant dans le fichier. Et on fait ça à chaque octet ajouté, donc on créé autant de chaine qu'il y a d'octets.
Grâce à ce résultat, on peut donc savoir quelles sont les chaines les plus rentables pour la compression... d'autant plus qu'on a accès à l'ensemble des descendants d'une chaine donnée, ce qui permet de déterminer tous les endroits où l'on trouve la même base, pour limiter la diversité des chaines. Donc il devient possible de partir d'une chaine et de dire partout où on la trouve comme tu en avais l'idée... là on a le choix entre le «où» et le «quoi»!
Voilà, c'est une bonne base de travail!
Je mets ici le programme en pascal (delphi), programme n'étant qu'une base pour expérimentation, il ne fait rien d'autre que de calculer la table pour l'exemple.

unit Tri;     

interface     
  uses Windows, Messages, SysUtils;     

implementation     


  Type     
    PDatasT = ^DatasT;     
    DatasT  = Array[0..$7FFFFFF] of Byte;     

    PPAlpha_Def = ^PAlpha_Def;     
    PAlpha_Def  = ^Alpha_Def;     
    Alpha_Def   =  Packed Object     
      FFrere     : PAlpha_Def;       // Chaine suivante ayant la même chaine-base     
      FFils      : PAlpha_Def;       // Pointeur sur le premier descendant     
      FParent    : PAlpha_Def;       // Parent     
      FSize      : Integer;          // Taille totale de la chaine     
      FFirstCode : PDatasT;          // Pointeur sur le début spécifique de cette chaine     
    end;     


  Var     
    AlphaPtr : Array of Alpha_Def;        // Recueil des chaines     


  Procedure Extract(Src: PDatasT; Size: Integer);     
    Var     
      Fils_      : PAlpha_Def;     
      PredFils_  : PPAlpha_Def;     
      ChaineBase : PAlpha_Def;     
      NewParent  : PAlpha_Def;     
      NewSize    : Integer;     
      Alpha_Size : DWord;     
    begin     
      ChaineBase:= @AlphaPtr[0];     
      Alpha_Size:= 256;     
            
      Repeat     
        If ChaineBase.FSize > 0 then     
        begin     
          DWord(NewParent):= DWord(ChaineBase) + SizeOf(Alpha_Def);     
          While NewParent.FSize >= ChaineBase.FSize do NewParent:= NewParent.FParent;     
        end else     
          NewParent:= @AlphaPtr[Src[0]];     

        NewSize:= NewParent.FSize+01;     

        Repeat     
          If NewParent.FFirstCode <> nil then     
           While (NewParent.FFirstCode[NewSize] = Src[NewSize]) and (NewSize < Size) do Inc(NewSize);     

          PredFils_:= @NewParent.FFils;     
          Fils_    := NewParent.FFils;     

          While (Fils_ <> nil) and ((Fils_.FSize < NewSize) or     
          ((Fils_.FSize = NewSize) and (Fils_.FFirstCode[NewSize] < Src[NewSize]))) do     
          begin     
            PredFils_:= @Fils_.FFrere;     
            Fils_    := Fils_.FFrere;     
          end;     

          If (Fils_ = nil) or (Fils_.FSize <> NewSize) or (Fils_.FFirstCode[NewSize] <> Src[NewSize]) then Break;     

          NewParent:= Fils_;     
          Inc(NewSize);     
        until (NewSize >= Size);     


        With AlphaPtr[Alpha_Size] do     
        begin     
          FParent    := NewParent;     
          FFirstCode := Src;       // Pointe sur le début de la chaine     
          FSize      := NewSize;     

          FFrere     := PredFils_^;     
          PredFils_^ := @AlphaPtr[Alpha_Size];     
        end;     
        ChaineBase:= NewParent;     
        Inc(Alpha_Size);     
        Inc(DWord(Src));     
        Dec(Size);     

      Until Size < 0;     
    end;     


Var     
  Source   : array of Byte;     

  F        : Integer;     
  PtrBuf   : Pointer;     
  FileSize : Integer;     

begin     
  F:= FileOpen('nom du fichier', fmopenread);     
  FileSize:= FileSeek(F, 00, 2);     
  FileSeek(F, 0, 0);     

  SetLength(Source, FileSize+1000);     
  SetLength(AlphaPtr, FileSize+1000);     

  PtrBuf := @Source[0];     
  FileSize:= FileRead(F, Pointer(PtrBuf^), FileSize);     
  FileClose(F);     

  FillChar(Pointer(AlphaPtr)^, Length(AlphaPtr) - 01, 0);     

  Extract(Source, FileSize);     
end.
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 1/04/2013 à 17:52
J'ai aussi fait la procédure d'extraction en assembleur, beaucoup plus rapide, le pascal étant très limité pour ce genre de programme!
L'ensemble est directement fonctionnel sous delphi 6.0

  Procedure Extract(Src: Pointer; Size: Integer);  
    asm  
        Push   EBX;  
        Push   EDI;  
        Push   ESI;  
        Push   EBP;  

        Push   EDX;  
        Mov    EBP,AlphaPtr;  
        Add    EBP,Type Alpha_Def * 256;  
        Jmp    @S01;  

@ExtBcl:Mov    EDX,[ECX].Alpha_Def.FSize;  
        And    EDX,EDX;  
        Jz     @S01;  
        Add    ECX,Type Alpha_Def;  
@DecBcl:Cmp    [ECX].Alpha_Def.FSize,EDX;  
        Jb     @S02;  
        Mov    ECX,[ECX].Alpha_Def.FParent;  
        Jmp    @DecBcl;  


@S01:   Movzx  ECX,Byte ptr [EAX];  
        Imul   ECX,Type Alpha_Def;  
        Add    ECX,AlphaPtr;  

@S02:   Mov    EBX,[ECX].Alpha_Def.FSize;  
        Inc    EBX;  

        Mov    [EBP].Alpha_Def.FParent,ECX;  
        Mov    EDI,[ECX].Alpha_Def.FFirstCode;  
        And    EDI,EDI;  
        Jz     @Bcl_P;  

@BclDWS:Sub    EBX,04;           // Recherche de correspondance Dword  
@BclDW: Add    EBX,04;  
        Cmp    EBX,[ESP];  
        Ja     @Bcl_BS;  
        Mov    EDX,[EAX + EBX];  
        Cmp    EDX,[EDI + EBX];  
        Jz     @BclDW;  

@Bcl_BS:Dec    EBX;                 // Recherche de correspondance Byte  
@Bcl_B: Cmp    EBX,[ESP];  
        Ja     @Bcl_P;  
        Inc    EBX;  
        Mov    DL,[EAX + EBX];  
        Cmp    DL,[EDI + EBX];  
        Jz     @Bcl_B;  


@Bcl_P: Lea    ESI,[ECX].Alpha_Def.FFils;  
        Jmp    @Ent;  
@Bcl:   Lea    ESI,[ECX].Alpha_Def.FFrere;  
@Ent:   Mov    ECX,[ESI];           // Lis le pointeur sur le frère  
        And    ECX,ECX;  
        Jz     @Final;  
        Cmp    EBX,[ECX].Alpha_Def.FSize;  
        Ja     @Bcl;  
        Jb     @Final;  
        Mov    EDI,[ECX].Alpha_Def.FFirstCode;  
        Mov    DL,[EAX + EBX];  
        Cmp    DL,[EDI + EBX];  
        Ja     @Final;  
        Jb     @Bcl;  


        Mov    [EBP].Alpha_Def.FParent,ECX; // Confirme un nouveau parent  
        Cmp    EBX,[ESP];  
        Jb     @BclDWS;  

       // Finalise la nouvelle chaine  
@Final: Mov    [EBP].Alpha_Def.FFirstCode,EAX;  
        Mov    [EBP].Alpha_Def.FSize,EBX;  
        Mov    ECX,[ESI];  
        Mov    [EBP].Alpha_Def.FFrere,ECX;  
        Mov    [ESI],EBP;  

        Mov    ECX,[EBP].Alpha_Def.FParent;  

        Inc    EAX;  
        Add    EBP,Type Alpha_Def;  
        Dec    DWord ptr [ESP];  
        Jns    @ExtBcl;  

        Pop    EDX;  
        Pop    EBP;  
        Pop    ESI;  
        Pop    EDI;  
        Pop    EBX;  
    end;
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
2 avril 2013 à 19:41
Oups, je devais préciser qu'il s'agit d'une unité qu'il faut inclure dans un programme, et qu'il faut évidemment mettre un nom de fichier valide dans le "fileopen"!
Ensuite il est facile d'utiliser le tableau, puisqu'il y a une entrée de chaine par octet une solution simple peut être de prendre la première chaine, puis la chaine suivante en ajoutant la taille de la première chaine à l'indice... par contre, il est nécessaire de préciser la taille de chaque chaine aussi, puisqu'elle n'est pas implicite! Pour ça il peut y avoir plusieurs méthodes, plus ou moins compliquées!
En tout cas les tests que j'ai fais montre qu'on obtient un taux de compression bien plus intéressant qu'avec lzw, sans être exceptionnel pour autant. Mais tout de même ça permet de constater que la taille de chaque indexs n'est pas forcément le plus important, preuve en est que là on parle même plus en index mais on donne carrément la position et la taille de la chaine qu'on doit recopier à partir de ce qui précède! Et de cette manière même sans optimiser c'est déjà meilleur, ce qui montre qu'il vaut mieux avoir un très grand choix de chaines mais coûteux plutôt qu'un choix restreint et spartiate. Forcément, pour chaque doublement du nombre de chaine indexables, ça ne demande qu'un bit de plus pour l'index... avec un index de 20 bits, passer à 21 bits n'est pas bien significatif mais autorise un peu plus d'un million de possibilités supplémentaires, tout est là! Donc diminuer la taille des indexs reste une base de travail c'est sûr, mais proposer un maximum de choix aussi...
Et y'a pas à dire, il faut travailler sur un très grand nombre de chaines... penser obtenir une grosse compression avec quelques chaines très répétitives est, je pense, irréaliste... Ce serait se passer des possibilités de compression sur tout le reste, tout simplement!
Là je m'orientais vers deux idées différentes, l'une qui consisterait à présenter l'information de telle manière qu'elle pourrait être recompressable par la même méthode, en restant sur des bases octets, et l'autre basée sur le fait d'introduire des octets spéciaux dans les chaines, genre la valeur qui sert le moins dans le fichier, et qu'on remplace par un octet supplémentaire fourni, afin d'éviter de briser les chaines avec des valeurs "folles"...
Les possibilités restent de toute façon infinies!
0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
2 avril 2013 à 20:17
Salut nicocorico !

J'avoue ne pas avoir trop de temps en ce moment pour m'investir dans une réflexion intense, je me le limite à virevolter sur quelques question faciles. Mais un jour viendra où je regarderai plus en détail tout ceci ;-)
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
2 avril 2013 à 20:26
Salut KX!

Pas de problème, de toute façon ce topic est intemporel n'est-ce pas! D'ici que tu t'y penche je continuerai à le garnir de mes réflexions!
0