Autor Beitrag
Juniorsatan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mo 22.03.10 17:43 
Ich probiere mich gerade an einer RLE-Kompression für dynamische Arrays.

Bisher funktionierte die Prozedur mit allen Testarrays, die ich manuell erstellt habe. Generiere ich jedoch ein größeres (wo bspw. die Farbwerte eines Bildes gespeichert sind), kommt es zu einem Stackoverflow.

Die sieht wie folgt aus:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
procedure RLE(kanal_array: Array of Byte);
var
new_array: Array of Byte;
k, count: integer;
output:string;
begin
setlength(new_array, 0);  //Initialisierung
k:=0;                     //Initialisierung
While ( k <= length(kanal_array)) DO
  Begin
    count:= countrep(kanal_array, k);
    if (kanal_array[k] = 255then // Ist das Zeichen der Codeflag?
          Begin
            setlength(new_array, (length(new_array) + 2));
            new_array[(high(new_array)-1)]:= 255// Codeflag speichern
            new_array[(high(new_array))]:= 0;   // No Code Flag speichern
            inc(k)
          End
    else if (count > 3then  // mind. 4 redundante Zeichen nebeneinander
          Begin
            setlength(new_array, (length(new_array) + 3)); //neues Array wird um drei Elemente erhöht
            new_array[(high(new_array)-2)]:= 255// Codeflag im neuen Array an vorvorletzte Stelle
            new_array[(high(new_array)-1)]:= count;    // Anzahl der Wiederholungen des Zeichen  an vorletzte Stelle
            new_array[(high(new_array))]:= kanal_array[k]; // Zeichen selbst an letzte Stelle
            k:=(k + count); // neue Stelle, bei der Kompressionsversuch gestartet wird
          End
    Else
      Begin
        setlength(new_array, (length(new_array) + 1)); // Array um ein Element vergrößern
        new_array[(high(new_array))]:= kanal_array[k]; // Wert an letzte Stelle schreiben
        inc (k);
      End;
  End;
setlength(new_array, (length(new_array) - 1)); // Produziertes Array ist immer ein Index zu groß, wird hier behoben

{Test}
For k:=0 to high(new_array) DO
  begin
  output:= output + inttostr(new_array[k]) + '; ';
  end;

showmessage(output);
end;


Die Funktion countrep sucht redundante Einträge und sieht so aus:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function countrep(arr: Array of Byte; k:Integer): Integer;
var
n:integer;
Begin
n:=0;
While ( ( (k+n) < high(arr) ) AND (arr[(k+n)] = arr[(k+n)+1]) AND (n < 253)) Do  // Solange weder Ende der Schleife + gleichheit der benachbarten Elemente + Maxcount nicht überschritten
  Begin
  inc(n);
  End;
countrep:=n +1 ;
End;


Mich verwirrt wie gesagt der Fakt, dass es für kleine Arrays bisher tadellos funktionierte, Endlosschleifen o.ä. sehe ich auch nirgends. Habt ihr eine Idee?
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: Mo 22.03.10 17:52 
kann es sein das er sich in der markierten zeile aufhängt weil du mit <= length anstatt mit < length bzw <= high arbeitest?

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
procedure RLE(kanal_array: Array of Byte);
var
new_array: Array of Byte;
k, count: integer;
output:string;
begin
setlength(new_array, 0);  //Initialisierung
k:=0;                     //Initialisierung
While ( k <= length(kanal_array)) DO
  Begin
    count:= countrep(kanal_array, k);
    if (kanal_array[k] = 255then // Ist das Zeichen der Codeflag?
          Begin
            setlength(new_array, (length(new_array) + 2));
            new_array[(high(new_array)-1)]:= 255// Codeflag speichern
            new_array[(high(new_array))]:= 0;   // No Code Flag speichern
            inc(k)
          End
    else if (count > 3then  // mind. 4 redundante Zeichen nebeneinander
          Begin
            setlength(new_array, (length(new_array) + 3)); //neues Array wird um drei Elemente erhöht
            new_array[(high(new_array)-2)]:= 255// Codeflag im neuen Array an vorvorletzte Stelle
            new_array[(high(new_array)-1)]:= count;    // Anzahl der Wiederholungen des Zeichen  an vorletzte Stelle
            new_array[(high(new_array))]:= kanal_array[k]; // Zeichen selbst an letzte Stelle
            k:=(k + count); // neue Stelle, bei der Kompressionsversuch gestartet wird
          End
    Else
      Begin
        setlength(new_array, (length(new_array) + 1)); // Array um ein Element vergrößern
        new_array[(high(new_array))]:= kanal_array[k]; // Wert an letzte Stelle schreiben
        inc (k);
      End;
  End;
setlength(new_array, (length(new_array) - 1)); // Produziertes Array ist immer ein Index zu groß, wird hier behoben

{Test}
For k:=0 to high(new_array) DO
  begin
  output:= output + inttostr(new_array[k]) + '; ';
  end;

showmessage(output);
end;


lg elundril

_________________
This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
Juniorsatan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mo 22.03.10 18:09 
Daran habe ich auch schon gedacht, deswegen prüfe ich in der darauffolgenden Funktion sofort, ob ich mich noch im Rahmen des Arrays bewege.

ausblenden Delphi-Quelltext
1:
While ( ( (k+n) < high(arr) ) AND ....) Do					


Mir wurde schulischerseits beigebracht, dass es bei solchen Prüfungen wichtig ist, dass diese "vorne" in der Bedingung stehen, sodass bei einem etwaigen Überschreiten die hinteren Expressions nicht mehr angesprochen wird, da es sofort zum Abbruch kommt.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 22.03.10 18:40 
Dennoch läuft deine äußere Schleife in einen Fall rein, der ohne Behandlung un der inneren Schleife bleibt und damit nie verlassen wird. Schau Dir das doch einmal im Single-Step-Modus (F7/F8) im Debugger an und beobachte die verschiedenen Werte.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Juniorsatan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mo 22.03.10 18:43 
Kann ich das in irgendeiner Weise zumindest ein wenig automatisieren? Das Array ist um die 4000000 Einheiten groß und ich kriege den Fehler bisher nicht anders reproduziert, als das ich das besagte Bild als Ausgangsmaterial verwende.

Nichtsdestotrotz werd ichs mir nochmal angucken.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 22.03.10 19:24 
Haltepunkt setzen, links auf das rote Mumpel klicken --> Halötepunkt-Eigenschaften und da ne Bedingung eingeben.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.