Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6148 serge 1
/*
2
 * TIFF Common Routines
3
 * Copyright (c) 2013 Thilo Borgmann 
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 
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
    unsigned v = le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb);
46
    return v;
47
}
48
 
49
 
50
unsigned ff_tget_long(GetByteContext *gb, int le)
51
{
52
    unsigned v = le ? bytestream2_get_le32(gb) : bytestream2_get_be32(gb);
53
    return v;
54
}
55
 
56
 
57
double ff_tget_double(GetByteContext *gb, int le)
58
{
59
    av_alias64 i = { .u64 = le ? bytestream2_get_le64(gb) : bytestream2_get_be64(gb)};
60
    return i.f64;
61
}
62
 
63
 
64
unsigned ff_tget(GetByteContext *gb, int type, int le)
65
{
66
    switch (type) {
67
    case TIFF_BYTE:
68
        return bytestream2_get_byte(gb);
69
    case TIFF_SHORT:
70
        return ff_tget_short(gb, le);
71
    case TIFF_LONG:
72
        return ff_tget_long(gb, le);
73
    default:
74
        return UINT_MAX;
75
    }
76
}
77
 
78
static char *auto_sep(int count, char *sep, int i, int columns)
79
{
80
    if (sep)
81
        return i ? sep : "";
82
    if (i && i%columns) {
83
        return ", ";
84
    } else
85
        return columns < count ? "\n" : "";
86
}
87
 
88
int ff_tadd_rational_metadata(int count, const char *name, const char *sep,
89
                              GetByteContext *gb, int le, AVDictionary **metadata)
90
{
91
    AVBPrint bp;
92
    char *ap;
93
    int32_t nom, denom;
94
    int i;
95
 
96
    if (count >= INT_MAX / sizeof(int64_t) || count <= 0)
97
        return AVERROR_INVALIDDATA;
98
    if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t))
99
        return AVERROR_INVALIDDATA;
100
 
101
    av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED);
102
 
103
    for (i = 0; i < count; i++) {
104
        nom   = ff_tget_long(gb, le);
105
        denom = ff_tget_long(gb, le);
106
        av_bprintf(&bp, "%s%7i:%-7i", auto_sep(count, sep, i, 4), nom, denom);
107
    }
108
 
109
    if ((i = av_bprint_finalize(&bp, &ap))) {
110
        return i;
111
    }
112
    if (!ap) {
113
        return AVERROR(ENOMEM);
114
    }
115
 
116
    av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);
117
 
118
    return 0;
119
}
120
 
121
 
122
int ff_tadd_long_metadata(int count, const char *name, const char *sep,
123
                          GetByteContext *gb, int le, AVDictionary **metadata)
124
{
125
    AVBPrint bp;
126
    char *ap;
127
    int i;
128
 
129
    if (count >= INT_MAX / sizeof(int32_t) || count <= 0)
130
        return AVERROR_INVALIDDATA;
131
    if (bytestream2_get_bytes_left(gb) < count * sizeof(int32_t))
132
        return AVERROR_INVALIDDATA;
133
 
134
    av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED);
135
 
136
    for (i = 0; i < count; i++) {
137
        av_bprintf(&bp, "%s%7i", auto_sep(count, sep, i, 8), ff_tget_long(gb, le));
138
    }
139
 
140
    if ((i = av_bprint_finalize(&bp, &ap))) {
141
        return i;
142
    }
143
    if (!ap) {
144
        return AVERROR(ENOMEM);
145
    }
146
 
147
    av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);
148
 
149
    return 0;
150
}
151
 
152
 
153
int ff_tadd_doubles_metadata(int count, const char *name, const char *sep,
154
                             GetByteContext *gb, int le, AVDictionary **metadata)
155
{
156
    AVBPrint bp;
157
    char *ap;
158
    int i;
159
 
160
    if (count >= INT_MAX / sizeof(int64_t) || count <= 0)
161
        return AVERROR_INVALIDDATA;
162
    if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t))
163
        return AVERROR_INVALIDDATA;
164
 
165
    av_bprint_init(&bp, 10 * count, 100 * count);
166
 
167
    for (i = 0; i < count; i++) {
168
        av_bprintf(&bp, "%s%f", auto_sep(count, sep, i, 4), ff_tget_double(gb, le));
169
    }
170
 
171
    if ((i = av_bprint_finalize(&bp, &ap))) {
172
        return i;
173
    }
174
    if (!ap) {
175
        return AVERROR(ENOMEM);
176
    }
177
 
178
    av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);
179
 
180
    return 0;
181
}
182
 
183
 
184
int ff_tadd_shorts_metadata(int count, const char *name, const char *sep,
185
                            GetByteContext *gb, int le, AVDictionary **metadata)
186
{
187
    AVBPrint bp;
188
    char *ap;
189
    int i;
190
 
191
    if (count >= INT_MAX / sizeof(int16_t) || count <= 0)
192
        return AVERROR_INVALIDDATA;
193
    if (bytestream2_get_bytes_left(gb) < count * sizeof(int16_t))
194
        return AVERROR_INVALIDDATA;
195
 
196
    av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED);
197
 
198
    for (i = 0; i < count; i++) {
199
        av_bprintf(&bp, "%s%5i", auto_sep(count, sep, i, 8), ff_tget_short(gb, le));
200
    }
201
 
202
    if ((i = av_bprint_finalize(&bp, &ap))) {
203
        return i;
204
    }
205
    if (!ap) {
206
        return AVERROR(ENOMEM);
207
    }
208
 
209
    av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);
210
 
211
    return 0;
212
}
213
 
214
 
215
int ff_tadd_bytes_metadata(int count, const char *name, const char *sep,
216
                           GetByteContext *gb, int le, AVDictionary **metadata)
217
{
218
    AVBPrint bp;
219
    char *ap;
220
    int i;
221
 
222
    if (count >= INT_MAX / sizeof(int8_t) || count < 0)
223
        return AVERROR_INVALIDDATA;
224
    if (bytestream2_get_bytes_left(gb) < count * sizeof(int8_t))
225
        return AVERROR_INVALIDDATA;
226
 
227
    av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED);
228
 
229
    for (i = 0; i < count; i++) {
230
        av_bprintf(&bp, "%s%3i", auto_sep(count, sep, i, 16), bytestream2_get_byte(gb));
231
    }
232
 
233
    if ((i = av_bprint_finalize(&bp, &ap))) {
234
        return i;
235
    }
236
    if (!ap) {
237
        return AVERROR(ENOMEM);
238
    }
239
 
240
    av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL);
241
 
242
    return 0;
243
}
244
 
245
int ff_tadd_string_metadata(int count, const char *name,
246
                            GetByteContext *gb, int le, AVDictionary **metadata)
247
{
248
    char *value;
249
 
250
    if (bytestream2_get_bytes_left(gb) < count || count < 0)
251
        return AVERROR_INVALIDDATA;
252
 
253
    value = av_malloc(count + 1);
254
    if (!value)
255
        return AVERROR(ENOMEM);
256
 
257
    bytestream2_get_bufferu(gb, value, count);
258
    value[count] = 0;
259
 
260
    av_dict_set(metadata, name, value, AV_DICT_DONT_STRDUP_VAL);
261
    return 0;
262
}
263
 
264
 
265
int ff_tdecode_header(GetByteContext *gb, int *le, int *ifd_offset)
266
{
267
    if (bytestream2_get_bytes_left(gb) < 8) {
268
        return AVERROR_INVALIDDATA;
269
    }
270
 
271
    *le = bytestream2_get_le16u(gb);
272
    if (*le == AV_RB16("II")) {
273
        *le = 1;
274
    } else if (*le == AV_RB16("MM")) {
275
        *le = 0;
276
    } else {
277
        return AVERROR_INVALIDDATA;
278
    }
279
 
280
    if (ff_tget_short(gb, *le) != 42) {
281
        return AVERROR_INVALIDDATA;
282
    }
283
 
284
    *ifd_offset = ff_tget_long(gb, *le);
285
 
286
    return 0;
287
}
288
 
289
 
290
int ff_tread_tag(GetByteContext *gb, int le, unsigned *tag, unsigned *type,
291
                 unsigned *count, int *next)
292
{
293
    int ifd_tag;
294
    int valid_type;
295
 
296
    *tag    = ff_tget_short(gb, le);
297
    *type   = ff_tget_short(gb, le);
298
    *count  = ff_tget_long (gb, le);
299
 
300
    ifd_tag    = ff_tis_ifd(*tag);
301
    valid_type = *type != 0 && *type < FF_ARRAY_ELEMS(type_sizes);
302
 
303
    *next = bytestream2_tell(gb) + 4;
304
 
305
    // check for valid type
306
    if (!valid_type) {
307
        return AVERROR_INVALIDDATA;
308
    }
309
 
310
    // seek to offset if this is an IFD-tag or
311
    // if count values do not fit into the offset value
312
    if (ifd_tag || (*count > 4 || !(type_sizes[*type] * (*count) <= 4 || *type == TIFF_STRING))) {
313
        bytestream2_seek(gb, ff_tget_long (gb, le), SEEK_SET);
314
    }
315
 
316
    return 0;
317
}