• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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