Home | History | Annotate | Download | only in libexif
      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