147 unsigned char const* buf =
reinterpret_cast<unsigned char const*
>(data);
149 std::size_t offs = 0;
151 bool align_intel =
true;
173 if (buf[0] != 0xFF || buf[1] != 0xD8)
174 throw std::invalid_argument(
"Invalid JPEG signature.");
177 for (offs = 0; offs < len - 1; offs++)
178 if (buf[offs] == 0xFF && buf[offs + 1] == 0xE1)
181 throw std::invalid_argument(
"Cannot find EXIF marker!");
187 throw std::invalid_argument(
"EXIF data corrupt (header)");
190 if (!std::equal(buf + offs, buf + offs + 6,
"Exif\0\0"))
191 throw std::invalid_argument(
"Cannot find EXIF signature");
195 std::size_t tiff_header_offset = offs;
196 if (std::equal(buf + offs, buf + offs + 2,
"II"))
198 else if (std::equal(buf + offs, buf + offs + 2,
"MM"))
201 throw std::invalid_argument(
"Cannot find EXIF byte alignment");
205 uint16_t tiff_magic_number = parse_u16(buf + offs, align_intel);
206 if (tiff_magic_number != 0x2a)
207 throw std::invalid_argument(
"Cannot find TIFF magic bytes");
211 std::size_t first_ifd_offset = parse_u32(buf + offs, align_intel);
212 offs += first_ifd_offset - 4;
220 throw std::invalid_argument(
"EXIF data corrupt (IFD entries)");
221 int num_entries = parse_u16(buf + offs, align_intel);
223 if (num_entries < 0 || num_entries > 10000)
224 throw std::invalid_argument(
"EXIF data corrupt (number of IFDs)");
225 if (offs + 4 + 12 * num_entries > len)
226 throw std::invalid_argument(
"EXIF data corrupt (IFD table)");
238 std::size_t exif_sub_ifd_offset = 0;
240 for (
int i = 0; i < num_entries; ++i)
242 unsigned short tag = parse_u16(buf + offs, align_intel);
243 unsigned short type = parse_u16(buf + offs + 2, align_intel);
244 unsigned int ncomp = parse_u32(buf + offs + 4, align_intel);
245 unsigned int coffs = parse_u32(buf + offs + 8, align_intel);
252 std::size_t buf_off = offs + 8;
253 if (ifd_is_offset(type, ncomp))
254 buf_off = tiff_header_offset + coffs;
255 if (buf_off + ncomp > len)
256 throw std::invalid_argument(
"EXIF data corrupt (IFD entry)");
261 exif_sub_ifd_offset = tiff_header_offset + coffs;
269 if (type == EXIF_TYPE_USHORT)
274 if (type == EXIF_TYPE_USHORT)
275 result.
orientation = parse_u16(buf + buf_off, align_intel);
279 if (type == EXIF_TYPE_ASCII)
280 copy_exif_string(buf + buf_off, ncomp, &result.
camera_maker);
284 if (type == EXIF_TYPE_ASCII)
285 copy_exif_string(buf + buf_off, ncomp, &result.
camera_model);
289 if (type == EXIF_TYPE_ASCII)
290 copy_exif_string(buf + buf_off, ncomp, &result.
date_modified);
294 if (type == EXIF_TYPE_ASCII)
295 copy_exif_string(buf + buf_off, ncomp, &result.
description);
299 if (type == EXIF_TYPE_ASCII)
300 copy_exif_string(buf + buf_off, ncomp, &result.
software);
304 if (type == EXIF_TYPE_ASCII)
305 copy_exif_string(buf + buf_off, ncomp, &result.
copyright);
309 if (type == EXIF_TYPE_ASCII)
310 copy_exif_string(buf + buf_off, ncomp, &result.
artist);
320 if (exif_sub_ifd_offset == 0)
324 offs = exif_sub_ifd_offset;
326 throw std::invalid_argument(
"EXIF data corrupt (SubIFD entries)");
327 num_entries = parse_u16(buf + offs, align_intel);
329 if (num_entries < 0 || num_entries > 10000)
330 throw std::invalid_argument(
"EXIF data corrupt (number of SubIFDs)");
331 if (offs + 4 + 12 * num_entries > len)
332 throw std::invalid_argument(
"EXIF data corrupt (SubIFD table)");
335 for (
int j = 0; j < num_entries; j++)
337 unsigned short tag = parse_u16(buf + offs, align_intel);
338 unsigned short type = parse_u16(buf + offs + 2, align_intel);
339 unsigned int ncomp = parse_u32(buf + offs + 4, align_intel);
340 unsigned int coffs = parse_u32(buf + offs + 8, align_intel);
342 std::size_t buf_off = offs + 8;
343 if (ifd_is_offset(type, ncomp))
344 buf_off = tiff_header_offset + coffs;
345 if (buf_off + ncomp > len)
346 throw std::invalid_argument(
"EXIF data corrupt (SubIFD entry)");
351 if (type == EXIF_TYPE_ASCII)
352 copy_exif_string(buf + buf_off, ncomp, &result.
date_original);
356 if (type == EXIF_TYPE_USHORT)
357 result.
iso_speed = parse_u16(buf + buf_off, align_intel);
361 if (type == EXIF_TYPE_URATIONAL)
362 result.
focal_length = parse_rational_u64(buf + buf_off, align_intel);
366 if (type == EXIF_TYPE_USHORT)
371 if (type == EXIF_TYPE_URATIONAL)
372 result.
f_number = parse_rational_u64(buf + buf_off, align_intel);
376 if (type == EXIF_TYPE_URATIONAL)
377 result.
exposure_time = parse_rational_u64(buf + buf_off, align_intel);
381 if (type == EXIF_TYPE_SRATIONAL)
382 result.
shutter_speed = apex_time_to_exposure(parse_rational_s64(buf + buf_off, align_intel));
386 if (type == EXIF_TYPE_URATIONAL)
387 result.
exposure_bias = parse_rational_u64(buf + buf_off, align_intel);
391 if (type == EXIF_TYPE_USHORT)
392 result.
flash_mode = parse_u16(buf + buf_off, align_intel);
396 if (type == EXIF_TYPE_USHORT)
397 result.
image_width = parse_u16(buf + buf_off, align_intel);
398 if (type == EXIF_TYPE_ULONG)
399 result.
image_width = parse_u32(buf + buf_off, align_intel);
403 if (type == EXIF_TYPE_USHORT)
404 result.
image_height = parse_u16(buf + buf_off, align_intel);
405 if (type == EXIF_TYPE_ULONG)
406 result.
image_height = parse_u32(buf + buf_off, align_intel);
445 int const width = indent ? 22 : 0;
447 << std::setw(width) << std::left <<
"Camera manufacturer: "
449 << std::setw(width) << std::left <<
"Camera model: "
451 << std::setw(width) << std::left <<
"Date (modified): "
453 << std::setw(width) << std::left <<
"Date (original): "
455 << std::setw(width) << std::left <<
"Description: "
457 << std::setw(width) << std::left <<
"Software: "
458 << debug_print(exif.
software) << std::endl
459 << std::setw(width) << std::left <<
"Copyright info: "
460 << debug_print(exif.
copyright) << std::endl
461 << std::setw(width) << std::left <<
"Artist info: "
462 << debug_print(exif.
artist) << std::endl
464 << std::setw(width) << std::left <<
"ISO speed: "
465 << debug_print(exif.
iso_speed) << std::endl
466 << std::setw(width) << std::left <<
"Bits per sample: "
468 << std::setw(width) << std::left <<
"Image Orientation: "
470 << std::setw(width) << std::left <<
"Focal length: "
472 << std::setw(width) << std::left <<
"Focal length (35mm): "
474 << std::setw(width) << std::left <<
"F-Number: "
475 << debug_print(exif.
f_number) << std::endl
476 << std::setw(width) << std::left <<
"Exposure time: "
478 << std::setw(width) << std::left <<
"Exposure bias: "
480 << std::setw(width) << std::left <<
"Shutter speed: "
482 << std::setw(width) << std::left <<
"Flash mode: "
484 << std::setw(width) << std::left <<
"Image width: "
485 << debug_print(exif.
image_width,
" pixel") << std::endl
486 << std::setw(width) << std::left <<
"Image height: "
487 << debug_print(exif.
image_height,
" pixel") << std::endl;