Coverage Report

Created: 2025-12-10 06:42

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