blob: 0af62ee96219a9f8eba1ce80e32b0408e5b06fc2
1 | /* |
2 | * TIFF Common Routines |
3 | * Copyright (c) 2013 Thilo Borgmann <thilo.borgmann _at_ mail.de> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | /** |
23 | * @file |
24 | * TIFF Common Routines |
25 | * @author Thilo Borgmann <thilo.borgmann _at_ mail.de> |
26 | */ |
27 | |
28 | #include "tiff_common.h" |
29 | |
30 | |
31 | int ff_tis_ifd(unsigned tag) |
32 | { |
33 | int i; |
34 | for (i = 0; i < FF_ARRAY_ELEMS(ifd_tags); i++) { |
35 | if (ifd_tags[i] == tag) { |
36 | return i + 1; |
37 | } |
38 | } |
39 | return 0; |
40 | } |
41 | |
42 | |
43 | unsigned ff_tget_short(GetByteContext *gb, int le) |
44 | { |
45 | return le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb); |
46 | } |
47 | |
48 | |
49 | unsigned ff_tget_long(GetByteContext *gb, int le) |
50 | { |
51 | return le ? bytestream2_get_le32(gb) : bytestream2_get_be32(gb); |
52 | } |
53 | |
54 | |
55 | double ff_tget_double(GetByteContext *gb, int le) |
56 | { |
57 | av_alias64 i = { .u64 = le ? bytestream2_get_le64(gb) : bytestream2_get_be64(gb)}; |
58 | return i.f64; |
59 | } |
60 | |
61 | |
62 | unsigned ff_tget(GetByteContext *gb, int type, int le) |
63 | { |
64 | switch (type) { |
65 | case TIFF_BYTE: return bytestream2_get_byte(gb); |
66 | case TIFF_SHORT: return ff_tget_short(gb, le); |
67 | case TIFF_LONG: return ff_tget_long(gb, le); |
68 | default: return UINT_MAX; |
69 | } |
70 | } |
71 | |
72 | static const char *auto_sep(int count, const char *sep, int i, int columns) |
73 | { |
74 | if (sep) |
75 | return i ? sep : ""; |
76 | if (i && i%columns) { |
77 | return ", "; |
78 | } else |
79 | return columns < count ? "\n" : ""; |
80 | } |
81 | |
82 | int ff_tadd_rational_metadata(int count, const char *name, const char *sep, |
83 | GetByteContext *gb, int le, AVDictionary **metadata) |
84 | { |
85 | AVBPrint bp; |
86 | char *ap; |
87 | int32_t nom, denom; |
88 | int i; |
89 | |
90 | if (count >= INT_MAX / sizeof(int64_t) || count <= 0) |
91 | return AVERROR_INVALIDDATA; |
92 | if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t)) |
93 | return AVERROR_INVALIDDATA; |
94 | |
95 | av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
96 | |
97 | for (i = 0; i < count; i++) { |
98 | nom = ff_tget_long(gb, le); |
99 | denom = ff_tget_long(gb, le); |
100 | av_bprintf(&bp, "%s%7"PRId32":%-7"PRId32, auto_sep(count, sep, i, 4), nom, denom); |
101 | } |
102 | |
103 | if ((i = av_bprint_finalize(&bp, &ap))) { |
104 | return i; |
105 | } |
106 | if (!ap) { |
107 | return AVERROR(ENOMEM); |
108 | } |
109 | |
110 | av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
111 | |
112 | return 0; |
113 | } |
114 | |
115 | |
116 | int ff_tadd_long_metadata(int count, const char *name, const char *sep, |
117 | GetByteContext *gb, int le, AVDictionary **metadata) |
118 | { |
119 | AVBPrint bp; |
120 | char *ap; |
121 | int i; |
122 | |
123 | if (count >= INT_MAX / sizeof(int32_t) || count <= 0) |
124 | return AVERROR_INVALIDDATA; |
125 | if (bytestream2_get_bytes_left(gb) < count * sizeof(int32_t)) |
126 | return AVERROR_INVALIDDATA; |
127 | |
128 | av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
129 | |
130 | for (i = 0; i < count; i++) { |
131 | av_bprintf(&bp, "%s%7i", auto_sep(count, sep, i, 8), ff_tget_long(gb, le)); |
132 | } |
133 | |
134 | if ((i = av_bprint_finalize(&bp, &ap))) { |
135 | return i; |
136 | } |
137 | if (!ap) { |
138 | return AVERROR(ENOMEM); |
139 | } |
140 | |
141 | av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
142 | |
143 | return 0; |
144 | } |
145 | |
146 | |
147 | int ff_tadd_doubles_metadata(int count, const char *name, const char *sep, |
148 | GetByteContext *gb, int le, AVDictionary **metadata) |
149 | { |
150 | AVBPrint bp; |
151 | char *ap; |
152 | int i; |
153 | |
154 | if (count >= INT_MAX / sizeof(int64_t) || count <= 0) |
155 | return AVERROR_INVALIDDATA; |
156 | if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t)) |
157 | return AVERROR_INVALIDDATA; |
158 | |
159 | av_bprint_init(&bp, 10 * count, 100 * count); |
160 | |
161 | for (i = 0; i < count; i++) { |
162 | av_bprintf(&bp, "%s%.15g", auto_sep(count, sep, i, 4), ff_tget_double(gb, le)); |
163 | } |
164 | |
165 | if ((i = av_bprint_finalize(&bp, &ap))) { |
166 | return i; |
167 | } |
168 | if (!ap) { |
169 | return AVERROR(ENOMEM); |
170 | } |
171 | |
172 | av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
173 | |
174 | return 0; |
175 | } |
176 | |
177 | |
178 | int ff_tadd_shorts_metadata(int count, const char *name, const char *sep, |
179 | GetByteContext *gb, int le, int is_signed, AVDictionary **metadata) |
180 | { |
181 | AVBPrint bp; |
182 | char *ap; |
183 | int i; |
184 | |
185 | if (count >= INT_MAX / sizeof(int16_t) || count <= 0) |
186 | return AVERROR_INVALIDDATA; |
187 | if (bytestream2_get_bytes_left(gb) < count * sizeof(int16_t)) |
188 | return AVERROR_INVALIDDATA; |
189 | |
190 | av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
191 | |
192 | for (i = 0; i < count; i++) { |
193 | int v = is_signed ? (int16_t)ff_tget_short(gb, le) : ff_tget_short(gb, le); |
194 | av_bprintf(&bp, "%s%5i", auto_sep(count, sep, i, 8), v); |
195 | } |
196 | |
197 | if ((i = av_bprint_finalize(&bp, &ap))) { |
198 | return i; |
199 | } |
200 | if (!ap) { |
201 | return AVERROR(ENOMEM); |
202 | } |
203 | |
204 | av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
205 | |
206 | return 0; |
207 | } |
208 | |
209 | |
210 | int ff_tadd_bytes_metadata(int count, const char *name, const char *sep, |
211 | GetByteContext *gb, int le, int is_signed, AVDictionary **metadata) |
212 | { |
213 | AVBPrint bp; |
214 | char *ap; |
215 | int i; |
216 | |
217 | if (count >= INT_MAX / sizeof(int8_t) || count < 0) |
218 | return AVERROR_INVALIDDATA; |
219 | if (bytestream2_get_bytes_left(gb) < count * sizeof(int8_t)) |
220 | return AVERROR_INVALIDDATA; |
221 | |
222 | av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
223 | |
224 | for (i = 0; i < count; i++) { |
225 | int v = is_signed ? (int8_t)bytestream2_get_byte(gb) : bytestream2_get_byte(gb); |
226 | av_bprintf(&bp, "%s%3i", auto_sep(count, sep, i, 16), v); |
227 | } |
228 | |
229 | if ((i = av_bprint_finalize(&bp, &ap))) { |
230 | return i; |
231 | } |
232 | if (!ap) { |
233 | return AVERROR(ENOMEM); |
234 | } |
235 | |
236 | av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
237 | |
238 | return 0; |
239 | } |
240 | |
241 | int ff_tadd_string_metadata(int count, const char *name, |
242 | GetByteContext *gb, int le, AVDictionary **metadata) |
243 | { |
244 | char *value; |
245 | |
246 | if (bytestream2_get_bytes_left(gb) < count || count < 0) |
247 | return AVERROR_INVALIDDATA; |
248 | |
249 | value = av_malloc(count + 1); |
250 | if (!value) |
251 | return AVERROR(ENOMEM); |
252 | |
253 | bytestream2_get_bufferu(gb, value, count); |
254 | value[count] = 0; |
255 | |
256 | av_dict_set(metadata, name, value, AV_DICT_DONT_STRDUP_VAL); |
257 | return 0; |
258 | } |
259 | |
260 | |
261 | int ff_tdecode_header(GetByteContext *gb, int *le, int *ifd_offset) |
262 | { |
263 | if (bytestream2_get_bytes_left(gb) < 8) { |
264 | return AVERROR_INVALIDDATA; |
265 | } |
266 | |
267 | *le = bytestream2_get_le16u(gb); |
268 | if (*le == AV_RB16("II")) { |
269 | *le = 1; |
270 | } else if (*le == AV_RB16("MM")) { |
271 | *le = 0; |
272 | } else { |
273 | return AVERROR_INVALIDDATA; |
274 | } |
275 | |
276 | if (ff_tget_short(gb, *le) != 42) { |
277 | return AVERROR_INVALIDDATA; |
278 | } |
279 | |
280 | *ifd_offset = ff_tget_long(gb, *le); |
281 | |
282 | return 0; |
283 | } |
284 | |
285 | |
286 | int ff_tread_tag(GetByteContext *gb, int le, unsigned *tag, unsigned *type, |
287 | unsigned *count, int *next) |
288 | { |
289 | int ifd_tag; |
290 | int valid_type; |
291 | |
292 | *tag = ff_tget_short(gb, le); |
293 | *type = ff_tget_short(gb, le); |
294 | *count = ff_tget_long (gb, le); |
295 | |
296 | ifd_tag = ff_tis_ifd(*tag); |
297 | valid_type = *type != 0 && *type < FF_ARRAY_ELEMS(type_sizes); |
298 | |
299 | *next = bytestream2_tell(gb) + 4; |
300 | |
301 | // check for valid type |
302 | if (!valid_type) { |
303 | return AVERROR_INVALIDDATA; |
304 | } |
305 | |
306 | // seek to offset if this is an IFD-tag or |
307 | // if count values do not fit into the offset value |
308 | if (ifd_tag || (*count > 4 || !(type_sizes[*type] * (*count) <= 4 || *type == TIFF_STRING))) { |
309 | bytestream2_seek(gb, ff_tget_long (gb, le), SEEK_SET); |
310 | } |
311 | |
312 | return 0; |
313 | } |
314 |