FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tiff_common.c
Go to the documentation of this file.
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 
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%7i:%-7i", 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 }