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 |
|
795 |
int ff_tis_ifd(unsigned tag) |
32 |
|
|
{ |
33 |
|
|
int i; |
34 |
✓✓ |
3100 |
for (i = 0; i < FF_ARRAY_ELEMS(ifd_tags); i++) { |
35 |
✓✓ |
2337 |
if (ifd_tags[i] == tag) { |
36 |
|
32 |
return i + 1; |
37 |
|
|
} |
38 |
|
|
} |
39 |
|
763 |
return 0; |
40 |
|
|
} |
41 |
|
|
|
42 |
|
|
|
43 |
|
1443 |
unsigned ff_tget_short(GetByteContext *gb, int le) |
44 |
|
|
{ |
45 |
✓✓ |
1443 |
return le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb); |
46 |
|
|
} |
47 |
|
|
|
48 |
|
|
|
49 |
|
2503 |
unsigned ff_tget_long(GetByteContext *gb, int le) |
50 |
|
|
{ |
51 |
✓✓ |
2503 |
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 |
|
1689 |
unsigned ff_tget(GetByteContext *gb, int type, int le) |
63 |
|
|
{ |
64 |
✗✓✓✗
|
1689 |
switch (type) { |
65 |
|
|
case TIFF_BYTE: return bytestream2_get_byte(gb); |
66 |
|
173 |
case TIFF_SHORT: return ff_tget_short(gb, le); |
67 |
|
1516 |
case TIFF_LONG: return ff_tget_long(gb, le); |
68 |
|
|
default: return UINT_MAX; |
69 |
|
|
} |
70 |
|
|
} |
71 |
|
|
|
72 |
|
10302 |
static const char *auto_sep(int count, const char *sep, int i, int columns) |
73 |
|
|
{ |
74 |
✓✓ |
10302 |
if (sep) |
75 |
✓✓ |
4 |
return i ? sep : ""; |
76 |
✓✓✓✓
|
10298 |
if (i && i%columns) { |
77 |
|
9488 |
return ", "; |
78 |
|
|
} else |
79 |
✓✓ |
810 |
return columns < count ? "\n" : ""; |
80 |
|
|
} |
81 |
|
|
|
82 |
|
56 |
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 |
✓✗✗✓
|
56 |
if (count >= INT_MAX / sizeof(int64_t) || count <= 0) |
91 |
|
|
return AVERROR_INVALIDDATA; |
92 |
✗✓ |
56 |
if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t)) |
93 |
|
|
return AVERROR_INVALIDDATA; |
94 |
|
|
|
95 |
|
56 |
av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
96 |
|
|
|
97 |
✓✓ |
112 |
for (i = 0; i < count; i++) { |
98 |
|
56 |
nom = ff_tget_long(gb, le); |
99 |
|
56 |
denom = ff_tget_long(gb, le); |
100 |
|
56 |
av_bprintf(&bp, "%s%7"PRId32":%-7"PRId32, auto_sep(count, sep, i, 4), nom, denom); |
101 |
|
|
} |
102 |
|
|
|
103 |
✗✓ |
56 |
if ((i = av_bprint_finalize(&bp, &ap))) { |
104 |
|
|
return i; |
105 |
|
|
} |
106 |
✗✓ |
56 |
if (!ap) { |
107 |
|
|
return AVERROR(ENOMEM); |
108 |
|
|
} |
109 |
|
|
|
110 |
|
56 |
av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
111 |
|
|
|
112 |
|
56 |
return 0; |
113 |
|
|
} |
114 |
|
|
|
115 |
|
|
|
116 |
|
20 |
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 |
✓✗✗✓
|
20 |
if (count >= INT_MAX / sizeof(int32_t) || count <= 0) |
124 |
|
|
return AVERROR_INVALIDDATA; |
125 |
✗✓ |
20 |
if (bytestream2_get_bytes_left(gb) < count * sizeof(int32_t)) |
126 |
|
|
return AVERROR_INVALIDDATA; |
127 |
|
|
|
128 |
|
20 |
av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
129 |
|
|
|
130 |
✓✓ |
40 |
for (i = 0; i < count; i++) { |
131 |
|
20 |
av_bprintf(&bp, "%s%7i", auto_sep(count, sep, i, 8), ff_tget_long(gb, le)); |
132 |
|
|
} |
133 |
|
|
|
134 |
✗✓ |
20 |
if ((i = av_bprint_finalize(&bp, &ap))) { |
135 |
|
|
return i; |
136 |
|
|
} |
137 |
✗✓ |
20 |
if (!ap) { |
138 |
|
|
return AVERROR(ENOMEM); |
139 |
|
|
} |
140 |
|
|
|
141 |
|
20 |
av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
142 |
|
|
|
143 |
|
20 |
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 |
|
76 |
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 |
✓✗✗✓
|
76 |
if (count >= INT_MAX / sizeof(int16_t) || count <= 0) |
186 |
|
|
return AVERROR_INVALIDDATA; |
187 |
✗✓ |
76 |
if (bytestream2_get_bytes_left(gb) < count * sizeof(int16_t)) |
188 |
|
|
return AVERROR_INVALIDDATA; |
189 |
|
|
|
190 |
|
76 |
av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
191 |
|
|
|
192 |
✓✓ |
154 |
for (i = 0; i < count; i++) { |
193 |
✗✓ |
78 |
int v = is_signed ? (int16_t)ff_tget_short(gb, le) : ff_tget_short(gb, le); |
194 |
|
78 |
av_bprintf(&bp, "%s%5i", auto_sep(count, sep, i, 8), v); |
195 |
|
|
} |
196 |
|
|
|
197 |
✗✓ |
76 |
if ((i = av_bprint_finalize(&bp, &ap))) { |
198 |
|
|
return i; |
199 |
|
|
} |
200 |
✗✓ |
76 |
if (!ap) { |
201 |
|
|
return AVERROR(ENOMEM); |
202 |
|
|
} |
203 |
|
|
|
204 |
|
76 |
av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
205 |
|
|
|
206 |
|
76 |
return 0; |
207 |
|
|
} |
208 |
|
|
|
209 |
|
|
|
210 |
|
36 |
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 |
✓✗✗✓
|
36 |
if (count >= INT_MAX / sizeof(int8_t) || count < 0) |
218 |
|
|
return AVERROR_INVALIDDATA; |
219 |
✗✓ |
36 |
if (bytestream2_get_bytes_left(gb) < count * sizeof(int8_t)) |
220 |
|
|
return AVERROR_INVALIDDATA; |
221 |
|
|
|
222 |
|
36 |
av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); |
223 |
|
|
|
224 |
✓✓ |
10184 |
for (i = 0; i < count; i++) { |
225 |
✗✓ |
10148 |
int v = is_signed ? (int8_t)bytestream2_get_byte(gb) : bytestream2_get_byte(gb); |
226 |
|
10148 |
av_bprintf(&bp, "%s%3i", auto_sep(count, sep, i, 16), v); |
227 |
|
|
} |
228 |
|
|
|
229 |
✗✓ |
36 |
if ((i = av_bprint_finalize(&bp, &ap))) { |
230 |
|
|
return i; |
231 |
|
|
} |
232 |
✗✓ |
36 |
if (!ap) { |
233 |
|
|
return AVERROR(ENOMEM); |
234 |
|
|
} |
235 |
|
|
|
236 |
|
36 |
av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); |
237 |
|
|
|
238 |
|
36 |
return 0; |
239 |
|
|
} |
240 |
|
|
|
241 |
|
58 |
int ff_tadd_string_metadata(int count, const char *name, |
242 |
|
|
GetByteContext *gb, int le, AVDictionary **metadata) |
243 |
|
|
{ |
244 |
|
|
char *value; |
245 |
|
|
|
246 |
✓✗✗✓
|
58 |
if (bytestream2_get_bytes_left(gb) < count || count < 0) |
247 |
|
|
return AVERROR_INVALIDDATA; |
248 |
|
|
|
249 |
|
58 |
value = av_malloc(count + 1); |
250 |
✗✓ |
58 |
if (!value) |
251 |
|
|
return AVERROR(ENOMEM); |
252 |
|
|
|
253 |
|
58 |
bytestream2_get_bufferu(gb, value, count); |
254 |
|
58 |
value[count] = 0; |
255 |
|
|
|
256 |
|
58 |
av_dict_set(metadata, name, value, AV_DICT_DONT_STRDUP_VAL); |
257 |
|
58 |
return 0; |
258 |
|
|
} |
259 |
|
|
|
260 |
|
|
|
261 |
|
41 |
int ff_tdecode_header(GetByteContext *gb, int *le, int *ifd_offset) |
262 |
|
|
{ |
263 |
✗✓ |
41 |
if (bytestream2_get_bytes_left(gb) < 8) { |
264 |
|
|
return AVERROR_INVALIDDATA; |
265 |
|
|
} |
266 |
|
|
|
267 |
|
41 |
*le = bytestream2_get_le16u(gb); |
268 |
✓✓ |
41 |
if (*le == AV_RB16("II")) { |
269 |
|
27 |
*le = 1; |
270 |
✓✗ |
14 |
} else if (*le == AV_RB16("MM")) { |
271 |
|
14 |
*le = 0; |
272 |
|
|
} else { |
273 |
|
|
return AVERROR_INVALIDDATA; |
274 |
|
|
} |
275 |
|
|
|
276 |
✗✓ |
41 |
if (ff_tget_short(gb, *le) != 42) { |
277 |
|
|
return AVERROR_INVALIDDATA; |
278 |
|
|
} |
279 |
|
|
|
280 |
|
41 |
*ifd_offset = ff_tget_long(gb, *le); |
281 |
|
|
|
282 |
|
41 |
return 0; |
283 |
|
|
} |
284 |
|
|
|
285 |
|
|
|
286 |
|
547 |
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 |
|
547 |
*tag = ff_tget_short(gb, le); |
293 |
|
547 |
*type = ff_tget_short(gb, le); |
294 |
|
547 |
*count = ff_tget_long (gb, le); |
295 |
|
|
|
296 |
|
547 |
ifd_tag = ff_tis_ifd(*tag); |
297 |
✓✗✓✗
|
547 |
valid_type = *type != 0 && *type < FF_ARRAY_ELEMS(type_sizes); |
298 |
|
|
|
299 |
|
547 |
*next = bytestream2_tell(gb) + 4; |
300 |
|
|
|
301 |
|
|
// check for valid type |
302 |
✗✓ |
547 |
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 |
✓✓✓✓ ✓✓✓✓
|
547 |
if (ifd_tag || (*count > 4 || !(type_sizes[*type] * (*count) <= 4 || *type == TIFF_STRING))) { |
309 |
|
231 |
bytestream2_seek(gb, ff_tget_long (gb, le), SEEK_SET); |
310 |
|
|
} |
311 |
|
|
|
312 |
|
547 |
return 0; |
313 |
|
|
} |