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
260M
{
91
260M
  if (!buf) return 0;
92
260M
        switch (order) {
93
106M
        case EXIF_BYTE_ORDER_MOTOROLA:
94
106M
                return (((unsigned int)buf[0] << 8) | buf[1]);
95
154M
        case EXIF_BYTE_ORDER_INTEL:
96
154M
                return (((unsigned int)buf[1] << 8) | buf[0]);
97
260M
        }
98
99
  /* Won't be reached */
100
0
  return (0);
101
260M
}
102
103
ExifShort
104
exif_get_short (const unsigned char *buf, ExifByteOrder order)
105
260M
{
106
260M
  return (exif_get_sshort (buf, order) & 0xffff);
107
260M
}
108
109
void
110
exif_set_sshort (unsigned char *b, ExifByteOrder order, ExifSShort value)
111
151k
{
112
151k
  if (!b) return;
113
151k
  switch (order) {
114
5.00k
  case EXIF_BYTE_ORDER_MOTOROLA:
115
5.00k
    b[0] = (unsigned char) (value >> 8);
116
5.00k
    b[1] = (unsigned char) value;
117
5.00k
    break;
118
146k
  case EXIF_BYTE_ORDER_INTEL:
119
146k
    b[0] = (unsigned char) value;
120
146k
    b[1] = (unsigned char) (value >> 8);
121
146k
    break;
122
151k
  }
123
151k
}
124
125
void
126
exif_set_short (unsigned char *b, ExifByteOrder order, ExifShort value)
127
151k
{
128
151k
  exif_set_sshort (b, order, value);
129
151k
}
130
131
ExifSLong
132
exif_get_slong (const unsigned char *b, ExifByteOrder order)
133
70.2M
{
134
70.2M
  if (!b) return 0;
135
70.2M
        switch (order) {
136
69.2M
        case EXIF_BYTE_ORDER_MOTOROLA:
137
69.2M
                return (((uint32_t)b[0] << 24) | ((uint32_t)b[1] << 16) | ((uint32_t)b[2] << 8) | (uint32_t)b[3]);
138
1.01M
        case EXIF_BYTE_ORDER_INTEL:
139
1.01M
                return (((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0]);
140
70.2M
        }
141
142
  /* Won't be reached */
143
0
  return (0);
144
70.2M
}
145
146
void
147
exif_set_slong (unsigned char *b, ExifByteOrder order, ExifSLong value)
148
65.7k
{
149
65.7k
  if (!b) return;
150
65.7k
  switch (order) {
151
8.12k
  case EXIF_BYTE_ORDER_MOTOROLA:
152
8.12k
    b[0] = (unsigned char) (value >> 24);
153
8.12k
    b[1] = (unsigned char) (value >> 16);
154
8.12k
    b[2] = (unsigned char) (value >> 8);
155
8.12k
    b[3] = (unsigned char) value;
156
8.12k
    break;
157
57.6k
  case EXIF_BYTE_ORDER_INTEL:
158
57.6k
    b[3] = (unsigned char) (value >> 24);
159
57.6k
    b[2] = (unsigned char) (value >> 16);
160
57.6k
    b[1] = (unsigned char) (value >> 8);
161
57.6k
    b[0] = (unsigned char) value;
162
57.6k
    break;
163
65.7k
  }
164
65.7k
}
165
166
ExifLong
167
exif_get_long (const unsigned char *buf, ExifByteOrder order)
168
70.0M
{
169
70.0M
        return (exif_get_slong (buf, order) & 0xffffffff);
170
70.0M
}
171
172
void
173
exif_set_long (unsigned char *b, ExifByteOrder order, ExifLong value)
174
61.7k
{
175
61.7k
  exif_set_slong (b, order, value);
176
61.7k
}
177
178
ExifSRational
179
exif_get_srational (const unsigned char *buf, ExifByteOrder order)
180
58.8k
{
181
58.8k
  ExifSRational r;
182
183
58.8k
  r.numerator   = buf ? exif_get_slong (buf, order) : 0;
184
58.8k
  r.denominator = buf ? exif_get_slong (buf + 4, order) : 0;
185
186
58.8k
  return (r);
187
58.8k
}
188
189
ExifRational
190
exif_get_rational (const unsigned char *buf, ExifByteOrder order)
191
91.0k
{
192
91.0k
  ExifRational r;
193
194
91.0k
  r.numerator   = buf ? exif_get_long (buf, order) : 0;
195
91.0k
  r.denominator = buf ? exif_get_long (buf + 4, order) : 0;
196
197
91.0k
  return (r);
198
91.0k
}
199
200
void
201
exif_set_rational (unsigned char *buf, ExifByteOrder order,
202
       ExifRational value)
203
30.8k
{
204
30.8k
  if (!buf) return;
205
30.8k
  exif_set_long (buf, order, value.numerator);
206
30.8k
  exif_set_long (buf + 4, order, value.denominator);
207
30.8k
}
208
209
void
210
exif_set_srational (unsigned char *buf, ExifByteOrder order,
211
        ExifSRational value)
212
2.00k
{
213
2.00k
  if (!buf) return;
214
2.00k
  exif_set_slong (buf, order, value.numerator);
215
2.00k
  exif_set_slong (buf + 4, order, value.denominator);
216
2.00k
}
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
113
{
224
113
  if (maxlen <= 0) {
225
0
    return;
226
0
  }
227
104k
  for (;;) {
228
104k
    ExifShort v = exif_get_short(in, EXIF_BYTE_ORDER_INTEL);
229
104k
    if (!v)
230
83
      break;
231
104k
    if (v < 0x80) {
232
949
      if (maxlen > 1) {
233
939
        *out++ = (char)v;
234
939
        maxlen--;
235
939
      } else {
236
10
        break;
237
10
      }
238
103k
    } else if (v < 0x800) {
239
2.57k
      if (maxlen > 2) {
240
2.56k
        *out++ = ((v >> 6) & 0x1F) | 0xC0;
241
2.56k
        *out++ = (v & 0x3F) | 0x80;
242
2.56k
        maxlen -= 2;
243
2.56k
      } else {
244
10
        break;
245
10
      }
246
101k
    } else {
247
101k
      if (maxlen > 3) {
248
101k
        *out++ = ((v >> 12) & 0x0F) | 0xE0;
249
101k
        *out++ = ((v >> 6) & 0x3F) | 0x80;
250
101k
        *out++ = (v & 0x3F) | 0x80;
251
101k
        maxlen -= 3;
252
101k
      } else {
253
10
        break;
254
10
      }
255
101k
    }
256
104k
    in += 2;
257
104k
  }
258
113
  *out = 0;
259
113
}