Mercurial > geeqie
diff src/format_olympus.c @ 101:847e4bc6b54c
Tue Nov 7 15:35:59 2006 John Ellis <johne@verizon.net>
* exif.c: Use new format_raw_exif_offset() function to find Exif in
raw files.
* filelist.c: Add orf and pef to displayed file types.
* format_canon.h, format_fuji.h: Update to new #define format.
* format_fuji.c: Use same offset for Exif as the jpeg image as the
Exif is always embedded in the jpeg and assuming offset of 12 is
just broken.
* format_nikon.h: Update to new #define format, and add pentax here
as finding the jpeg will be same code.
* format_olympus.[ch]: Support Olympus raw files with embedded jpegs,
not all raw files will have a jpeg, but all appear to have Exif tags.
* format_raw.[ch]: Add new camera types, and add a debugging facility
to easily list all tags within tiff files (see format_raw.h to enable).
author | gqview |
---|---|
date | Tue, 07 Nov 2006 21:00:50 +0000 |
parents | deafec7cd99f |
children | 71e1ebee420e |
line wrap: on
line diff
--- a/src/format_olympus.c Tue Nov 07 01:57:19 2006 +0000 +++ b/src/format_olympus.c Tue Nov 07 21:00:50 2006 +0000 @@ -28,6 +28,115 @@ /* *----------------------------------------------------------------------------- + * Raw ORF embedded jpeg extraction for Olympus + *----------------------------------------------------------------------------- + */ + +static guint olympus_tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo, + gint level, + guint *image_offset, guint *exif_offset); + + +static void olympus_tiff_entry(unsigned char *data, const guint len, guint offset, ExifByteOrder bo, + gint level, + guint *image_offset, guint *exif_offset) +{ + guint tag; + guint type; + guint count; + guint segment; + guint seg_len; + + tag = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_TAG, bo); + type = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_FORMAT, bo); + count = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_COUNT, bo); + + /* so far, we only care about tags with type long */ + if (type != EXIF_FORMAT_LONG_UNSIGNED && type != EXIF_FORMAT_LONG) return; + + seg_len = ExifFormatList[type].size * count; + if (seg_len > 4) + { + segment = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_DATA, bo); + if (segment + seg_len > len) return; + } + else + { + segment = offset + EXIF_TIFD_OFFSET_DATA; + } + + if (tag == 0x201) + { + /* start of embedded jpeg, not all olympus cameras embed a jpeg */ + *image_offset = exif_byte_get_int32(data + segment, bo); + } + + if (tag == 0x8769) + { + /* This is the Exif info */ + *exif_offset = exif_byte_get_int32(data + segment, bo); + } +} + +static guint olympus_tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo, + gint level, + guint *image_offset, guint *exif_offset) +{ + guint count; + guint i; + + if (level > EXIF_TIFF_MAX_LEVELS) return 0; + + if (len < offset + 2) return FALSE; + + count = exif_byte_get_int16(data + offset, bo); + offset += 2; + if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0; + + for (i = 0; i < count; i++) + { + olympus_tiff_entry(data, len, offset + i * EXIF_TIFD_SIZE, bo, level, + image_offset, exif_offset); + } + + return exif_byte_get_int32(data + offset + count * EXIF_TIFD_SIZE, bo); +} + +gint format_olympus_raw(unsigned char *data, const guint len, + guint *image_offset, guint *exif_offset) +{ + guint i_off = 0; + guint e_off = 0; + guint offset; + gint level; + + if (len < 8) return FALSE; + + /* these are in tiff file format with a different magick header */ + if (memcmp(data, "IIR", 3) != 0) return FALSE; + + offset = exif_byte_get_int32(data + 4, EXIF_BYTE_ORDER_INTEL); + + level = 0; + while (offset && level < EXIF_TIFF_MAX_LEVELS) + { + offset = olympus_tiff_table(data, len, offset, EXIF_BYTE_ORDER_INTEL, 0, &i_off, &e_off); + level++; + } + + if (i_off != 0 || e_off != 0) + { + if (image_offset) *image_offset = i_off; + if (exif_offset) *exif_offset = e_off; + return TRUE; + } + + return FALSE; +} + + +/* + *----------------------------------------------------------------------------- * EXIF Makernote for Olympus *----------------------------------------------------------------------------- */