1/* exif-utils.c 2 * 3 * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301 USA. 19 */ 20 21#include <config.h> 22 23#include <libexif/exif-utils.h> 24 25void 26exif_array_set_byte_order (ExifFormat f, unsigned char *b, unsigned int n, 27 ExifByteOrder o_orig, ExifByteOrder o_new) 28{ 29 unsigned int j; 30 unsigned int fs = exif_format_get_size (f); 31 ExifShort s; 32 ExifSShort ss; 33 ExifLong l; 34 ExifSLong sl; 35 ExifRational r; 36 ExifSRational sr; 37 38 if (!b || !n || !fs) return; 39 40 switch (f) { 41 case EXIF_FORMAT_SHORT: 42 for (j = 0; j < n; j++) { 43 s = exif_get_short (b + j * fs, o_orig); 44 exif_set_short (b + j * fs, o_new, s); 45 } 46 break; 47 case EXIF_FORMAT_SSHORT: 48 for (j = 0; j < n; j++) { 49 ss = exif_get_sshort (b + j * fs, o_orig); 50 exif_set_sshort (b + j * fs, o_new, ss); 51 } 52 break; 53 case EXIF_FORMAT_LONG: 54 for (j = 0; j < n; j++) { 55 l = exif_get_long (b + j * fs, o_orig); 56 exif_set_long (b + j * fs, o_new, l); 57 } 58 break; 59 case EXIF_FORMAT_RATIONAL: 60 for (j = 0; j < n; j++) { 61 r = exif_get_rational (b + j * fs, o_orig); 62 exif_set_rational (b + j * fs, o_new, r); 63 } 64 break; 65 case EXIF_FORMAT_SLONG: 66 for (j = 0; j < n; j++) { 67 sl = exif_get_slong (b + j * fs, o_orig); 68 exif_set_slong (b + j * fs, o_new, sl); 69 } 70 break; 71 case EXIF_FORMAT_SRATIONAL: 72 for (j = 0; j < n; j++) { 73 sr = exif_get_srational (b + j * fs, o_orig); 74 exif_set_srational (b + j * fs, o_new, sr); 75 } 76 break; 77 case EXIF_FORMAT_UNDEFINED: 78 case EXIF_FORMAT_BYTE: 79 case EXIF_FORMAT_ASCII: 80 default: 81 /* Nothing here. */ 82 break; 83 } 84} 85 86ExifSShort 87exif_get_sshort (const unsigned char *buf, ExifByteOrder order) 88{ 89 if (!buf) return 0; 90 switch (order) { 91 case EXIF_BYTE_ORDER_MOTOROLA: 92 return (((unsigned int)buf[0] << 8) | buf[1]); 93 case EXIF_BYTE_ORDER_INTEL: 94 return (((unsigned int)buf[1] << 8) | buf[0]); 95 } 96 97 /* Won't be reached */ 98 return (0); 99} 100 101ExifShort 102exif_get_short (const unsigned char *buf, ExifByteOrder order) 103{ 104 return (exif_get_sshort (buf, order) & 0xffff); 105} 106 107void 108exif_set_sshort (unsigned char *b, ExifByteOrder order, ExifSShort value) 109{ 110 if (!b) return; 111 switch (order) { 112 case EXIF_BYTE_ORDER_MOTOROLA: 113 b[0] = (unsigned char) (value >> 8); 114 b[1] = (unsigned char) value; 115 break; 116 case EXIF_BYTE_ORDER_INTEL: 117 b[0] = (unsigned char) value; 118 b[1] = (unsigned char) (value >> 8); 119 break; 120 } 121} 122 123void 124exif_set_short (unsigned char *b, ExifByteOrder order, ExifShort value) 125{ 126 exif_set_sshort (b, order, value); 127} 128 129ExifSLong 130exif_get_slong (const unsigned char *b, ExifByteOrder order) 131{ 132 if (!b) return 0; 133 switch (order) { 134 case EXIF_BYTE_ORDER_MOTOROLA: 135 return (((uint32_t)b[0] << 24) | ((uint32_t)b[1] << 16) | ((uint32_t)b[2] << 8) | (uint32_t)b[3]); 136 case EXIF_BYTE_ORDER_INTEL: 137 return (((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0]); 138 } 139 140 /* Won't be reached */ 141 return (0); 142} 143 144void 145exif_set_slong (unsigned char *b, ExifByteOrder order, ExifSLong value) 146{ 147 if (!b) return; 148 switch (order) { 149 case EXIF_BYTE_ORDER_MOTOROLA: 150 b[0] = (unsigned char) (value >> 24); 151 b[1] = (unsigned char) (value >> 16); 152 b[2] = (unsigned char) (value >> 8); 153 b[3] = (unsigned char) value; 154 break; 155 case EXIF_BYTE_ORDER_INTEL: 156 b[3] = (unsigned char) (value >> 24); 157 b[2] = (unsigned char) (value >> 16); 158 b[1] = (unsigned char) (value >> 8); 159 b[0] = (unsigned char) value; 160 break; 161 } 162} 163 164ExifLong 165exif_get_long (const unsigned char *buf, ExifByteOrder order) 166{ 167 return (exif_get_slong (buf, order) & 0xffffffff); 168} 169 170void 171exif_set_long (unsigned char *b, ExifByteOrder order, ExifLong value) 172{ 173 exif_set_slong (b, order, value); 174} 175 176ExifSRational 177exif_get_srational (const unsigned char *buf, ExifByteOrder order) 178{ 179 ExifSRational r; 180 181 r.numerator = buf ? exif_get_slong (buf, order) : 0; 182 r.denominator = buf ? exif_get_slong (buf + 4, order) : 0; 183 184 return (r); 185} 186 187ExifRational 188exif_get_rational (const unsigned char *buf, ExifByteOrder order) 189{ 190 ExifRational r; 191 192 r.numerator = buf ? exif_get_long (buf, order) : 0; 193 r.denominator = buf ? exif_get_long (buf + 4, order) : 0; 194 195 return (r); 196} 197 198void 199exif_set_rational (unsigned char *buf, ExifByteOrder order, 200 ExifRational value) 201{ 202 if (!buf) return; 203 exif_set_long (buf, order, value.numerator); 204 exif_set_long (buf + 4, order, value.denominator); 205} 206 207void 208exif_set_srational (unsigned char *buf, ExifByteOrder order, 209 ExifSRational value) 210{ 211 if (!buf) return; 212 exif_set_slong (buf, order, value.numerator); 213 exif_set_slong (buf + 4, order, value.denominator); 214} 215 216/*! This function converts rather UCS-2LE than UTF-16 to UTF-8. 217 * It should really be replaced by iconv(). 218 */ 219void 220exif_convert_utf16_to_utf8 (char *out, const unsigned char *in, int maxlen) 221{ 222 if (maxlen <= 0) { 223 return; 224 } 225 for (;;) { 226 ExifShort v = exif_get_short(in, EXIF_BYTE_ORDER_INTEL); 227 if (!v) 228 break; 229 if (v < 0x80) { 230 if (maxlen > 1) { 231 *out++ = (char)v; 232 maxlen--; 233 } else { 234 break; 235 } 236 } else if (v < 0x800) { 237 if (maxlen > 2) { 238 *out++ = ((v >> 6) & 0x1F) | 0xC0; 239 *out++ = (v & 0x3F) | 0x80; 240 maxlen -= 2; 241 } else { 242 break; 243 } 244 } else { 245 if (maxlen > 3) { 246 *out++ = ((v >> 12) & 0x0F) | 0xE0; 247 *out++ = ((v >> 6) & 0x3F) | 0x80; 248 *out++ = (v & 0x3F) | 0x80; 249 maxlen -= 3; 250 } else { 251 break; 252 } 253 } 254 in += 2; 255 } 256 *out = 0; 257} 258