Libpng-Version 1.2.5


Home > Server Administration

Eine Beschreibung dafür, wie man libpng verwendet und modifiziert

Libpng-Version 1.2.5 - am 2. Oktober 2002
Aktualisiert und verteilt von Glenn Randers-Pehrson <[email protected]>
Copyright (c) 1998-2002 Glenn Randers-Pehrson
Für Bedingungen des Vertriebs und Gebrauches, sieh Urheberrechtsvermerk in png.h.

beruhend auf:

libpng 1.0 Version 0.96 des Betas 6 am 28. Mai 1997
Aktualisiert und verteilt von Andreas Dilger
Copyright (c) 1996, 1997 Andreas Dilger

libpng 1.0 Beta 2 - Version 0.88 am 26. Januar 1996
Für Bedingungen des Vertriebs und Gebrauches, sieh Urheberrechtsvermerk in png.h.
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.

Aktualisiert/umgeschrieben auf Anfrage in den libpng "häufig gestellten Fragen"
Copyright (c) 1995, 1996 Frank J. T. Wojcik
Am 18. Dezember 1995 & am 20. Januar 1996



I. Einführung

Diese Datei beschreibt, wie man verwendet und die PNG Präsenzbibliothek (bekannt als libpng) für Ihren eigenen Gebrauch modifiziert. Es gibt fünf Abteilungen zu dieser Datei: Einführung, Strukturen, das Lesen, das Schreiben, und die Modifizierung und die Konfiguration bemerken für verschiedene spezielle Plattformen. Zusätzlich zu dieser Datei ist example.c ein guter Startpunkt, um die Bibliothek zu verwenden, weil es schwer kommentiert wird und alles umfassen sollte, was die meisten Menschen brauchen werden. Wir nehmen an, dass libpng bereits installiert wird; sieh die INSTALLIEREN Datei für Instruktionen darauf, wie man libpng installiert.

Libpng wurde als ein Begleiter zur PNG Spezifizierung als eine Weise geschrieben, die Zeitdauer und Anstrengung zu reduzieren, die es bringt, um das PNG Dateiformat in Anwenderprogrammen zu unterstützen.

Die PNG-1.2 Spezifizierung ist an <http://www.libpng.org/pub/png> und an <ftp://ftp.uu.net/graphics/png/documents/> verfügbar.

Die PNG-1.0 Spezifizierung ist als RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/> und als eine W3C Empfehlung <http://www.w3.org/TR/REC.png.html> verfügbar. Einige zusätzliche Klötze werden in den Publikum-Klotz-Dokumenten des speziellen Zwecks an <ftp://ftp.uu.net/graphics/png/documents/> beschrieben.

Andere Information über PNG, und die letzte Version von libpng, können an der PNG Einstiegsseite, <http://www.libpng.org/pub/png/> und an <ftp://ftp.uu.net/graphics/png/> gefunden werden.

Die meisten Benutzer werden die Bibliothek bedeutsam nicht modifizieren müssen; fortgeschrittene Benutzer können es mehr modifizieren wollen. Alle Versuche wurden gemacht, es ebenso abgeschlossen wie möglich zu machen, indem sie den Code behielten, der leicht ist zu verstehen. Zurzeit wird diese Bibliothek nur Supports C. Support für andere Sprachen betrachtet.

Libpng ist entworfen worden, um vielfache Sitzungen auf einmal zu behandeln, leicht modifizierbar zu sein, zur großen Mehrheit von Maschinen (ANSI, K&R, 16-, 32-, und 64 Bit) verfügbar tragbar zu sein, und leicht zu sein, zu verwenden. Die äußerste Absicht von libpng ist, die Annahme des PNG Dateiformats auf beliebige mögliche Weise zu fördern. Während es noch zu tuende Arbeit gibt (sieh die TODO Datei), sollte libpng die Mehrheit der Bedürfnisse nach seinen Benutzern bedecken.

Libpng verwendet zlib für seine Kompression und Dekompression von PNG Dateien. Weitere Information über zlib, und die letzte Version von zlib, können an der zlib Einstiegsseite, <http://www.info-zip.org/pub/infozip/zlib/> gefunden werden. Das zlib Kompressionsdienstprogramm ist ein allgemeines Zweck-Dienstprogramm, das für mehr nützlich ist als PNG Dateien, und ohne libpng verwendet werden kann. Sieh die Dokumentation, die mit zlib für mehr Details geliefert ist. Sie können gewöhnlich die Ursprungsdateien für das zlib Dienstprogramm finden, wo auch immer Sie die libpng Ursprungsdateien finden.

Libpng ist Faden-Safe, vorausgesetzt dass die Fäden verschiedene Beispiele der Strukturen verwenden. Jeder Faden sollte seinen eigenen png_struct und png_info Beispiele, und so sein eigenes Image haben. Libpng schützt sich gegen zwei Fäden nicht, denselben Beispiel einer Struktur verwendend. Bemerken Sie: Faden-Sicherheit kann durch den Gebrauch von etwas vom MMX Assemblercode in pnggccrd.c vereitelt werden, der nur kompiliert wird, wenn der Benutzer PNG_THREAD_UNSAFE_OK definiert.

II. Strukturen

Es gibt zwei Hauptstrukturen, die für libpng, png_struct und png_info wichtig sind. Das erste, png_struct, ist eine interne Struktur, die größtenteils von einem Benutzer außer nicht verwendet wird, weil die erste Variable zu jedem libpng Funktionsaufruf ging.

Die png_info Struktur wird entworfen, um Auskunft über die PNG Datei zu geben. Auf einmal waren die Felder von png_info beabsichtigt, um für den Benutzer direkt zugänglich zu sein. Jedoch neigte das dazu, Probleme mit Anwendungen zu verursachen, die dynamisch geladene Bibliotheken verwenden, und infolgedessen wurde eine Reihe von Schnittstelle-Funktionen für png_info (der png_get_ * () und png_set_ * () Funktionen) entwickelt. Die Felder von png_info sind noch für ältere Anwendungen verfügbar, aber es wird darauf hingewiesen, dass Anwendungen die neuen Schnittstellen wenn überhaupt möglich verwenden.

Anwendungen, die wirklich direkten Zugriff den Mitgliedern von png_struct machen (abgesehen von png_ptr-> jmpbuf) müssen wiederkompiliert werden, wann auch immer die Bibliothek aktualisiert wird, und Anwendungen, die direkten Zugriff den Mitgliedern von png_info machen, wiederkompiliert werden müssen, wenn sie kompiliert oder mit der libpng Version 1.0.6 geladen wurden, in der die Mitglieder in einer verschiedenen Ordnung waren. In der Version 1.0.7 kehrten die Mitglieder der png_info Struktur zur alten Ordnung zurück, weil sie in Versionen 0.97c bis 1.0.5 waren. Mit der Version 2.0.0 anfangend, sind beide Strukturen dabei, verborgen zu werden, und der Inhalt der Strukturen wird nur durch die png_get/png_Set-Funktionen zugänglich sein.

Die png.h Kopfball-Datei ist eine unschätzbare Verweisung, um mit libpng zu programmieren. Und während ich zum Thema bin, stellen Sie sicher, dass Sie die libpng Kopfball-Datei umfassen:

   #include <png.h> 

III. Das Lesen

Wir werden Sie jetzt durch die möglichen Funktionen spazieren gehen zu rufen, indem wir in einer PNG Datei folgend kurz lesen werden, die Syntax und den Zweck von jedem erklärend. Sieh example.c und png.h für mehr Detail. Während das progressive Lesen in der folgenden Abteilung bedeckt wird, werden Sie noch einige der in dieser Abteilung besprochenen Funktionen brauchen, um eine PNG Datei zu lesen.

Einstellung

Sie werden die Eingabe/Ausgabe-Initialisierung (*) tun wollen, bevor Sie in libpng so kommen, wenn es nicht arbeitet, haben Sie viel nicht, um aufzumachen. Natürlich werden Sie auch versichern wollen, dass Sie SICH tatsächlich mit einer PNG Datei befassen. Libpng stellt eine einfache Kontrolle zur Verfügung, um zu sehen, ob eine Datei eine PNG Datei ist. Um es zu verwenden, gehen Sie in den ersten 1 bis 8 Bytes der Datei zur Funktion png_sig_cmp (), und es wird 0 zurückkehren, wenn die Bytes die entsprechenden Bytes der PNG Unterschrift, oder Nichtnull in anderer Weise vergleichen. Natürlich, je mehr Bytes Sie in, desto größer die Genauigkeit der Vorhersage gehen.

Wenn Sie vorhaben, den Dateiadressenverweis offen für den Gebrauch in libpng zu halten, müssen Sie sicherstellen, dass Sie mehr als 8 Bytes vom Anfang der Datei nicht lesen, und Sie auch einen Anruf png_set_sig_bytes_read () mit der Anzahl von Bytes machen müssen, die Sie vom Anfang lesen. Libpng wird dann nur die Bytes überprüfen (wenn irgendwelcher), den Ihr Programm nicht las.

(*): Wenn Sie die Standardeingabe/Ausgabe-Funktionen nicht verwenden, werden Sie sie durch kundenspezifische Funktionen ersetzen müssen. Sieh die Diskussion unter der Anpassung libpng.

 
    FILE *fp = fopen(file_name, "rb");
    if (!fp)
    {
        return (ERROR);
    }
    fread(header, 1, number, fp);
    is_png = !png_sig_cmp(header, 0, number);
    if (!is_png)
    {
        return (NOT_PNG);
    }

Dann müssen png_struct und png_info alloziert und initialisiert werden. Um sicherzustellen, dass die Größe dieser Strukturen sogar mit einem dynamisch verbundenen libpng richtig ist, gibt es Funktionen, die Strukturen zu initialisieren und zu allozieren. Wir passieren auch die Bibliotheksversion, optionalen Adressenverweise zu Fehlerbehandlungsfunktionen, und einen Adressenverweis zu Daten struct für den Gebrauch durch die Fehlerfunktionen nötigenfalls (der Adressenverweis, und Funktionen können UNGÜLTIG sein, wenn die Verzug-Fehlerbehandlungsprogramme verwendet werden sollen). Sieh die Abteilung auf Änderungen zu Libpng unter der Bewertung der alten Initialisierungsfunktionen. Die Struktur-Allozierungsfunktionen kehren ruhig UNGÜLTIG zurück, wenn sie scheitern, die Struktur zu schaffen, so sollte Ihre Anwendung dafür überprüfen.

     png_structp png_ptr = png_create_read_struct
       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
        user_error_fn, user_warning_fn);
    if (!png_ptr)
        return (ERROR);

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr,
           (png_infopp)NULL, (png_infopp)NULL);
        return (ERROR);
    }

    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
        png_destroy_read_struct(&png_ptr, &info_ptr,
          (png_infopp)NULL);
        return (ERROR);
    }

Wenn Sie Ihre eigenen Arbeitsspeicherzuweisungsroutinen verwenden wollen, PNG_USER_MEM_SUPPORTED zu definieren und png_create_read_struct_2 () statt png_create_read_struct () zu verwenden:

 png_structp png_ptr = png_create_read_struct_2
       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
        user_error_fn, user_warning_fn, (png_voidp)
        user_mem_ptr, user_malloc_fn, user_free_fn);

Die Fehlerbehandlungsroutinen gingen zu png_create_read_struct (), und der Speicher alloc/free Routinen ging zu png_create_struct_2 () sind nur notwendig, wenn Sie gelieferte Fehlerbehandlung des libpng und Speicher alloc/free Funktionen nicht verwenden.

Wenn libpng auf einen Fehler stößt, erwartet er zu longjmp zurück zu Ihrer Routine. Deshalb werden Sie setjmp nennen und Ihren png_jmpbuf (png_ptr) passieren müssen. Wenn Sie die Datei von verschiedenen Routinen lesen, werden Sie das jmpbuf Feld jedes Mal aktualisieren müssen, wenn Sie eine neue Routine eingeben, die einen png_ * () Funktion nennen wird.

Sieh Ihre Dokumentation von setjmp/longjmp für Ihren Bearbeiter für weitere Informationen über setjmp/longjmp. Sieh die Diskussion über die libpng Fehlerbehandlung in der Anpassung Libpng Abteilung unten für weitere Informationen über die libpng Fehlerbehandlung. Wenn ein Fehler, und libpng longjmp's zurück zu Ihrem setjmp vorkommt, werden Sie png_destroy_read_struct () nennen wollen, um jeden Speicher zu befreien.

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr,
           &end_info);
        fclose(fp);
        return (ERROR);

Wenn Sie die Kompliziertheit von setjmp/Longjmp-Problemen lieber vermeiden möchten, können Sie libpng mit PNG_SETJMP_NOT_SUPPORTED kompilieren, in welchem Fall Fehler auf einen Anruf zu PNG_ABORT () welch Verzug hinauslaufen werden () abzubrechen.

Jetzt müssen Sie den Eingangscode aufstellen. Der Verzug für libpng soll die C-Funktion fread () verwenden. Wenn Sie das verwenden, werden Sie eine gültige DATEI * in der Funktion png_init_io () passieren müssen. Seien Sie überzeugt, dass die Datei in der binären Weise geöffnet wird. Wenn Sie Lesen-Daten auf eine andere Weise behandeln möchten, brauchen Sie nicht den png_init_io () Funktion zu nennen, aber Sie müssen dann die libpng Eingabe/Ausgabe-Methoden durchführen, die in der Anpassung Libpng Abteilung unten besprochen sind.

    png_init_io(png_ptr, fp);

Wenn Sie vorher die Datei geöffnet und einige der Unterschrift vom Anfang gelesen hatten, um zu sehen, ob das eine PNG Datei war, müssen Sie libpng mitteilen, dass es einige Bytes gibt, die vom Anfang der Datei fehlen.

        png_set_sig_bytes(png_ptr, number);

Aufstellung des Rückrufaktionscodes

Sie können eine Rückrufaktionsfunktion aufstellen, irgendwelche unbekannten Klötze im Eingabedatenstrom zu behandeln. Sie müssen die Funktion liefern

  read_chunk_callback(png_ptr ptr,
         png_unknown_chunkp chunk);
    {
       /* The unknown chunk structure contains your
          chunk data: */
           png_byte name[5];
           png_byte *data;
           png_size_t size;
       /* Note that libpng has already taken care of
          the CRC handling */

       /* put your code here.  Return one of the
          following: */

       return (-n); /* chunk had an error */
       return (0); /* did not recognize */
       return (n); /* success */
    }

(Sie können Ihrer Funktion einen anderen Namen geben, den Sie statt "read_chunk_callback" mögen)

Um libpng über Ihre Funktion zu informieren, verwenden

    png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
        read_chunk_callback);
 

Das nennt nicht nur die Rückrufaktionsfunktion, sondern auch einen Benutzeradressenverweis, mit dem Sie abrufen können

    png_get_user_chunk_ptr(png_ptr);

An diesem Punkt können Sie eine Rückrufaktionsfunktion aufstellen, die genannt wird, nachdem jede Reihe gelesen worden ist, den Sie verwenden können, um einen Fortschritt-Meter oder das ähnliche zu kontrollieren. Es wird in pngtest.c demonstriert. Sie müssen eine Funktion liefern

    void read_row_callback(png_ptr ptr, png_uint_32 row,
       int pass);
    {
      /* put your code here */
    }

(Sie können ihm einen anderen Namen geben, den Sie statt "read_row_callback" mögen)

Um libpng über Ihre Funktion zu informieren, verwenden

       png_set_read_status_fn(png_ptr, read_row_callback);

Das Berühren des unbekannten Klotzes

Jetzt kommen Sie, um den Weg zu setzen, wie die Bibliothek unbekannte Klötze im Eingang PNG Strom bearbeitet. Sowohl bekannte als auch unbekannte Klötze werden gelesen. Normales Verhalten besteht darin, dass bekannte Klötze in die Information in verschiedenen info_ptr Mitgliedern grammatisch analysiert werden; unbekannte Klötze werden verworfen. Um das zu ändern, können Sie rufen:

    png_set_keep_unknown_chunks(png_ptr, info_ptr, keep,
        chunk_list, num_chunks);
    keep       - 0: do not keep
                 1: keep only if safe-to-copy
                 2: keep even if unsafe-to-copy
    chunk_list - list of chunks affected (a byte string,
                 five bytes per chunk, NULL or '\0' if
                 num_chunks is 0)
    num_chunks - number of chunks affected; if 0, all
                 unknown chunks are affected

Unbekannte Klötze erklärt werden auf diese Weise als Ausgangsdaten auf eine Liste von png_unknown_chunk Strukturen gespeichert. Wenn ein Klotz, der normalerweise zu libpng bekannt ist, in der Liste genannt wird, wird es als unbekannt gemäß der "behalten" Direktive behandelt. Wenn ein Klotz in aufeinander folgenden Beispielen von png_set_keep_unknown_chunks genannt wird (), wird der Endbeispiel den Vortritt haben.

Die gelesene Schnittstelle auf höchster Ebene

An diesem Punkt gibt es zwei Wege weiterzugehen; durch die gelesene Schnittstelle auf höchster Ebene, oder durch eine Folge von auf niedriger Stufe Lesevorgängen. Sie können die Schnittstelle auf höchster Ebene verwenden, wenn (a) Sie sind bereit, das komplette Image in den Speicher, und (den b) die Eingangstransformationen zu lesen, die Sie tun wollen, werden auf den folgenden Satz beschränkt:

    PNG_TRANSFORM_IDENTITY      No transformation
    PNG_TRANSFORM_STRIP_16      Strip 16-bit samples to
                                8 bits
    PNG_TRANSFORM_STRIP_ALPHA   Discard the alpha channel
    PNG_TRANSFORM_PACKING       Expand 1, 2 and 4-bit
                                samples to bytes
    PNG_TRANSFORM_PACKSWAP      Change order of packed
                                pixels to LSB first
    PNG_TRANSFORM_EXPAND        Perform set_expand()
    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
    PNG_TRANSFORM_SHIFT         Normalize pixels to the
                                sBIT depth
    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA
                                to BGRA
    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA
                                to AG
    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity
                                to transparency
    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples

(Das schließt das Setzen einer Hintergrundfarbe, Tun der Gammatransformation, Dithering, und Setzen des Füllers aus.), Wenn das einfach der Fall ist, tun Sie das:

 
    png_read_png(png_ptr, info_ptr, png_transforms, NULL)

wo png_transforms eine ganze Zahl ist, die das logische ODER von einem Satz von Transformationsfahnen enthält. Dieser Anruf ist zu png_read_info gleichwertig (), folgte dem Satz von Transformationen, die durch die umgestalten Maske, dann png_read_image (), und schließlich png_read_end () angezeigt sind.

(Der Endparameter dieses Anrufs wird noch nicht verwendet. Eines Tages könnte es zu durch einen zukünftigen Eingang erforderlichen Transformationsparametern hinweisen verwandeln sich.)

Nachdem Sie png_read_png genannt haben (), können Sie die Bilddaten damit abrufen

     row_pointers = png_get_rows(png_ptr, info_ptr);

wo row_pointers eine Reihe von Adressenverweisen zu den Pixel-Daten für jede Reihe ist:

   png_bytep row_pointers[height];

Wenn Sie Ihre Bildgröße und Pixel-Größe vorzeitig wissen, können Sie row_pointers vor dem Benennen png_read_png () damit allozieren

      row_pointers = png_malloc(png_ptr,
      height*sizeof(png_bytep));
   for (int i=0; i<height, i++)
      row_pointers[i]=png_malloc(png_ptr,
         width*pixel_size);
   png_set_rows(png_ptr, info_ptr, &row_pointers);

Wechselweise konnten Sie Ihr Image in einem großem Block allozieren und row_pointers [ich] definieren, um in die richtigen Plätze in Ihrem Block hinzuweisen.

Wenn Sie png_set_rows verwenden (), ist die Anwendung dafür verantwortlich, row_pointers zu befreien (und row_pointers [ich], wenn sie getrennt alloziert wurden).

Wenn Sie row_pointers vorzeitig nicht allozieren, png_read_png () wird es tun, und es wird free'ed sein, wenn Sie png_destroy_ * () nennen.

Die auf niedriger Stufe gelesene Schnittstelle

Wenn Sie die auf niedriger Stufe Route gehen, sind Sie jetzt bereit, die ganze Dateiinformation bis zu den wirklichen Bilddaten zu lesen. Sie tun das mit einem Anruf png_read_info ().

   png_read_info(png_ptr, info_ptr);

Das wird alle Klötze bis zu, aber nicht einschließlich der Bilddaten bearbeiten.

Das Abfragen der Info-Struktur

Funktionen werden verwendet, um die Information vom info_ptr zu bekommen, sobald es gelesen worden ist. Bemerken Sie, dass diese Felder nicht völlig ausgefüllt werden dürfen, bis png_read_end () hat die Klotz-Daten im Anschluss an das Image gelesen.

  png_get_IHDR(png_ptr, info_ptr, &width, &height,
       &bit_depth, &color_type, &interlace_type,
       &compression_type, &filter_method);

    width          - holds the width of the image
                     in pixels (up to 2^31).
    height         - holds the height of the image
                     in pixels (up to 2^31).
    bit_depth      - holds the bit depth of one of the
                     image channels.  (valid values are
                     1, 2, 4, 8, 16 and depend also on
                     the color_type.  See also
                     significant bits (sBIT) below).
    color_type     - describes which color/alpha channels
                         are present.
                     PNG_COLOR_TYPE_GRAY
                        (bit depths 1, 2, 4, 8, 16)
                     PNG_COLOR_TYPE_GRAY_ALPHA
                        (bit depths 8, 16)
                     PNG_COLOR_TYPE_PALETTE
                        (bit depths 1, 2, 4, 8)
                     PNG_COLOR_TYPE_RGB
                        (bit_depths 8, 16)
                     PNG_COLOR_TYPE_RGB_ALPHA
                        (bit_depths 8, 16)

                     PNG_COLOR_MASK_PALETTE
                     PNG_COLOR_MASK_COLOR
                     PNG_COLOR_MASK_ALPHA

    filter_method  - (must be PNG_FILTER_TYPE_BASE
                     for PNG 1.0, and can also be
                     PNG_INTRAPIXEL_DIFFERENCING if
                     the PNG datastream is embedded in
                     a MNG-1.0 datastream)
    compression_type - (must be PNG_COMPRESSION_TYPE_BASE
                     for PNG 1.0)
    interlace_type - (PNG_INTERLACE_NONE or
                     PNG_INTERLACE_ADAM7)
    Any or all of interlace_type, compression_type, of
    filter_method can be NULL if you are
    not interested in their values.

    channels = png_get_channels(png_ptr, info_ptr);
    channels       - number of channels of info for the
                     color type (valid values are 1 (GRAY,
                     PALETTE), 2 (GRAY_ALPHA), 3 (RGB),
                     4 (RGB_ALPHA or RGB + filler byte))
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    rowbytes       - number of bytes needed to hold a row

    signature = png_get_signature(png_ptr, info_ptr);
    signature      - holds the signature read from the
                     file (if any).  The data is kept in
                     the same offset it would be if the
                     whole signature were read (i.e. if an
                     application had already read in 4
                     bytes of signature before starting
                     libpng, the remaining 4 bytes would
                     be in signature[4] through signature[7]
                     (see png_set_sig_bytes())).


    width            = png_get_image_width(png_ptr,
                         info_ptr);
    height           = png_get_image_height(png_ptr,
                         info_ptr);
    bit_depth        = png_get_bit_depth(png_ptr,
                         info_ptr);
    color_type       = png_get_color_type(png_ptr,
                         info_ptr);
    filter_method    = png_get_filter_type(png_ptr,
                         info_ptr);
    compression_type = png_get_compression_type(png_ptr,
                         info_ptr);
    interlace_type   = png_get_interlace_type(png_ptr,
                         info_ptr);

Diese sind auch wichtig, aber ihre Gültigkeit hängt ab, ob der Klotz gelesen worden ist. Der png_get_valid (png_ptr, info_ptr, PNG_INFO _ <Klotz>) und png_get _ <Klotz> (png_ptr, info_ptr...) geben Funktionen Nichtnull zurück, wenn die Daten, oder Null gelesen worden sind, wenn es vermisst wird. Die Parameter zum png_get _ <Klotz> werden direkt aufgestellt, wenn sie einfache Datentypen sind, oder ein Adressenverweis in den info_ptr für irgendwelche komplizierten Typen zurückgegeben wird.

 png_get_PLTE(png_ptr, info_ptr, &palette,
                     &num_palette);
    palette        - the palette for the file
                     (array of png_color)
    num_palette    - number of entries in the palette

    png_get_gAMA(png_ptr, info_ptr, &gamma);
    gamma          - the gamma the file is written
                     at (PNG_INFO_gAMA)

    png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
    srgb_intent    - the rendering intent (PNG_INFO_sRGB)
                     The presence of the sRGB chunk
                     means that the pixel data is in the
                     sRGB color space.  This chunk also
                     implies specific values of gAMA and
                     cHRM.

    png_get_iCCP(png_ptr, info_ptr, &name,
       &compression_type, &profile, &proflen);
    name            - The profile name.
    compression     - The compression type; always
                      PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
                      You may give NULL to this argument to
                      ignore it.
    profile         - International Color Consortium color
                      profile data. May contain NULs.
    proflen         - length of profile data in bytes.

    png_get_sBIT(png_ptr, info_ptr, &sig_bit);
    sig_bit        - the number of significant bits for
                     (PNG_INFO_sBIT) each of the gray,
                     red, green, and blue channels,
                     whichever are appropriate for the
                     given color type (png_color_16)

    png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
                     &trans_values);
    trans          - array of transparent entries for
                     palette (PNG_INFO_tRNS)
    trans_values   - graylevel or color sample values of
                     the single transparent color for
                     non-paletted images (PNG_INFO_tRNS)
    num_trans      - number of transparent entries
                     (PNG_INFO_tRNS)

    png_get_hIST(png_ptr, info_ptr, &hist);
                     (PNG_INFO_hIST)
    hist           - histogram of palette (array of
                     png_uint_16)

    png_get_tIME(png_ptr, info_ptr, &mod_time);
    mod_time       - time image was last modified
                    (PNG_VALID_tIME)

    png_get_bKGD(png_ptr, info_ptr, &background);
    background     - background color (PNG_VALID_bKGD)
                     valid 16-bit red, green and blue
                     values, regardless of color_type

    num_comments   = png_get_text(png_ptr, info_ptr,
                     &text_ptr, &num_text);
    num_comments   - number of comments
    text_ptr       - array of png_text holding image
                     comments
    text_ptr[i].compression - type of compression used
                 on "text" PNG_TEXT_COMPRESSION_NONE
                           PNG_TEXT_COMPRESSION_zTXt
                           PNG_ITXT_COMPRESSION_NONE
                           PNG_ITXT_COMPRESSION_zTXt
    text_ptr[i].key   - keyword for comment.  Must contain
                         1-79 characters.
    text_ptr[i].text  - text comments for current
                         keyword.  Can be empty.
    text_ptr[i].text_length - length of text string,
                 after decompression, 0 for iTXt
    text_ptr[i].itxt_length - length of itxt string,
                 after decompression, 0 for tEXt/zTXt
    text_ptr[i].lang  - language of comment (empty
                         string for unknown).
    text_ptr[i].lang_key  - keyword in UTF-8
                         (empty string for unknown).
    num_text       - number of comments (same as
                     num_comments; you can put NULL here
                     to avoid the duplication)
    Note while png_set_text() will accept text, language,
    and translated keywords that can be NULL pointers, the
    structure returned by png_get_text will always contain
    regular zero-terminated C strings.  They might be
    empty strings but they will never be NULL pointers.

    num_spalettes = png_get_sPLT(png_ptr, info_ptr,
       &palette_ptr);
    palette_ptr    - array of palette structures holding
                     contents of one or more sPLT chunks
                     read.
    num_spalettes  - number of sPLT chunks read.

    png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y,
       &unit_type);
    offset_x       - positive offset from the left edge
                     of the screen
    offset_y       - positive offset from the top edge
                     of the screen
    unit_type      - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER

    png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y,
       &unit_type);
    res_x          - pixels/unit physical resolution in
                     x direction
    res_y          - pixels/unit physical resolution in
                     x direction
    unit_type      - PNG_RESOLUTION_UNKNOWN,
                     PNG_RESOLUTION_METER

    png_get_sCAL(png_ptr, info_ptr, &unit, &width,
       &height)
    unit        - physical scale units (an integer)
    width       - width of a pixel in physical scale units
    height      - height of a pixel in physical scale units
                 (width and height are doubles)

    png_get_sCAL_s(png_ptr, info_ptr, &unit, &width,
       &height)
    unit        - physical scale units (an integer)
    width       - width of a pixel in physical scale units
    height      - height of a pixel in physical scale units
                 (width and height are strings like "2.54")

    num_unknown_chunks = png_get_unknown_chunks(png_ptr,
       info_ptr, &unknowns)
    unknowns          - array of png_unknown_chunk
                        structures holding unknown chunks
    unknowns[i].name  - name of unknown chunk
    unknowns[i].data  - data of unknown chunk
    unknowns[i].size  - size of unknown chunk's data
    unknowns[i].location - position of chunk in file

    The value of "i" corresponds to the order in which the
    chunks were read from the PNG file or inserted with the
    png_set_unknown_chunks() function.

Die Daten vom pHYs Klotz können in mehreren günstigen Formen abgerufen werden:

    res_x = png_get_x_pixels_per_meter(png_ptr,
       info_ptr)
    res_y = png_get_y_pixels_per_meter(png_ptr,
       info_ptr)
    res_x_and_y = png_get_pixels_per_meter(png_ptr,
       info_ptr)
    res_x = png_get_x_pixels_per_inch(png_ptr,
       info_ptr)
    res_y = png_get_y_pixels_per_inch(png_ptr,
       info_ptr)
    res_x_and_y = png_get_pixels_per_inch(png_ptr,
       info_ptr)
    aspect_ratio = png_get_pixel_aspect_ratio(png_ptr,
       info_ptr)

   (Each of these returns 0 [signifying "unknown"] if
       the data is not present or if res_x is 0;
       res_x_and_y is 0 if res_x != res_y)

Die Daten vom oFFs Klotz können in mehreren günstigen Formen abgerufen werden:

   x_offset = png_get_x_offset_microns(png_ptr, info_ptr);
    y_offset = png_get_y_offset_microns(png_ptr, info_ptr);
    x_offset = png_get_x_offset_inches(png_ptr, info_ptr);
    y_offset = png_get_y_offset_inches(png_ptr, info_ptr);

   (Each of these returns 0 [signifying "unknown" if both
       x and y are 0] if the data is not present or if the
       chunk is present but the unit is the pixel)

Für mehr Information, sieh die png_info Definition in png.h und der PNG Spezifizierung für den Klotz-Inhalt. Seien Sie mit dem Vertrauen rowbytes sorgfältig, weil einige der Transformationen zunehmen konnten, musste der Raum halten eine Reihe (dekomprimieren Sie Füller, gray_to_rgb, usw.). Sieh png_read_update_info () unten.

Ein schnelles Wort über text_ptr und num_text. PNG speichert Anmerkungen in Paaren des Schlüsselwortes/Textes, einem Paar pro Klotz, ohne Grenze auf der Anzahl von Textklötzen, und eine 2^31-Byte-Grenze auf ihrer Größe. Während dort Schlüsselwörter angedeutet werden, gibt es keine Voraussetzung, um den Gebrauch auf diese Schnuren einzuschränken. Es wird stark darauf hingewiesen, dass Schlüsselwörter und Text Menschen (das ist die Frage!) vernünftig sind, verwenden Sie Abkürzungen so nicht. Nicht bedruckbaren Symbolen wird nicht erlaubt. Sieh die PNG Spezifizierung für mehr Details. Es gibt auch keine Voraussetzung, um Text nach dem Schlüsselwort zu haben.

Schlüsselwörter sollten auf 79 lateinische 1 Zeichen beschränkt werden ohne zu führen oder nachfolgende Leerzeichen, aber Nichtkonsekutivräumen wird innerhalb des Schlüsselwortes erlaubt. Es ist möglich, dasselbe Schlüsselwort jede Anzahl von Zeiten zu haben. Der text_ptr ist eine Reihe von png_text Strukturen, jeder, einen Adressenverweis zu einer Sprachschnur, einen Adressenverweis zu einem Schlüsselwort und einen Adressenverweis zu einer Textfolge haltend. Die Textfolge, der Sprachcode, und das übersetzte Schlüsselwort können leere oder UNGÜLTIGE Adressenverweise sein. Die Paare des Schlüsselwortes/Textes werden in die Reihe in der Ordnung gebracht, dass sie erhalten werden. Jedoch können einige oder alle Textklötze sein nach dem Image, um so sich zu überzeugen, haben Sie alle Textklötze gelesen, panschen Sie mit diesen nicht, bis Sie das Zeug nach dem Image lesen. Das wird wieder unten in der Diskussion erwähnt, die mit png_read_end () geht.

Eingangstransformationen

Nachdem Sie die Kopfball-Information gelesen haben, können Sie die Bibliothek aufstellen, um irgendwelche speziellen Transformationen der Bilddaten zu behandeln. Die verschiedenen Wege, die Daten umzugestalten, werden in der Ordnung beschrieben, dass sie vorkommen sollten. Das ist wichtig, weil einige von diesen den Farbentyp and/or Bit-Tiefe der Daten ändern, und einige andere nur an bestimmten Farbentypen und Bit-Tiefen arbeiten. Wenn auch jede Transformation überprüft, um zu sehen, ob sie Daten hat, mit denen sie etwas tun kann, sollten Sie sich überzeugen, um nur eine Transformation zu ermöglichen, wenn es für die Daten gültig sein wird. Tauschen Sie zum Beispiel rot und blau auf grayscale Daten nicht.

Die Farben, die für den Hintergrund und die Durchsichtigkeitswerte verwendet sind, sollten in demselben Format/Tiefe wie die gegenwärtigen Bilddaten geliefert werden. Sie werden in demselben Format/Tiefe wie die Bilddaten in einem bKGD oder tRNS Klotz gespeichert, so ist das, welcher libpng dafür Daten erwartet. Die Farben werden umgestaltet, um synchron mit den Bilddaten zu bleiben, wenn eine Anwendung den png_read_update_info () Routine (sieh unten) nennt.

Daten werden in die gelieferten in Bytes gepackten Reihe-Puffer decodiert es sei denn, dass die Bibliothek gesagt worden ist, es in ein anderes Format umzugestalten. Zum Beispiel werden 4 Bit/Pixel paletted oder grayscale Daten 2 Pixel/Byte mit dem leftmost Pixel in den höherwertigen Bit des Bytes zurückgegeben, es sei denn, dass png_set_packing () genannt wird. RGB 8-Bit-Daten werden in RGB RGB RGB Format gespeichert es sei denn, dass png_set_filler () genannt wird, um Füllzeichen entweder vorher oder nach jedem RGB Drilling einzufügen. RGB 16-Bit-Daten werden RRGGBB RRGGBB mit dem bedeutendsten Byte des Farbwerts zuerst zurückgegeben, es sei denn, dass png_set_strip_16 () genannt wird, um es in regelmäßigen RGB RGB Drillinge umzugestalten, oder png_set_filler () genannt wird, um Füllzeichen entweder vorher oder nach jedem RRGGBB Drilling einzufügen. Ähnlich können 8 Bit oder 16 Bit grayscale Daten mit png_set_filler () oder png_set_strip_16 () modifiziert werden.

Der folgende Code gestaltet grayscale Images von weniger als 8 bis 8 Bit um, ändert paletted Images zu RGB, und fügt einen vollen Alfakanal hinzu, wenn es Durchsichtigkeitsinformation in einem tRNS Klotz gibt. Das ist auf grayscale Images mit Bit-Tiefen 2 oder 4 am nützlichsten, oder wenn es eine Vielfach-Bildbetrachtungsanwendung gibt, die alle Images ebenso behandeln möchte.

   if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);

    if (color_type == PNG_COLOR_TYPE_GRAY &&
        bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);

    if (png_get_valid(png_ptr, info_ptr,
        PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);

Diese drei Funktionen sind wirklich Decknamen für png_set_expand (), hinzugefügt in der libpng Version 1.0.4 mit den Funktionsnamen, die dekomprimiert sind, um Codelesbarkeit zu verbessern. In einer zukünftigen Version können sie wirklich verschiedene Sachen machen.

PNG kann Dateien mit 16 Bit pro Kanal haben. Wenn Sie nur 8 Bit pro Kanal behandeln können, wird das die Pixel unten zu 8 Bit abziehen.

if (bit_depth == 16)
        png_set_strip_16(png_ptr);

Wenn, aus irgendeinem Grund, Sie den Alfakanal auf einem Image nicht brauchen, und Sie ihn entfernen wollen, anstatt ihn mit dem Hintergrund zu verbinden (aber der Bildautor hatte sicher das Sie im Sinn, verbinden *would* ihn mit dem Hintergrund, so ist es, was Sie wahrscheinlich tun sollten):

     if (color_type & PNG_COLOR_MASK_ALPHA)
        png_set_strip_alpha(png_ptr);
 

In PNG Dateien ist der Alfakanal in einem Image das Niveau der Undurchsichtigkeit. Wenn Sie den Alfakanal in einem Image brauchen, um das Niveau der Durchsichtigkeit statt der Undurchsichtigkeit zu sein, können Sie den Alfakanal umkehren (oder die tRNS Klotz-Daten), nachdem es gelesen wird, so dass 0 völlig undurchsichtig ist und 255 (in 8 Bit oder paletted Images) oder 65535 (in 16 Bitbildern), damit völlig durchsichtig ist

    png_set_invert_alpha(png_ptr);

PNG Dateien packen Pixel von Bit-Tiefen 1, 2, und 4 in ebenso kleine Bytes ein, wie sie können, zum Beispiel, 8 Pixel pro Byte für 1-Bit-Dateien hinauslaufend. Dieser Code dekomprimiert zu 1 Pixel pro Byte, ohne die Werte der Pixel zu ändern:

    if (bit_depth < 8)
        png_set_packing(png_ptr);

PNG Dateien haben mögliche Bit-Tiefen 1, 2, 4, 8, und 16. Alle in einem PNG Image gespeicherten Pixel sind "erklettert" oder bis zum folgenden höher mögliche Bit-Tiefe (z.B von 5 Bit/Probe in der Reihe [0,31] zu 8 Bit/Probe in der Reihe [0, 255]) "ausgewechselt" "worden". Jedoch ist es auch möglich, die PNG Pixel-Daten zurück zur ursprünglichen Bit-Tiefe des Images umzuwandeln. Dieser Anruf nimmt ab die Pixel treten zur ursprünglichen Bit-Tiefe zurück:

     png_color_8p sig_bit;

    if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
        png_set_shift(png_ptr, sig_bit);

PNG Dateien speichern 3-farbige Pixel in der roten, grünen, blauen Ordnung. Dieser Code ändert die Speicherung der Pixel zu blau, grün, rot:

    if (color_type == PNG_COLOR_TYPE_RGB ||
        color_type == PNG_COLOR_TYPE_RGB_ALPHA)
        png_set_bgr(png_ptr);

PNG Dateien speichern RGB in 3 oder 6 Bytes gepackte Pixel. Dieser Code dekomprimiert sie in 4 oder 8 Bytes für Fenstertechnik-Systeme, die sie in diesem Format brauchen:

    if (color_type == PNG_COLOR_TYPE_RGB)
        png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE);

wo "Füller" die 8 oder 16 Bit-Anzahl ist, um sich mit zu füllen, und die Speicherstelle entweder PNG_FILLER_BEFORE oder PNG_FILLER_AFTER, abhängig davon ist, ob Sie den Füller vor dem RGB oder danach wollen. Diese Transformation betrifft Images nicht, die bereits volle Alfakanäle haben. Um einen undurchsichtigen Alfakanal hinzuzufügen, verwenden Sie filler=0xff oder 0xffff und PNG_FILLER_AFTER, der RGBA Pixel erzeugen wird.

Wenn Sie ein Image mit einem Alfakanal lesen, und Sie die Daten brauchen, weil ARGB statt des normalen PNG RGBA formatieren:

    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
        png_set_swap_alpha(png_ptr);

Für etwas Gebrauch können Sie wollen, dass ein grayscale Image als RGB vertreten wird. Dieser Code wird diese Konvertierung tun:

    if (color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
          png_set_gray_to_rgb(png_ptr);

Umgekehrt können Sie einen RGB oder RGBA Image zu grayscale oder grayscale mit dem Alpha umwandeln.

    if (color_type == PNG_COLOR_TYPE_RGB ||
        color_type == PNG_COLOR_TYPE_RGB_ALPHA)
          png_set_rgb_to_gray_fixed(png_ptr, error_action,
             int red_weight, int green_weight);

    error_action = 1: silently do the conversion
    error_action = 2: issue a warning if the original
                      image has any pixel where
                      red != green or red != blue
    error_action = 3: issue an error and abort the
                      conversion if the original
                      image has any pixel where
                      red != green or red != blue

    red_weight:       weight of red component times 100000
    green_weight:     weight of green component times 100000
                      If either weight is negative, default
                      weights (21268, 71514) are used.

Wenn Sie error_action = 1 oder 2 gesetzt haben, können Sie später überprüfen, ob das Image wirklich, nach der Verarbeitung der Bildreihen, mit dem png_get_rgb_to_gray_status (png_ptr) Funktion grau war. Es wird einen png_byte zurückgeben, der Null ist, wenn das Image grau war oder 1, wenn es irgendwelche nichtgrauen Pixel gab. bKGD und sBIT Daten werden zu grayscale still umgewandelt, die grünen Kanaldaten unabhängig von der error_Action-Einstellung verwendend.

Mit red_weight+green_weight <=100000 wird der normalisierte graylevel geschätzt:

    int rw = red_weight * 65536;
    int gw = green_weight * 65536;
    int bw = 65536 - (rw + gw);
    gray = (rw*red + gw*green + bw*blue)/65536;

Die Ausgangsparameter kommen denjenigen näher, die in den häufig gestellten Farbenfragen von Charles Poynton, <http://www.inforamp.net / ~ poynton/> Copyright (c) 1998-01-04 Charles Poynton [email protected] empfohlen sind

    Y = 0.212671 * R + 0.715160 * G + 0.072169 * B

Libpng kommt dem damit näher

    Y = 0.21268 * R + 0.7151 * G + 0.07217 * B 

der mit ganzen Zahlen als ausgedrückt werden kann

    Y = (6969 * R + 23434 * G + 2365 * B)/32768 

Die Berechnung wird in einem geradlinigen colorspace getan, wenn das Bildgamma bekannt ist.

Wenn Sie einen grayscale haben und Sie png_set_expand_depth (), png_set_expand (), oder png_set_gray_to_rgb verwenden, um sich zu truecolor oder zu einer höheren Bit-Tiefe zu ändern, müssen Sie entweder die Hintergrundfarbe als ein grauer Wert an der ursprünglichen Dateibit-Tiefe (need_expand = 1) oder Versorgung die Hintergrundfarbe als ein RGB Drilling an der endgültigen, dekomprimierten Bit-Tiefe (need_expand = 0) liefern. Ähnlich, wenn Sie ein paletted Image lesen, müssen Sie entweder die Hintergrundfarbe als ein Palette-Index (need_expand = 1) oder als ein RGB Drilling liefern, der kann oder in der Palette (need_expand = 0) nicht sein kann.

 png_color_16 my_background;
    png_color_16p image_background;

    if (png_get_bKGD(png_ptr, info_ptr, &image_background))
        png_set_background(png_ptr, image_background,
          PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    else
        png_set_background(png_ptr, &my_background,
          PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);

Der png_set_background () Funktion erzählt libpng zu zerlegbaren Images mit dem Alpha oder der einfachen Durchsichtigkeit gegen die gelieferte Hintergrundfarbe. Wenn die PNG Datei einen bKGD Klotz enthält (gültiger PNG_INFO_bKGD), können Sie diese Farbe verwenden, oder eine andere für die gegenwärtige Anzeige passendere Farbe (z.B, die Hintergrundfarbe von einer Webseite) liefern. Sie müssen libpng erzählen, ob die Farbe im Gammaraum der Anzeige ist (PNG_BACKGROUND_GAMMA_SCREEN für Farben, die Sie liefern), die Datei (PNG_BACKGROUND_GAMMA_FILE für Farben vom bKGD Klotz), oder derjenige, der kein dieser Gammas ist (PNG_BACKGROUND_GAMMA_UNIQUE - weiß ich nicht, warum irgendjemand das verwenden würde, aber es ist hier).

Um PNG Images auf jeder Art des Systems richtig anzuzeigen, muss die Anwendung wissen, wie das Anzeige-Gamma ist. Ideal wird der Benutzer das wissen, und die Anwendung wird ihnen erlauben, es zu setzen. Eine Methode, dem Benutzer zu erlauben, das Anzeige-Gamma getrennt für jedes System zu setzen, soll für einen SCREEN_GAMMA oder DISPLAY_GAMMA Umgebungsvariable überprüfen, die hoffentlich richtig gesetzt wird.

Bemerken Sie, dass display_gamma die gesamte Gammakorrektur ist, die erforderlich ist, angenehme Ergebnisse zu produzieren, der von den Lichtverhältnissen in der Umgebungsumgebung abhängt. In einem dunklen oder hell angezündeten Zimmer ist keine Entschädigung außer der physischen Gammahochzahl des Monitors erforderlich, während in einem dunklen Zimmer eine ein bisschen kleinere Hochzahl besser ist.

  double gamma, screen_gamma;

   if (/* We have a user-defined screen
       gamma value */)
   {
      screen_gamma = user_defined_screen_gamma;
   }
   /* One way that applications can share the same
      screen gamma value */
   else if ((gamma_str = getenv("SCREEN_GAMMA"))
      != NULL)
   {
      screen_gamma = (double)atof(gamma_str);
   }
   /* If we don't have another value */
   else
   {
      screen_gamma = 2.2; /* A good guess for a
           PC monitor in a bright office or a dim room */
      screen_gamma = 2.0; /* A good guess for a
           PC monitor in a dark room */
      screen_gamma = 1.7 or 1.0;  /* A good
           guess for Mac systems */
   }

Die png_set_gamma () fungieren Griff-Gammatransformationen der Daten. Passieren Sie sowohl das Dateigamma als auch den Strom screen_gamma. Wenn die Datei einen Gammawert nicht hat, können Sie denjenigen irgendwie passieren, wenn Sie eine Idee haben, was es ist (gewöhnlich 0.45455, ist eine gute Annahme für GIF-Images auf PCs). Bemerken Sie, dass Dateigammas von Bildschirm-Gammas umgekehrt werden. Sieh die Diskussionen über das Gamma in der PNG Spezifizierung für eine ausgezeichnete Beschreibung dessen, welches Gamma ist, und warum alle Anwendungen es unterstützen sollten. Es wird dass PNG Zuschauer-Support-Gammakorrektur stark empfohlen.

 if (png_get_gAMA(png_ptr, info_ptr, &gamma))
      png_set_gamma(png_ptr, screen_gamma, gamma);
   else
      png_set_gamma(png_ptr, screen_gamma, 0.45455);

Wenn Sie eine RGB Datei auf eine paletted Datei reduzieren müssen, oder wenn eine paletted Datei mehr Einträge hat, dann wird auf Ihrem Bildschirm passen, png_set_dither () wird das tun. Bemerken Sie, dass das eine einfache Übereinstimmungsaufregung ist, die bloß die nächste Farbe verfügbar findet. Das sollte ziemlich gut mit optimierten Paletten, und ziemlich schlecht mit geradlinigen Farbenwürfeln arbeiten. Wenn Sie eine Palette passieren, die dann maximum_colors größer ist, wird die Datei die Anzahl von Farben in der Palette vermindern, so wird es maximum_colors einbauen. Wenn es einen histogram gibt, wird es es verwenden, um intelligentere Wahlen zu machen, die Palette reduzierend. Wenn es keinen histogram gibt, kann es nicht als gut ein Job tun.

  if (color_type & PNG_COLOR_MASK_COLOR)
   {
      if (png_get_valid(png_ptr, info_ptr,
         PNG_INFO_PLTE))
      {
         png_uint_16p histogram = NULL;

         png_get_hIST(png_ptr, info_ptr,
            &histogram);
         png_set_dither(png_ptr, palette, num_palette,
            max_screen_colors, histogram, 1);
      }
      else
      {
         png_color std_color_cube[MAX_SCREEN_COLORS] =
            { ... colors ... };

         png_set_dither(png_ptr, std_color_cube,
            MAX_SCREEN_COLORS, MAX_SCREEN_COLORS,
            NULL,0);
      }
   }

PNG Dateien beschreiben monochrom als schwarz, Null und weiß seiend, ein seiend. Der folgende Code wird das umkehren (machen Sie schwarz, ein und weiß zu sein, Null sein):

   if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY)
      png_set_invert_mono(png_ptr);

Diese Funktion kann auch verwendet werden, um grayscale und Images des grauen Alphas umzukehren:

   if (color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      png_set_invert_mono(png_ptr);

PNG Dateien speichern 16-Bit-Pixel in der Netzwerksbyte-Ordnung (groß-endian, d. h.. die meisten bedeutenden Bit zuerst). Dieser Code ändert die Speicherung zum anderen Weg (wenig-endian, d. h. am wenigsten bedeutende Bit zuerst, der Weg, wie PCs sie speichern):

     if (bit_depth == 16)
        png_set_swap(png_ptr);

Wenn Sie einpacken-Bildpunktabbilder (1, 2, oder 4 Bit/Pixel) verwenden, und Sie die Ordnung ändern müssen, sind die Pixel in Bytes gepackt, Sie können verwenden:

   if (bit_depth < 8)
       png_set_packswap(png_ptr);

Schließlich können Sie Ihre eigene Transformationsfunktion schreiben, wenn keiner der vorhandenen Ihren Bedarf deckt. Das wird getan, eine Rückrufaktion damit setzend

  png_set_read_user_transform_fn(png_ptr,
       read_transform_fn);

Sie müssen die Funktion liefern

    void read_transform_fn(png_ptr ptr, row_info_ptr
       row_info, png_bytep data)

Sieh pngtest.c für ein Arbeitsbeispiel. Ihre Funktion wird genannt, nachdem alle anderen Transformationen bearbeitet worden sind.

Sie können auch einen Adressenverweis zu einer Benutzerstruktur für den Gebrauch durch Ihre Rückrufaktionsfunktion aufstellen, und Sie können libpng informieren, der Ihr, umgestaltest Funktion, die Anzahl von Kanälen ändern wird oder Tiefe mit der Funktion beißt

    png_set_user_transform_info(png_ptr, user_ptr,
       user_depth, user_channels);

Die Anwendung des Benutzers, nicht libpng, ist dafür verantwortlich, jeden für die Benutzerstruktur erforderlichen Speicher zu allozieren und zu befreien.

Sie können den Adressenverweis über die Funktion png_get_user_transform_ptr () abrufen. Zum Beispiel:

      voidp read_user_transform_ptr =
       png_get_user_transform_ptr(png_ptr);

Das letzte Ding zu behandeln verflicht sich; das wird im Detail unten bedeckt, aber Sie müssen die Funktion hier nennen, wenn Sie wollen, dass libpng Vergrößerung des verflochtenen Images behandelt.

     number_of_passes = png_set_interlace_handling(png_ptr);

Nach dem Setzen der Transformationen kann libpng Ihre png_info Struktur aktualisieren, um irgendwelche Transformationen zu widerspiegeln, um die Sie mit diesem Anruf gebeten haben. Das ist am nützlichsten, um das rowbytes Feld der Struktur des Infos zu aktualisieren, so können Sie es verwenden, um Ihren Bildspeicher zu allozieren. Diese Funktion wird auch Ihre Palette mit dem richtigen screen_gamma und Hintergrund aktualisieren, wenn diesen mit den Anrufen oben gegeben worden ist.

   png_read_update_info(png_ptr, info_ptr);

Nachdem Sie png_read_update_info nennen (), können Sie jeden Speicher allozieren Sie müssen das Image halten. Die Reihe-Daten sind einfach rohe Byte-Daten für alle Formen von Images. Weil sich die wirkliche Allozierung unter Anwendungen ändert, wird kein Beispiel angeführt. Wenn Sie einen großen Klotz allozieren, werden Sie eine Reihe von Adressenverweisen zu jeder Reihe bauen müssen, weil es für einige der Funktionen unten erforderlich sein wird.

Das Lesen von Bilddaten

Nachdem Sie Speicher alloziert haben, können Sie die Bilddaten lesen. Der einfachste Weg zu tun ist das in einem Funktionsaufruf. Wenn Sie genug Speicher allozieren, um das ganze Image zu halten, können Sie gerade png_read_image nennen (), und libpng wird in allen Bilddaten lesen und es im gelieferten Speicherbereich stellen. Sie werden in einer Reihe von Adressenverweisen zu jeder Reihe gehen müssen.

Diese Funktion behandelt automatisch das Verflechten, so brauchen Sie nicht png_set_interlace_handling () zu nennen oder diese Funktion mehrmals, oder einige dieses anderen mit png_read_rows notwendigen Zeugs () zu nennen.

   png_read_image(png_ptr, row_pointers);

wo row_pointers ist:

    png_bytep row_pointers[height];

Sie können zur Leere oder Rotforelle hinweisen, oder was auch immer Sie für Pixel verwenden.

Wenn Sie im ganzen Image sofort nicht lesen wollen, können Sie png_read_rows () stattdessen verwenden. Wenn sich dort nicht verflechtend ist (überprüfen Sie interlace_type == PNG_INTERLACE_NONE), ist das einfach:

   png_read_rows(png_ptr, row_pointers, NULL,
       number_of_rows);

wo row_pointers dasselbe als im png_read_image () Anruf ist.

Wenn Sie das gerade eine Reihe auf einmal tun, können Sie das mit einem einzelnen row_pointer statt einer Reihe von row_pointers tun:

     png_bytep row_pointer = row;
    png_read_row(png_ptr, row_pointer, NULL);

Wenn die Datei verflochten wird (interlace_type! = 0 im IHDR Klotz), Dinge werden etwas härter. Der einzige Strom (PNG Spezifizierungsversion 1.2) der sich verflechtende Typ für PNG ist (interlace_type == PNG_INTERLACE_ADAM7) ist ein etwas kompliziertes 2. Zwischenzeile-Schema, bekannt als Adam7, der ein Image in sieben kleinere Images der unterschiedlichen Größe bricht, die auf 8x8 Bratrost basiert ist.

libpng kann jene Images ausfüllen, oder er kann sie Ihnen geben, "als ist". Wenn Sie sie ausgefüllt wollen, gibt es zwei Wege, das zu tun. In der PNG Spezifizierung erwähnter derjenige soll jedes Pixel dekomprimieren, um jene Pixel zu bedecken, die noch (die "Rechteck"-Methode) nicht gelesen worden sind. Das läuft auf ein blocky Image für den ersten Pass hinaus, der allmählich wegräumt, weil mehr Pixel gelesen werden. Die andere Methode ist die "sprühen" Methode, wo Pixel nur in ihren Endspeicherstellen mit dem Rest des Images gezogen werden, das beliebige Farben bleibt, wurden sie zu vor dem Anfang des gelesenen initialisiert. Die erste Methode sieht gewöhnlich besser aus, aber neigt dazu, langsamer zu sein, weil es mehr Pixel gibt, um in den Reihen zu stellen.

Wenn Sie nicht wollen, dass libpng die sich verflechtenden Details behandelt, nennen Sie gerade png_read_rows () siebenmal, um in allen sieben Images zu lesen. Jedes der Images ist ein gültiges Image allein, oder sie können alle auf 8x8 Bratrost verbunden werden, um ein einzelnes Image zu bilden (obwohl, wenn Sie vorhaben, sie zu verbinden, Sie vom Verwenden des Libpng-Zwischenzeile-Berührens viel besser sein würden).

Der erste Pass wird ein Image 1/8 ebenso breit zurückgeben wie das komplette Image (jede 8. Säule, die in der Säule 0 anfängt) und 1/8 ebenso hoch wie das Original (jede 8. Reihe, die in der Reihe 0 anfängt), das zweite wird 1/8 als breit sein (in der Säule 4 anfangend), und 1/8 als hoch (auch in der Reihe 0 anfangend). Der dritte Pass wird 1/4 als breit (jedes 4. Pixel sein, die, das in der Säule 0 anfängt) und 1/8 als hoch (jede 8. Reihe in der Reihe 4 anfängt), und der vierte Pass wird 1/4 ebenso breit und 1/4 sein wie hoch (jede 4. Säule, die, die in der Säule 2, und jede 4. Reihe anfängt in der Reihe 0 anfängt). Der fünfte Pass wird ein Image 1/2 ebenso breit, und 1/4 zurückgeben wie hoch (an der Säule 0 und Reihe 2 anfangend), während der sechste Pass 1/2 ebenso breit und 1/2 ebenso hoch sein wird wie das Original (in der Säule 1 und Reihe 0 anfangend). Der siebente und endgültige Pass wird als das Original, und der 1/2 ebenso breit sein, weil hoch, alle sonderbaren enthaltend, scanlines zählte. Puh!

Wenn Sie wollen, dass libpng die Images dekomprimiert, nennen Sie das vor dem Benennen png_start_read_image () oder png_read_update_info ():

      if (interlace_type == PNG_INTERLACE_ADAM7)
        number_of_passes
           = png_set_interlace_handling(png_ptr);

Das wird die Anzahl von erforderlichen Pässen zurückgeben. Zurzeit ist das sieben, aber kann sich ändern, wenn ein anderer Zwischenzeile-Typ hinzugefügt wird. Diese Funktion kann genannt werden, selbst wenn die Datei nicht verflochten wird, wohin es einen Pass zurückgeben wird.

Wenn Sie nicht dabei sind, das Image nach jedem Pass anzuzeigen, aber dabei sind zu warten, bis das komplette Image gelesen wird in, die sprühen Wirkung zu verwenden. Diese Wirkung ist schneller, und das Endergebnis jeder Methode ist genau dasselbe. Wenn Sie beim Anzeigen des Images planen, nachdem jeder Pass, die "Rechteck"-Wirkung allgemein als das bessere Aussehen ein betrachtet wird.

Wenn Sie nur die "sprühen" Wirkung wollen, nennen Sie gerade png_read_rows () als normal, mit dem dritten Parameter UNGÜLTIG. Stellen Sie sicher, dass Sie machen, übertragen das Image number_of_passes Zeiten, und Sie ändern die Daten in den Reihen zwischen Anrufen nicht. Sie können die Speicherstellen der Daten, gerade nicht die Daten ändern. Jeder Pass schreibt nur die Pixel, die für diesen Pass, und nimmt passend sind, an, dass die Daten von vorherigen Pässen noch gültig sind.

      png_read_rows(png_ptr, row_pointers, NULL,
       number_of_rows);

Wenn Sie nur die erste Wirkung (die Rechtecke) wollen, wie zuvor außer dem Pass der Reihe-Puffer im dritten Parameter dasselbe machen, und den zweiten Parameter UNGÜLTIG verlassen.

      png_read_rows(png_ptr, NULL, row_pointers,
       number_of_rows);

Das Vollenden eines gelesenen folgenden

Nachdem Sie beendet werden, das Image entweder durch das hohe - oder durch die auf niedriger Stufe Schnittstellen lesend, können Sie beenden, die Datei zu lesen. Wenn Sie sich für Anmerkungen oder Zeit interessieren, die entweder vorher oder nach den Bilddaten gespeichert werden kann, sollten Sie den getrennten png_info struct passieren, wenn Sie die Anmerkungen aus der Zeit vor und nach dem Image getrennt halten wollen. Wenn Sie sich nicht interessieren, können Sie UNGÜLTIG gehen.