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
25 void
exif_array_set_byte_order(ExifFormat f,unsigned char * b,unsigned int n,ExifByteOrder o_orig,ExifByteOrder o_new)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
exif_get_sshort(const unsigned char * buf,ExifByteOrder order)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 (((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
101 ExifShort
exif_get_short(const unsigned char * buf,ExifByteOrder order)102 exif_get_short (const unsigned char *buf, ExifByteOrder order)
103 {
104 return (exif_get_sshort (buf, order) & 0xffff);
105 }
106
107 void
exif_set_sshort(unsigned char * b,ExifByteOrder order,ExifSShort value)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
exif_set_short(unsigned char * b,ExifByteOrder order,ExifShort value)124 exif_set_short (unsigned char *b, ExifByteOrder order, ExifShort value)
125 {
126 exif_set_sshort (b, order, value);
127 }
128
129 ExifSLong
exif_get_slong(const unsigned char * b,ExifByteOrder order)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 (((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
144 void
exif_set_slong(unsigned char * b,ExifByteOrder order,ExifSLong value)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
exif_get_long(const unsigned char * buf,ExifByteOrder order)165 exif_get_long (const unsigned char *buf, ExifByteOrder order)
166 {
167 return (exif_get_slong (buf, order) & 0xffffffff);
168 }
169
170 void
exif_set_long(unsigned char * b,ExifByteOrder order,ExifLong value)171 exif_set_long (unsigned char *b, ExifByteOrder order, ExifLong value)
172 {
173 exif_set_slong (b, order, value);
174 }
175
176 ExifSRational
exif_get_srational(const unsigned char * buf,ExifByteOrder order)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
exif_get_rational(const unsigned char * buf,ExifByteOrder order)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
exif_set_rational(unsigned char * buf,ExifByteOrder order,ExifRational value)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
exif_set_srational(unsigned char * buf,ExifByteOrder order,ExifSRational value)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
exif_convert_utf16_to_utf8(char * out,const unsigned char * in,int maxlen)220 exif_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