|
| 1 | +/* |
| 2 | + * EXIF metadata parser |
| 3 | + * Copyright (c) 2013 Thilo Borgmann <thilo.borgmann _at_ mail.de> |
| 4 | + * Copyright (c) 2024-2025 Leo Izen <leo.izen@gmail.com> |
| 5 | + * |
| 6 | + * This file is part of FFmpeg. |
| 7 | + * |
| 8 | + * FFmpeg is free software; you can redistribute it and/or |
| 9 | + * modify it under the terms of the GNU Lesser General Public |
| 10 | + * License as published by the Free Software Foundation; either |
| 11 | + * version 2.1 of the License, or (at your option) any later version. |
| 12 | + * |
| 13 | + * FFmpeg is distributed in the hope that it will be useful, |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 | + * Lesser General Public License for more details. |
| 17 | + * |
| 18 | + * You should have received a copy of the GNU Lesser General Public |
| 19 | + * License along with FFmpeg; if not, write to the Free Software |
| 20 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 | + */ |
| 22 | + |
| 23 | +/** |
| 24 | + * @file |
| 25 | + * EXIF metadata parser |
| 26 | + * @author Thilo Borgmann <thilo.borgmann _at_ mail.de> |
| 27 | + * @author Leo Izen <leo.izen@gmail.com> |
| 28 | + */ |
| 29 | + |
| 30 | +#ifndef AVCODEC_EXIF_H |
| 31 | +#define AVCODEC_EXIF_H |
| 32 | + |
| 33 | +#include <stddef.h> |
| 34 | +#include <stdint.h> |
| 35 | + |
| 36 | +#include "libavutil/buffer.h" |
| 37 | +#include "libavutil/dict.h" |
| 38 | +#include "libavutil/rational.h" |
| 39 | +#include "version_major.h" |
| 40 | + |
| 41 | +/** Data type identifiers for TIFF tags */ |
| 42 | +enum AVTiffDataType { |
| 43 | + AV_TIFF_BYTE = 1, |
| 44 | + AV_TIFF_STRING, |
| 45 | + AV_TIFF_SHORT, |
| 46 | + AV_TIFF_LONG, |
| 47 | + AV_TIFF_RATIONAL, |
| 48 | + AV_TIFF_SBYTE, |
| 49 | + AV_TIFF_UNDEFINED, |
| 50 | + AV_TIFF_SSHORT, |
| 51 | + AV_TIFF_SLONG, |
| 52 | + AV_TIFF_SRATIONAL, |
| 53 | + AV_TIFF_FLOAT, |
| 54 | + AV_TIFF_DOUBLE, |
| 55 | + AV_TIFF_IFD, |
| 56 | +}; |
| 57 | + |
| 58 | +enum AVExifHeaderMode { |
| 59 | + /** |
| 60 | + * The TIFF header starts with 0x49492a00, or 0x4d4d002a. |
| 61 | + * This one is used internally by FFmpeg. |
| 62 | + */ |
| 63 | + AV_EXIF_TIFF_HEADER, |
| 64 | + /** skip the TIFF header, assume little endian */ |
| 65 | + AV_EXIF_ASSUME_LE, |
| 66 | + /** skip the TIFF header, assume big endian */ |
| 67 | + AV_EXIF_ASSUME_BE, |
| 68 | + /** The first four bytes point to the actual start, then it's AV_EXIF_TIFF_HEADER */ |
| 69 | + AV_EXIF_T_OFF, |
| 70 | + /** The first six bytes contain "Exif\0\0", then it's AV_EXIF_TIFF_HEADER */ |
| 71 | + AV_EXIF_EXIF00, |
| 72 | +}; |
| 73 | + |
| 74 | +typedef struct AVExifEntry AVExifEntry; |
| 75 | + |
| 76 | +typedef struct AVExifMetadata { |
| 77 | + /* array of EXIF metadata entries */ |
| 78 | + AVExifEntry *entries; |
| 79 | + /* number of entries in this array */ |
| 80 | + unsigned int count; |
| 81 | + /* size of the buffer, used for av_fast_realloc */ |
| 82 | + unsigned int size; |
| 83 | +} AVExifMetadata; |
| 84 | + |
| 85 | +struct AVExifEntry { |
| 86 | + uint16_t id; |
| 87 | + enum AVTiffDataType type; |
| 88 | + uint32_t count; |
| 89 | + |
| 90 | + /* |
| 91 | + * These are for IFD-style MakerNote |
| 92 | + * entries which occur after a fixed |
| 93 | + * offset rather than at the start of |
| 94 | + * the entry. The ifd_lead field contains |
| 95 | + * the leading bytes which typically |
| 96 | + * identify the type of MakerNote. |
| 97 | + */ |
| 98 | + uint32_t ifd_offset; |
| 99 | + uint8_t *ifd_lead; |
| 100 | + |
| 101 | + /* |
| 102 | + * An array of entries of size count |
| 103 | + * Unless it's an IFD, in which case |
| 104 | + * it's not an array and count = 1 |
| 105 | + */ |
| 106 | + union { |
| 107 | + void *ptr; |
| 108 | + int64_t *sint; |
| 109 | + uint64_t *uint; |
| 110 | + double *dbl; |
| 111 | + char *str; |
| 112 | + uint8_t *ubytes; |
| 113 | + int8_t *sbytes; |
| 114 | + AVRational *rat; |
| 115 | + AVExifMetadata ifd; |
| 116 | + } value; |
| 117 | +}; |
| 118 | + |
| 119 | +/** |
| 120 | + * Retrieves the tag name associated with the provided tag ID. |
| 121 | + * If the tag ID is unknown, NULL is returned. |
| 122 | + * |
| 123 | + * For example, av_exif_get_tag_name(0x112) returns "Orientation". |
| 124 | + */ |
| 125 | +const char *av_exif_get_tag_name(uint16_t id); |
| 126 | + |
| 127 | +/** |
| 128 | + * Retrieves the tag ID associated with the provided tag string name. |
| 129 | + * If the tag name is unknown, a negative number is returned. Otherwise |
| 130 | + * it always fits inside a uint16_t integer. |
| 131 | + * |
| 132 | + * For example, av_exif_get_tag_id("Orientation") returns 274 (0x0112). |
| 133 | + */ |
| 134 | +int32_t av_exif_get_tag_id(const char *name); |
| 135 | + |
| 136 | +/** |
| 137 | + * Add an entry to the provided EXIF metadata struct. If one already exists with the provided |
| 138 | + * ID, it will set the existing one to have the other information provided. Otherwise, it |
| 139 | + * will allocate a new entry. |
| 140 | + * |
| 141 | + * This function reallocates ifd->entries using av_realloc and allocates (using av_malloc) |
| 142 | + * a new value member of the entry, then copies the contents of value into that buffer. |
| 143 | + */ |
| 144 | +int av_exif_set_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, enum AVTiffDataType type, |
| 145 | + uint32_t count, const uint8_t *ifd_lead, uint32_t ifd_offset, const void *value); |
| 146 | + |
| 147 | +/** |
| 148 | + * Get an entry with the tagged ID from the EXIF metadata struct. A pointer to the entry |
| 149 | + * will be written into *value. If the recursive flag is set to true, this function will check |
| 150 | + * subdirectories as well. |
| 151 | + * |
| 152 | + * If the entry was present and returned successfully, a positive number is returned. |
| 153 | + * If the entry was not found, *value is left untouched and zero is returned. |
| 154 | + * If an error occurred, a negative number is returned. |
| 155 | + */ |
| 156 | +int av_exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int recursive, AVExifEntry **value); |
| 157 | + |
| 158 | +/** |
| 159 | + * Remove an entry from the provided EXIF metadata struct. If the recursive flag is set |
| 160 | + * to true, then this function will check subdirectories as well. |
| 161 | + * |
| 162 | + * If the entry was present and removed successfully, a positive number is returned. |
| 163 | + * If the entry was not found, zero is returned. |
| 164 | + * If an error occurred, a negative number is returned. |
| 165 | + */ |
| 166 | +int av_exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int recursive); |
| 167 | + |
| 168 | +/** |
| 169 | + * Decodes the EXIF data provided in the buffer and writes it into the |
| 170 | + * struct *ifd. If this function succeeds, the IFD is owned by the caller |
| 171 | + * and must be cleared after use by calling av_exif_free(); If this function |
| 172 | + * fails and returns a negative value, it will call av_exif_free(ifd) before |
| 173 | + * returning. |
| 174 | + */ |
| 175 | +int av_exif_parse_buffer(void *logctx, const uint8_t *data, size_t size, |
| 176 | + AVExifMetadata *ifd, enum AVExifHeaderMode header_mode); |
| 177 | + |
| 178 | +/** |
| 179 | + * Allocates a buffer using av_malloc of an appropriate size and writes the |
| 180 | + * EXIF data represented by ifd into that buffer. |
| 181 | + * |
| 182 | + * Upon error, *buffer will be NULL. The buffer becomes owned by the caller upon |
| 183 | + * success. The *buffer argument must be NULL before calling. |
| 184 | + */ |
| 185 | +int av_exif_write(void *logctx, const AVExifMetadata *ifd, AVBufferRef **buffer, enum AVExifHeaderMode header_mode); |
| 186 | + |
| 187 | +/** |
| 188 | + * Frees all resources associated with the given EXIF metadata struct. |
| 189 | + * Does not free the pointer passed itself, in case it is stack-allocated. |
| 190 | + * The pointer passed to this function must be freed by the caller, |
| 191 | + * if it is heap-allocated. Passing NULL is permitted. |
| 192 | + */ |
| 193 | +void av_exif_free(AVExifMetadata *ifd); |
| 194 | + |
| 195 | +/** |
| 196 | + * Recursively reads all tags from the IFD and stores them in the |
| 197 | + * provided metadata dictionary. |
| 198 | + */ |
| 199 | +int av_exif_ifd_to_dict(void *logctx, const AVExifMetadata *ifd, AVDictionary **metadata); |
| 200 | + |
| 201 | +/** |
| 202 | + * Allocates a duplicate of the provided EXIF metadata struct. The caller owns |
| 203 | + * the duplicate and must free it with av_exif_free. Returns NULL if the duplication |
| 204 | + * process failed. |
| 205 | + */ |
| 206 | +AVExifMetadata *av_exif_clone_ifd(const AVExifMetadata *ifd); |
| 207 | + |
| 208 | +/** |
| 209 | + * Convert a display matrix used by AV_FRAME_DATA_DISPLAYMATRIX |
| 210 | + * into an orientation constant used by EXIF's orientation tag. |
| 211 | + * |
| 212 | + * Returns an EXIF orientation between 1 and 8 (inclusive) depending |
| 213 | + * on the rotation and flip factors. Returns 0 if the matrix is singular. |
| 214 | + */ |
| 215 | +int av_exif_matrix_to_orientation(const int32_t *matrix); |
| 216 | + |
| 217 | +/** |
| 218 | + * Convert an orientation constant used by EXIF's orientation tag |
| 219 | + * into a display matrix used by AV_FRAME_DATA_DISPLAYMATRIX. |
| 220 | + * |
| 221 | + * Returns 0 on success and negative if the orientation is invalid, |
| 222 | + * i.e. not between 1 and 8 (inclusive). |
| 223 | + */ |
| 224 | +int av_exif_orientation_to_matrix(int32_t *matrix, int orientation); |
| 225 | + |
| 226 | +#endif /* AVCODEC_EXIF_H */ |
0 commit comments