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 "libavutil/bprint.h" 29#include "tiff_common.h" 30 31 32int ff_tis_ifd(unsigned tag) 33{ 34 int i; 35 for (i = 0; i < FF_ARRAY_ELEMS(ifd_tags); i++) { 36 if (ifd_tags[i] == tag) { 37 return i + 1; 38 } 39 } 40 return 0; 41} 42 43 44unsigned ff_tget_short(GetByteContext *gb, int le) 45{ 46 return le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb); 47} 48 49 50unsigned ff_tget_long(GetByteContext *gb, int le) 51{ 52 return le ? bytestream2_get_le32(gb) : bytestream2_get_be32(gb); 53} 54 55 56double ff_tget_double(GetByteContext *gb, int le) 57{ 58 av_alias64 i = { .u64 = le ? bytestream2_get_le64(gb) : bytestream2_get_be64(gb)}; 59 return i.f64; 60} 61 62 63unsigned ff_tget(GetByteContext *gb, int type, int le) 64{ 65 switch (type) { 66 case TIFF_BYTE: return bytestream2_get_byte(gb); 67 case TIFF_SHORT: return ff_tget_short(gb, le); 68 case TIFF_LONG: return ff_tget_long(gb, le); 69 default: return UINT_MAX; 70 } 71} 72 73static const char *auto_sep(int count, const char *sep, int i, int columns) 74{ 75 if (sep) 76 return i ? sep : ""; 77 if (i && i%columns) { 78 return ", "; 79 } else 80 return columns < count ? "\n" : ""; 81} 82 83static int bprint_to_avdict(AVBPrint *bp, const char *name, 84 AVDictionary **metadata) 85{ 86 char *ap; 87 int ret; 88 89 if (!av_bprint_is_complete(bp)) { 90 av_bprint_finalize(bp, NULL); 91 return AVERROR(ENOMEM); 92 } 93 if ((ret = av_bprint_finalize(bp, &ap)) < 0) 94 return ret; 95 96 return av_dict_set(metadata, name, ap, AV_DICT_DONT_STRDUP_VAL); 97} 98 99int ff_tadd_rational_metadata(int count, const char *name, const char *sep, 100 GetByteContext *gb, int le, AVDictionary **metadata) 101{ 102 AVBPrint bp; 103 int32_t nom, denom; 104 int i; 105 106 if (count >= INT_MAX / sizeof(int64_t) || count <= 0) 107 return AVERROR_INVALIDDATA; 108 if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t)) 109 return AVERROR_INVALIDDATA; 110 111 av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); 112 113 for (i = 0; i < count; i++) { 114 nom = ff_tget_long(gb, le); 115 denom = ff_tget_long(gb, le); 116 av_bprintf(&bp, "%s%7"PRId32":%-7"PRId32, auto_sep(count, sep, i, 4), nom, denom); 117 } 118 119 return bprint_to_avdict(&bp, name, metadata); 120} 121 122 123int ff_tadd_long_metadata(int count, const char *name, const char *sep, 124 GetByteContext *gb, int le, AVDictionary **metadata) 125{ 126 AVBPrint bp; 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 return bprint_to_avdict(&bp, name, metadata); 141} 142 143 144int ff_tadd_doubles_metadata(int count, const char *name, const char *sep, 145 GetByteContext *gb, int le, AVDictionary **metadata) 146{ 147 AVBPrint bp; 148 int i; 149 150 if (count >= INT_MAX / sizeof(int64_t) || count <= 0) 151 return AVERROR_INVALIDDATA; 152 if (bytestream2_get_bytes_left(gb) < count * sizeof(int64_t)) 153 return AVERROR_INVALIDDATA; 154 155 av_bprint_init(&bp, 10 * count, 100 * count); 156 157 for (i = 0; i < count; i++) { 158 av_bprintf(&bp, "%s%.15g", auto_sep(count, sep, i, 4), ff_tget_double(gb, le)); 159 } 160 161 return bprint_to_avdict(&bp, name, metadata); 162} 163 164 165int ff_tadd_shorts_metadata(int count, const char *name, const char *sep, 166 GetByteContext *gb, int le, int is_signed, AVDictionary **metadata) 167{ 168 AVBPrint bp; 169 int i; 170 171 if (count >= INT_MAX / sizeof(int16_t) || count <= 0) 172 return AVERROR_INVALIDDATA; 173 if (bytestream2_get_bytes_left(gb) < count * sizeof(int16_t)) 174 return AVERROR_INVALIDDATA; 175 176 av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); 177 178 for (i = 0; i < count; i++) { 179 int v = is_signed ? (int16_t)ff_tget_short(gb, le) : ff_tget_short(gb, le); 180 av_bprintf(&bp, "%s%5i", auto_sep(count, sep, i, 8), v); 181 } 182 183 return bprint_to_avdict(&bp, name, metadata); 184} 185 186 187int ff_tadd_bytes_metadata(int count, const char *name, const char *sep, 188 GetByteContext *gb, int le, int is_signed, AVDictionary **metadata) 189{ 190 AVBPrint bp; 191 int i; 192 193 if (count >= INT_MAX / sizeof(int8_t) || count < 0) 194 return AVERROR_INVALIDDATA; 195 if (bytestream2_get_bytes_left(gb) < count * sizeof(int8_t)) 196 return AVERROR_INVALIDDATA; 197 198 av_bprint_init(&bp, 10 * count, AV_BPRINT_SIZE_UNLIMITED); 199 200 for (i = 0; i < count; i++) { 201 int v = is_signed ? (int8_t)bytestream2_get_byte(gb) : bytestream2_get_byte(gb); 202 av_bprintf(&bp, "%s%3i", auto_sep(count, sep, i, 16), v); 203 } 204 205 return bprint_to_avdict(&bp, name, metadata); 206} 207 208int ff_tadd_string_metadata(int count, const char *name, 209 GetByteContext *gb, int le, AVDictionary **metadata) 210{ 211 char *value; 212 213 if (bytestream2_get_bytes_left(gb) < count || count < 0) 214 return AVERROR_INVALIDDATA; 215 216 value = av_malloc(count + 1); 217 if (!value) 218 return AVERROR(ENOMEM); 219 220 bytestream2_get_bufferu(gb, value, count); 221 value[count] = 0; 222 223 av_dict_set(metadata, name, value, AV_DICT_DONT_STRDUP_VAL); 224 return 0; 225} 226 227 228int ff_tdecode_header(GetByteContext *gb, int *le, int *ifd_offset) 229{ 230 if (bytestream2_get_bytes_left(gb) < 8) { 231 return AVERROR_INVALIDDATA; 232 } 233 234 *le = bytestream2_get_le16u(gb); 235 if (*le == AV_RB16("II")) { 236 *le = 1; 237 } else if (*le == AV_RB16("MM")) { 238 *le = 0; 239 } else { 240 return AVERROR_INVALIDDATA; 241 } 242 243 if (ff_tget_short(gb, *le) != 42) { 244 return AVERROR_INVALIDDATA; 245 } 246 247 *ifd_offset = ff_tget_long(gb, *le); 248 249 return 0; 250} 251 252 253int ff_tread_tag(GetByteContext *gb, int le, unsigned *tag, unsigned *type, 254 unsigned *count, int *next) 255{ 256 int ifd_tag; 257 int valid_type; 258 259 *tag = ff_tget_short(gb, le); 260 *type = ff_tget_short(gb, le); 261 *count = ff_tget_long (gb, le); 262 263 ifd_tag = ff_tis_ifd(*tag); 264 valid_type = *type != 0 && *type < FF_ARRAY_ELEMS(type_sizes); 265 266 *next = bytestream2_tell(gb) + 4; 267 268 // check for valid type 269 if (!valid_type) { 270 return AVERROR_INVALIDDATA; 271 } 272 273 // seek to offset if this is an IFD-tag or 274 // if count values do not fit into the offset value 275 if (ifd_tag || (*count > 4 || !(type_sizes[*type] * (*count) <= 4 || *type == TIFF_STRING))) { 276 bytestream2_seek(gb, ff_tget_long (gb, le), SEEK_SET); 277 } 278 279 return 0; 280} 281