1 /* exif-utils.c 2 * 3 * Copyright (c) 2001 Lutz Mueller <lutz (at) 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 25 void 26 exif_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 86 ExifSShort 87 exif_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 ((buf[0] << 8) | buf[1]); 93 case EXIF_BYTE_ORDER_INTEL: 94 return ((buf[1] << 8) | buf[0]); 95 } 96 97 /* Won't be reached */ 98 return (0); 99 } 100 101 ExifShort 102 exif_get_short (const unsigned char *buf, ExifByteOrder order) 103 { 104 return (exif_get_sshort (buf, order) & 0xffff); 105 } 106 107 void 108 exif_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 123 void 124 exif_set_short (unsigned char *b, ExifByteOrder order, ExifShort value) 125 { 126 exif_set_sshort (b, order, value); 127 } 128 129 ExifSLong 130 exif_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 ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); 136 case EXIF_BYTE_ORDER_INTEL: 137 return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]); 138 } 139 140 /* Won't be reached */ 141 return (0); 142 } 143 144 void 145 exif_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 164 ExifLong 165 exif_get_long (const unsigned char *buf, ExifByteOrder order) 166 { 167 return (exif_get_slong (buf, order) & 0xffffffff); 168 } 169 170 void 171 exif_set_long (unsigned char *b, ExifByteOrder order, ExifLong value) 172 { 173 exif_set_slong (b, order, value); 174 } 175 176 ExifSRational 177 exif_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 187 ExifRational 188 exif_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 198 void 199 exif_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 207 void 208 exif_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 */ 219 void 220 exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen) 221 { 222 if (maxlen <= 0) { 223 return; 224 } 225 while (*in) { 226 if (*in < 0x80) { 227 if (maxlen > 1) { 228 *out++ = (char)*in++; 229 maxlen--; 230 } else { 231 break; 232 } 233 } else if (*in < 0x800) { 234 if (maxlen > 2) { 235 *out++ = ((*in >> 6) & 0x1F) | 0xC0; 236 *out++ = (*in++ & 0x3F) | 0x80; 237 maxlen -= 2; 238 } else { 239 break; 240 } 241 } else { 242 if (maxlen > 3) { 243 *out++ = ((*in >> 12) & 0x0F) | 0xE0; 244 *out++ = ((*in >> 6) & 0x3F) | 0x80; 245 *out++ = (*in++ & 0x3F) | 0x80; 246 maxlen -= 3; 247 } else { 248 break; 249 } 250 } 251 } 252 *out = 0; 253 } 254