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 * SPDX-License-Identifier: LGPL-2.0-or-later
21 */
22
23 #include <config.h>
24
25 #include <libexif/exif-utils.h>
26
27 void
exif_array_set_byte_order(ExifFormat f,unsigned char * b,unsigned int n,ExifByteOrder o_orig,ExifByteOrder o_new)28 exif_array_set_byte_order (ExifFormat f, unsigned char *b, unsigned int n,
29 ExifByteOrder o_orig, ExifByteOrder o_new)
30 {
31 unsigned int j;
32 unsigned int fs = exif_format_get_size (f);
33 ExifShort s;
34 ExifSShort ss;
35 ExifLong l;
36 ExifSLong sl;
37 ExifRational r;
38 ExifSRational sr;
39
40 if (!b || !n || !fs) return;
41
42 switch (f) {
43 case EXIF_FORMAT_SHORT:
44 for (j = 0; j < n; j++) {
45 s = exif_get_short (b + j * fs, o_orig);
46 exif_set_short (b + j * fs, o_new, s);
47 }
48 break;
49 case EXIF_FORMAT_SSHORT:
50 for (j = 0; j < n; j++) {
51 ss = exif_get_sshort (b + j * fs, o_orig);
52 exif_set_sshort (b + j * fs, o_new, ss);
53 }
54 break;
55 case EXIF_FORMAT_LONG:
56 for (j = 0; j < n; j++) {
57 l = exif_get_long (b + j * fs, o_orig);
58 exif_set_long (b + j * fs, o_new, l);
59 }
60 break;
61 case EXIF_FORMAT_RATIONAL:
62 for (j = 0; j < n; j++) {
63 r = exif_get_rational (b + j * fs, o_orig);
64 exif_set_rational (b + j * fs, o_new, r);
65 }
66 break;
67 case EXIF_FORMAT_SLONG:
68 for (j = 0; j < n; j++) {
69 sl = exif_get_slong (b + j * fs, o_orig);
70 exif_set_slong (b + j * fs, o_new, sl);
71 }
72 break;
73 case EXIF_FORMAT_SRATIONAL:
74 for (j = 0; j < n; j++) {
75 sr = exif_get_srational (b + j * fs, o_orig);
76 exif_set_srational (b + j * fs, o_new, sr);
77 }
78 break;
79 case EXIF_FORMAT_UNDEFINED:
80 case EXIF_FORMAT_BYTE:
81 case EXIF_FORMAT_ASCII:
82 default:
83 /* Nothing here. */
84 break;
85 }
86 }
87
88 ExifSShort
exif_get_sshort(const unsigned char * buf,ExifByteOrder order)89 exif_get_sshort (const unsigned char *buf, ExifByteOrder order)
90 {
91 if (!buf) return 0;
92 switch (order) {
93 case EXIF_BYTE_ORDER_MOTOROLA:
94 return (((unsigned int)buf[0] << 8) | buf[1]);
95 case EXIF_BYTE_ORDER_INTEL:
96 return (((unsigned int)buf[1] << 8) | buf[0]);
97 }
98
99 /* Won't be reached */
100 return (0);
101 }
102
103 ExifShort
exif_get_short(const unsigned char * buf,ExifByteOrder order)104 exif_get_short (const unsigned char *buf, ExifByteOrder order)
105 {
106 return (exif_get_sshort (buf, order) & 0xffff);
107 }
108
109 void
exif_set_sshort(unsigned char * b,ExifByteOrder order,ExifSShort value)110 exif_set_sshort (unsigned char *b, ExifByteOrder order, ExifSShort value)
111 {
112 if (!b) return;
113 switch (order) {
114 case EXIF_BYTE_ORDER_MOTOROLA:
115 b[0] = (unsigned char) (value >> 8);
116 b[1] = (unsigned char) value;
117 break;
118 case EXIF_BYTE_ORDER_INTEL:
119 b[0] = (unsigned char) value;
120 b[1] = (unsigned char) (value >> 8);
121 break;
122 }
123 }
124
125 void
exif_set_short(unsigned char * b,ExifByteOrder order,ExifShort value)126 exif_set_short (unsigned char *b, ExifByteOrder order, ExifShort value)
127 {
128 exif_set_sshort (b, order, value);
129 }
130
131 ExifSLong
exif_get_slong(const unsigned char * b,ExifByteOrder order)132 exif_get_slong (const unsigned char *b, ExifByteOrder order)
133 {
134 if (!b) return 0;
135 switch (order) {
136 case EXIF_BYTE_ORDER_MOTOROLA:
137 return (((uint32_t)b[0] << 24) | ((uint32_t)b[1] << 16) | ((uint32_t)b[2] << 8) | (uint32_t)b[3]);
138 case EXIF_BYTE_ORDER_INTEL:
139 return (((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0]);
140 }
141
142 /* Won't be reached */
143 return (0);
144 }
145
146 void
exif_set_slong(unsigned char * b,ExifByteOrder order,ExifSLong value)147 exif_set_slong (unsigned char *b, ExifByteOrder order, ExifSLong value)
148 {
149 if (!b) return;
150 switch (order) {
151 case EXIF_BYTE_ORDER_MOTOROLA:
152 b[0] = (unsigned char) (value >> 24);
153 b[1] = (unsigned char) (value >> 16);
154 b[2] = (unsigned char) (value >> 8);
155 b[3] = (unsigned char) value;
156 break;
157 case EXIF_BYTE_ORDER_INTEL:
158 b[3] = (unsigned char) (value >> 24);
159 b[2] = (unsigned char) (value >> 16);
160 b[1] = (unsigned char) (value >> 8);
161 b[0] = (unsigned char) value;
162 break;
163 }
164 }
165
166 ExifLong
exif_get_long(const unsigned char * buf,ExifByteOrder order)167 exif_get_long (const unsigned char *buf, ExifByteOrder order)
168 {
169 return (exif_get_slong (buf, order) & 0xffffffff);
170 }
171
172 void
exif_set_long(unsigned char * b,ExifByteOrder order,ExifLong value)173 exif_set_long (unsigned char *b, ExifByteOrder order, ExifLong value)
174 {
175 exif_set_slong (b, order, value);
176 }
177
178 ExifSRational
exif_get_srational(const unsigned char * buf,ExifByteOrder order)179 exif_get_srational (const unsigned char *buf, ExifByteOrder order)
180 {
181 ExifSRational r;
182
183 r.numerator = buf ? exif_get_slong (buf, order) : 0;
184 r.denominator = buf ? exif_get_slong (buf + 4, order) : 0;
185
186 return (r);
187 }
188
189 ExifRational
exif_get_rational(const unsigned char * buf,ExifByteOrder order)190 exif_get_rational (const unsigned char *buf, ExifByteOrder order)
191 {
192 ExifRational r;
193
194 r.numerator = buf ? exif_get_long (buf, order) : 0;
195 r.denominator = buf ? exif_get_long (buf + 4, order) : 0;
196
197 return (r);
198 }
199
200 void
exif_set_rational(unsigned char * buf,ExifByteOrder order,ExifRational value)201 exif_set_rational (unsigned char *buf, ExifByteOrder order,
202 ExifRational value)
203 {
204 if (!buf) return;
205 exif_set_long (buf, order, value.numerator);
206 exif_set_long (buf + 4, order, value.denominator);
207 }
208
209 void
exif_set_srational(unsigned char * buf,ExifByteOrder order,ExifSRational value)210 exif_set_srational (unsigned char *buf, ExifByteOrder order,
211 ExifSRational value)
212 {
213 if (!buf) return;
214 exif_set_slong (buf, order, value.numerator);
215 exif_set_slong (buf + 4, order, value.denominator);
216 }
217
218 /*! This function converts rather UCS-2LE than UTF-16 to UTF-8.
219 * It should really be replaced by iconv().
220 */
221 void
exif_convert_utf16_to_utf8(char * out,const unsigned char * in,int maxlen)222 exif_convert_utf16_to_utf8 (char *out, const unsigned char *in, int maxlen)
223 {
224 if (maxlen <= 0) {
225 return;
226 }
227 for (;;) {
228 ExifShort v = exif_get_short(in, EXIF_BYTE_ORDER_INTEL);
229 if (!v)
230 break;
231 if (v < 0x80) {
232 if (maxlen > 1) {
233 *out++ = (char)v;
234 maxlen--;
235 } else {
236 break;
237 }
238 } else if (v < 0x800) {
239 if (maxlen > 2) {
240 *out++ = ((v >> 6) & 0x1F) | 0xC0;
241 *out++ = (v & 0x3F) | 0x80;
242 maxlen -= 2;
243 } else {
244 break;
245 }
246 } else {
247 if (maxlen > 3) {
248 *out++ = ((v >> 12) & 0x0F) | 0xE0;
249 *out++ = ((v >> 6) & 0x3F) | 0x80;
250 *out++ = (v & 0x3F) | 0x80;
251 maxlen -= 3;
252 } else {
253 break;
254 }
255 }
256 in += 2;
257 }
258 *out = 0;
259 }
260