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