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