| # Image Decoders | 
 |  | 
 | Regardless of the file format (GIF, JPEG, PNG, etc), every Wuffs image decoder | 
 | has a similar API. This document gives `wuffs_gif__decoder__foo_bar` examples, | 
 | but the `gif` could be replaced by `jpeg`, `png`, etc. | 
 |  | 
 | Some image formats (GIF) are animated, consisting of an image header and then N | 
 | frames. The image header gives e.g. the overall image's width and height. Each | 
 | frame consists of a frame header (e.g. frame rectangle bounds, display | 
 | duration) and a payload (the pixels). | 
 |  | 
 | In general, there is one `wuffs_base__image_config` and then N pairs of | 
 | (`wuffs_base__frame_config`, frame). Non-animated (still) image formats are | 
 | treated the same way: that their N is 1 and their single frame's bounds equals | 
 | the overall image bounds. | 
 |  | 
 | To decode everything (without knowing N in advance) sequentially: | 
 |  | 
 | ``` | 
 | wuffs_base__io_buffer src = etc; | 
 | wuffs_gif__decoder* dec = etc; | 
 |  | 
 | wuffs_base__image_config ic; | 
 | wuffs_base__status status = wuffs_gif__decoder__decode_image_config(dec, &ic, &src); | 
 | // Error checking (inspecting the status variable) is not shown, for brevity. | 
 | // See the example programs, listed below, for how to handle errors. | 
 |  | 
 | // Allocate the pixel buffer, based on ic's width and height, etc. | 
 | wuffs_base__pixel_buffer pb = etc; | 
 |  | 
 | while (true) { | 
 |   wuffs_base__frame_config fc; | 
 |   status = wuffs_gif__decoder__decode_frame_config(dec, &fc, &src); | 
 |   if (status.repr == wuffs_base__note__end_of_data) { | 
 |     break; | 
 |   } | 
 |   // Ditto re error checking. | 
 |  | 
 |   status = wuffs_gif__decoder__decode_frame(dec, &pb, &etc); | 
 |   // Ditto re error checking. | 
 | } | 
 | ``` | 
 |  | 
 | The second argument to each `decode_xxx` method (`&ic`, `&fc` or `&pb`), is the | 
 | destination data structure to store the decoded information. | 
 |  | 
 | For random (instead of sequential) access to an image's frames, call | 
 | `wuffs_gif__decoder__restart_frame(dec, i, io_pos)` to prepare to decode the | 
 | i'th frame. Essentially, it restores the state to be at the top of the while | 
 | loop above. The `wuffs_base__io_buffer`'s reader position will also need to be | 
 | set to the `io_pos` position in the source data stream. The position for the | 
 | i'th frame is calculated by the i'th `decode_frame_config` call and saved in | 
 | the `frame_config`. You can only call `restart_frame` after | 
 | `decode_image_config` is called, explicitly or implicitly (see below), as | 
 | decoding a single frame might require for-all-frames information like the | 
 | overall image dimensions and the global palette. | 
 |  | 
 | All of those `decode_xxx` calls are optional. For example, if | 
 | `decode_image_config` is not called, then the first `decode_frame_config` call | 
 | will implicitly parse and verify the image header, before parsing the first | 
 | frame's header. Similarly, you can call only `decode_frame` N times, without | 
 | calling `decode_image_config` or `decode_frame_config`, if you already know | 
 | metadata like N and each frame's rectangle bounds by some other means (e.g. | 
 | this is a first party, statically known image). | 
 |  | 
 | Specifically, starting with an unknown (but re-windable) animated image, if you | 
 | want to just find N (i.e. count the number of frames), you can loop calling | 
 | only the `decode_frame_config` method and avoid calling the more expensive | 
 | `decode_frame` method. For GIF, in terms of the underlying wire format, this | 
 | will skip over (instead of decompress) the LZW-encoded pixel data, which is | 
 | faster. | 
 |  | 
 | Those `decode_xxx` methods are also suspendible | 
 | [coroutines](/doc/note/coroutines.md). They will return early (with a status | 
 | code that `is_suspendible` and therefore isn't `is_complete`) if there isn't | 
 | enough source data to complete the operation: an incremental decode. Calling | 
 | `decode_xxx` again with additional source data will resume the previous | 
 | operation instead of starting a new one. Calling `decode_yyy` whilst | 
 | `decode_xxx` is suspended will result in an error. | 
 |  | 
 | Once an error is encountered, whether from invalid source data or from a | 
 | programming error, such as calling `decode_yyy` while suspended in | 
 | `decode_xxx`, all subsequent calls will be no-ops that return an error. To | 
 | reset the decoder into something that does productive work, | 
 | [re-initialize](/doc/note/initialization.md) and then, in order to be able to | 
 | call `restart_frame`, call `decode_image_config`. The `io_buffer` and its | 
 | associated stream will also need to be rewound. | 
 |  | 
 |  | 
 | ## Metadata | 
 |  | 
 | Images can also contain metadata (e.g. color profiles, time stamps). By | 
 | default, Wuffs' image decoders skip over metadata, but calling | 
 | `set_report_metadata` will opt in to having `decode_image_config` return early | 
 | when encountering metadata in the file. Calling `set_report_metadata` can be | 
 | done multiple times, each with a different | 
 | [FourCC](/doc/note/base38-and-fourcc.md) code such as `0x49434350` "ICCP" or | 
 | `0x584D5020` "XMP ", to indicate what sorts of metadata the caller is | 
 | interested in. Conversely, when the parser encounters metadata (and returns a | 
 | "@metadata reported" [status](/doc/note/statuses.md)), call `metadata_fourcc` | 
 | to see what sort of metadata it is. | 
 |  | 
 | Embedded metadata needs to be processed by a separate parser. For example, | 
 | processing XMP metadata usually involves some sort of XML parser, regardless of | 
 | what particular image format that XMP metadata was embedded in. That metadata | 
 | might also be in multiple (non-contiguous) chunks. The caller needs to loop, | 
 | repeatedly calling `metadata_chunk_length`, advancing the `io_buffer` by that | 
 | many bytes (after diverting those bytes to the separate parser) and calling | 
 | `ack_metadata_chunk`. If the latter returns "@metadata reported", then repeat | 
 | the loop. If it returns ok, then the metadata was completely consumed, and the | 
 | caller can go back to the `decode_image_config` method. | 
 |  | 
 |  | 
 | ## Implementations | 
 |  | 
 | - [std/bmp](/std/bmp) | 
 | - [std/gif](/std/gif) | 
 | - [std/nie](/std/nie) | 
 | - [std/png](/std/png) | 
 | - [std/wbmp](/std/wbmp) | 
 |  | 
 |  | 
 | ## Examples | 
 |  | 
 | - [example/convert-to-nia](/example/convert-to-nia) | 
 | - [example/gifplayer](/example/gifplayer) | 
 | - [example/imageviewer](/example/imageviewer) | 
 |  | 
 | Examples in other repositories: | 
 |  | 
 | - [Skia](https://skia.googlesource.com/skia/+/refs/heads/master/src/codec/SkWuffsCodec.cpp), | 
 |   a 2-D graphics library used by the Android operating system and the Chromium | 
 |   web browser. | 
 |  | 
 |  | 
 | ## [Quirks](/doc/note/quirks.md) | 
 |  | 
 | - [GIF decoder quirks](/std/gif/decode_quirks.wuffs) | 
 |  | 
 |  | 
 | ## Related Documentation | 
 |  | 
 | - [I/O (Input / Output)](/doc/note/io-input-output.md) | 
 | - [Pixel Formats](/doc/note/pixel-formats.md) | 
 | - [Pixel Subsampling](/doc/note/pixel-subsampling.md) | 
 | - [Ranges and Rects](/doc/note/ranges-and-rects.md) | 
 |  | 
 | See also the general remarks on [Wuffs' standard library](/doc/std/README.md). |