| # Metadata | |
| Files can also contain metadata (e.g. for image files, EXIF information, color | |
| profiles and time stamps). By default, Wuffs' decoders skip over metadata, but | |
| calling `set_report_metadata` will opt in to having `decode_etc` methods 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 `tell_me_more` to | |
| see what sort of metadata it is. | |
| Some metadata is short and `tell_me_more` will also fill in its `minfo: nptr | |
| more_information` out parameter with "parsed metadata". For example, Gamma | |
| Correction metadata is a single numerical value and Primary Chromaticities | |
| metadata is only eight numbers. From C++ code, call the `metadata_parsed__gama` | |
| or `metadata_parsed__chrm` methods to retrieve these value. | |
| Some metadata is long (or at least variable length) and needs processing 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. Wuffs decoders will return "raw metadata" instead of | |
| parsing it themselves. Raw metadata is further sub-divided into two categories: | |
| "raw passthrough" and "raw transform". Either way, note that raw metadata might | |
| also be arranged in multiple (non-contiguous) chunks of the source data. | |
| "Raw passthrough" means that the bytes in the wire format can be sent "as is" | |
| to the separate parser. Call `tell_me_more` in a loop (the `dst: io_writer` | |
| argument will be ignored) and `metadata_raw_passthrough__range` to identify a | |
| range (a chunk) of the input stream. Divert the bytes in that range to the | |
| separate parser (which should advance the `io_buffer` to the end of that range) | |
| and repeat the loop as long as `tell_me_more` returned a "$even more | |
| information" status. | |
| "Raw transform" means that the bytes in the wire format have to be further | |
| processed (e.g. decompressed) before sending them on to the separate parser. | |
| That processing is done by the decoder callee, not the caller. Pass a writable | |
| `dst io_buffer` to `tell_me_more` (where writable means that it has a positive | |
| `writer_length`) and implementations should fill in that buffer with | |
| post-transformed (e.g. decompressed) data to send onwards. Like any | |
| `io_transformer`-like coroutine, this should be in a loop, as it may suspend | |
| with "$short read" and "$short write" statuses. | |
| Either way, break the loop (after handling the `dst` and `minfo` out | |
| parameters) when `tell_me_more` returns a NULL status, meaning ok, when the | |
| metadata is complete. Afterwards, call the original action (e.g. `decode_etc`) | |
| again to resume after the "@metadata reported" detour. | |
| `tell_me_more` both returns a status and fills in the `dst` and `minfo` out | |
| parameters. Subtly, the caller should process the out parameters before | |
| considering the status. It is valid for the callee to fill in the out | |
| parameters with partial results when returning an error status or with full | |
| results when returning an ok status. 'No partial results' is represented by an | |
| unchanged `dst` or `minfo`. For example, if `minfo` was reset to zero before | |
| each `tell_me_more` call then `minfo.flavor` remaining zero means that the | |
| `minfo` was unchanged, as valid flavor values are non-zero. | |
| ## Examples | |
| - [script/print-image-metadata](/script/print-image-metadata.cc) |