Forum: Mikrocontroller und Digitale Elektronik zlib: adler32 Prüfsummer rechnet falsch


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Rangi J. (rangi)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,
ich habe PNG (libpng) auf meinem STM32 zum laufen gebracht. Darin 
enthalten ist ja die zlib und diese bringt die adler32() Prüfsumme mit. 
Funktioniert soweit prima, bis auf das die Prüfsumme nicht mit der Summe 
des png-Bildes übereinstimmt.
Wenn ich die Überprüfung abschalte (ganz am Ende) wird der Bildinhalt 
korrekt ausgegeben, keine Fehler.
Hat jemand sowas schonmal gemacht? Gibts da irgendwas zu beachten?
1
#define BASE 65521      /* largest prime smaller than 65536 */
2
#define NMAX 5552
3
#define MOD(a) a %= BASE
4
#define MOD28(a) a %= BASE
5
6
#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
7
#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
8
#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
9
#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
10
#define DO16(buf)   DO8(buf,0); DO8(buf,8);
11
12
u32 adler32(u32 adler, const u8 *buf, u32 len)
13
{
14
    u32 sum2;
15
    u32 n;
16
17
    /* split Adler-32 into component sums */
18
    sum2 = (adler >> 16) & 0xffff;
19
    adler &= 0xffff;
20
21
    /* in case user likes doing a byte at a time, keep it fast */
22
    if (len == 1) {
23
        adler += buf[0];
24
        if (adler >= BASE)
25
            adler -= BASE;
26
        sum2 += adler;
27
        if (sum2 >= BASE)
28
            sum2 -= BASE;
29
        return adler | (sum2 << 16);
30
    }
31
32
    /* initial Adler-32 value (deferred check for len == 1 speed) */
33
    if (buf == NULL)
34
        return 1L;
35
36
    /* in case short lengths are provided, keep it somewhat fast */
37
    if (len < 16) {
38
        while (len--) {
39
            adler += *buf++;
40
            sum2 += adler;
41
        }
42
        if (adler >= BASE)
43
            adler -= BASE;
44
        MOD28(sum2);            /* only added so many BASE's */
45
        return adler | (sum2 << 16);
46
    }
47
48
    /* do length NMAX blocks -- requires just one modulo operation */
49
    while (len >= NMAX) {
50
        len -= NMAX;
51
        n = NMAX / 16;          /* NMAX is divisible by 16 */
52
        do {
53
            DO16(buf);          /* 16 sums unrolled */
54
            buf += 16;
55
        } while (--n);
56
        MOD(adler);
57
        MOD(sum2);
58
    }
59
60
    /* do remaining bytes (less than NMAX, still just one modulo) */
61
    if (len) {                  /* avoid modulos if none remaining */
62
        while (len >= 16) {
63
            len -= 16;
64
            DO16(buf);
65
            buf += 16;
66
        }
67
        while (len--) {
68
            adler += *buf++;
69
            sum2 += adler;
70
        }
71
        MOD(adler);
72
        MOD(sum2);
73
    }
74
75
    /* return recombined sums */
76
    return adler | (sum2 << 16);
77
}

Initialisieren muss man den ja scheinbar nicht, denn im case "HEAD" 
steht:
1
            Tracev((stderr, "inflate:   zlib header ok\n"));
2
            strm->adler = state->check = adler32(0L, NULL, 0);

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Auf PC und Controller mit den gleichen Eingabedaten aufrufen, bei jedem 
Schritt die Zwischenergebnisse ausgeben und vergleichen? Möglicherweise 
ein Problem mit unportablem Integer Verhalten. Mal mit "-Wall -Wextra 
-pedantic" kompilieren, vielleicht findet der Compiler das ja sogar...

von Rangi J. (rangi)


Bewertung
1 lesenswert
nicht lesenswert
Habs gefunden!
ich hab die CRC des Chunks mit übergeben, also das zu bearbeitetende 
Array war 4 Bytes zu lange. Damit hat scheinbar der Adler ein Problem.
Jetzt gehts

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.