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
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
A voir également:
- Nouvelle algorithme de compression
- Darkino nouvelle adresse - Guide
- Darkino : le grand site pirate change d'adresse et d'interface - Accueil - Services en ligne
- Extreme download nouvelle adresse - Accueil - Outils
- Nouvelle chaîne tnt gratuite 2024 - Accueil - TV & Vidéo
- Yggtorrent nouvelle adresse - Accueil - Outils
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
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 :
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.
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.
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
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
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
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
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 ^^
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 ^^
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
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!
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!
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
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 :
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 !
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 !
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
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 ;-)
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 ^^
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 ^^
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
12 févr. 2013 à 18:33
pas mal j'y a pas pensé ^^
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
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.
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.
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
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
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;
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
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!
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!
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
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 ;-)
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 ;-)
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
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!
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!
10 févr. 2013 à 20:54
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
10 févr. 2013 à 21:14
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
11 févr. 2013 à 19:20
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.