summaryrefslogtreecommitdiff
path: root/src/libexif/olympus/exif-mnote-data-olympus.c
diff options
context:
space:
mode:
authorscuri <scuri>2009-08-20 12:13:11 +0000
committerscuri <scuri>2009-08-20 12:13:11 +0000
commit35733b87eed86e5228f12fa10c98a3d9d22a6073 (patch)
treeaa7e3c89788c15b925eecdbdf7e9d98291b4f469 /src/libexif/olympus/exif-mnote-data-olympus.c
parent83b3c8b629d96f5fdf754d35d5f4f5369dbfef1d (diff)
*** empty log message ***
Diffstat (limited to 'src/libexif/olympus/exif-mnote-data-olympus.c')
-rw-r--r--src/libexif/olympus/exif-mnote-data-olympus.c152
1 files changed, 122 insertions, 30 deletions
diff --git a/src/libexif/olympus/exif-mnote-data-olympus.c b/src/libexif/olympus/exif-mnote-data-olympus.c
index 02794c5..200a276 100644
--- a/src/libexif/olympus/exif-mnote-data-olympus.c
+++ b/src/libexif/olympus/exif-mnote-data-olympus.c
@@ -1,6 +1,6 @@
/* exif-mnote-data-olympus.c
*
- * Copyright © 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
+ * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -71,13 +71,25 @@ exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val,
return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
}
+
+
+
+/**
+ * @brief save the MnoteData from ne to buf
+ *
+ * @param ne extract the data from this structure
+ * @param *buf write the mnoteData to this buffer (buffer will be allocated)
+ * @param buf_size the size of the buffer
+ */
static void
exif_mnote_data_olympus_save (ExifMnoteData *ne,
unsigned char **buf, unsigned int *buf_size)
{
ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
- unsigned int i, o, s, doff, base = 0, o2 = 6;
- int datao = 0;
+ size_t i, o, s, doff, base = 0, o2 = 6 + 2;
+ size_t datao = 0;
+ unsigned char *t;
+ size_t ts;
if (!n || !buf || !buf_size) return;
@@ -86,29 +98,49 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,
*/
*buf_size = 6 + 2 + 2 + n->count * 12;
switch (n->version) {
- case 0: /* Olympus */
+ case olympusV1:
+ case sanyoV1:
*buf = exif_mem_alloc (ne->mem, *buf_size);
if (!*buf) return;
/* Write the header and the number of entries. */
- strcpy (*buf, "OLYMP");
- o2 += 2;
+ strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":"OLYMP");
+ exif_set_short (*buf + 6, n->order, (ExifShort) 1);
datao = n->offset;
break;
- case 1: /* Nikon v1 */
+ case olympusV2:
+ *buf_size += 8-6 + 4;
+ *buf = exif_mem_alloc (ne->mem, *buf_size);
+ if (!*buf) return;
+
+ /* Write the header and the number of entries. */
+ strcpy ((char *)*buf, "OLYMPUS");
+ exif_set_short (*buf + 8, n->order, (ExifShort) (
+ (n->order == EXIF_BYTE_ORDER_INTEL) ?
+ ('I' << 8) | 'I' :
+ ('M' << 8) | 'M'));
+ exif_set_short (*buf + 10, n->order, (ExifShort) 3);
+ o2 += 4;
+ break;
+ case nikonV1:
base = MNOTE_NIKON1_TAG_BASE;
- *buf_size -= 8;
+
+ /* v1 has offsets based to main IFD, not makernote IFD */
+ datao += n->offset + 10;
+ /* subtract the size here, so the increment in the next case will not harm us */
+ *buf_size -= 8 + 2;
/* Fall through */
- case 2: /* Nikon v2 */
- *buf_size += 8;
+ case nikonV2:
+ *buf_size += 8 + 2;
+ *buf_size += 4; /* Next IFD pointer */
*buf = exif_mem_alloc (ne->mem, *buf_size);
if (!*buf) return;
/* Write the header and the number of entries. */
- strcpy (*buf, "Nikon");
+ strcpy ((char *)*buf, "Nikon");
(*buf)[6] = n->version;
- o2 += 2; *buf_size += 2;
- if (n->version == 2) {
+
+ if (n->version == nikonV2) {
exif_set_short (*buf + 10, n->order, (ExifShort) (
(n->order == EXIF_BYTE_ORDER_INTEL) ?
('I' << 8) | 'I' :
@@ -117,8 +149,13 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,
exif_set_long (*buf + 14, n->order, (ExifShort) 8);
o2 += 2 + 8;
}
- datao = -10;
+ datao -= 10;
+ /* Reset next IFD pointer */
+ exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
break;
+
+ default:
+ return;
}
exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
@@ -136,12 +173,20 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,
o += 8;
s = exif_format_get_size (n->entries[i].format) *
n->entries[i].components;
+ if (s > 65536) {
+ /* Corrupt data: EXIF data size is limited to the
+ * maximum size of a JPEG segment (64 kb).
+ */
+ continue;
+ }
if (s > 4) {
doff = *buf_size;
- *buf_size += s;
- *buf = exif_mem_realloc (ne->mem, *buf,
- sizeof (char) * *buf_size);
- if (!*buf) return;
+ ts = *buf_size + s;
+ t = exif_mem_realloc (ne->mem, *buf,
+ sizeof (char) * ts);
+ if (!t) return;
+ *buf = t;
+ *buf_size = ts;
exif_set_long (*buf + o, n->order, datao + doff);
} else
doff = o;
@@ -162,7 +207,7 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
{
ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
ExifShort c;
- unsigned int i, s, o, o2 = 0, datao = 6, base = 0;
+ size_t i, s, o, o2 = 0, datao = 6, base = 0;
if (!n || !buf) return;
@@ -174,6 +219,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
* a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
* number of entries, and 12 for one entry.
*
+ * Sanyo format is identical and uses identical tags except that
+ * header starts with "SANYO".
+ *
* Nikon headers start with "Nikon" (6 bytes including '\0'),
* version number (1 or 2).
*
@@ -185,13 +233,46 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
* lastly 0x2A.
*/
if (buf_size - n->offset < 22) return;
- if (!memcmp (buf + o2, "OLYMP", 5)) {
+ if (!memcmp (buf + o2, "OLYMP", 6) || !memcmp (buf + o2, "SANYO", 6)) {
exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
- "Parsing Olympus maker note...");
+ "Parsing Olympus/Sanyo maker note v1...");
/* The number of entries is at position 8. */
- n->version = 0;
+ if (!memcmp (buf + o2, "SANYO", 6))
+ n->version = sanyoV1;
+ else
+ n->version = olympusV1;
+ if (buf[o2 + 6] == 1)
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ else if (buf[o2 + 6 + 1] == 1)
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
o2 += 8;
+ if (o2 >= buf_size) return;
+ c = exif_get_short (buf + o2, n->order);
+ if ((!(c & 0xFF)) && (c > 0x500)) {
+ if (n->order == EXIF_BYTE_ORDER_INTEL) {
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+ } else {
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ }
+ }
+
+ } else if (!memcmp (buf + o2, "OLYMPUS", 8)) {
+ /* Olympus S760, S770 */
+ datao = o2;
+ o2 += 8;
+ exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
+ "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
+ buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
+
+ if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+
+ /* The number of entries is at position 8+4. */
+ n->version = olympusV2;
+ o2 += 4;
} else if (!memcmp (buf + o2, "Nikon", 6)) {
o2 += 6;
@@ -199,8 +280,7 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
"Parsing Nikon maker note (0x%02x, %02x, %02x, "
"%02x, %02x, %02x, %02x, %02x)...",
buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
- buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
-
+ buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
/* The first byte is the version. */
if (o2 >= buf_size) return;
n->version = buf[o2];
@@ -210,12 +290,22 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
o2 += 1;
switch (n->version) {
- case 1:
+ case nikonV1:
base = MNOTE_NIKON1_TAG_BASE;
+ /* Fix endianness, if needed */
+ if (o2 >= buf_size) return;
+ c = exif_get_short (buf + o2, n->order);
+ if ((!(c & 0xFF)) && (c > 0x500)) {
+ if (n->order == EXIF_BYTE_ORDER_INTEL) {
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
+ } else {
+ n->order = EXIF_BYTE_ORDER_INTEL;
+ }
+ }
break;
- case 2:
+ case nikonV2:
/* Skip 2 unknown bytes (00 00). */
o2 += 2;
@@ -226,9 +316,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
*/
datao = o2;
if (o2 >= buf_size) return;
- if (!strncmp (&buf[o2], "II", 2))
+ if (!strncmp ((char *)&buf[o2], "II", 2))
n->order = EXIF_BYTE_ORDER_INTEL;
- else if (!strncmp (&buf[o2], "MM", 2))
+ else if (!strncmp ((char *)&buf[o2], "MM", 2))
n->order = EXIF_BYTE_ORDER_MOTOROLA;
else {
exif_log (en->log, EXIF_LOG_CODE_DEBUG,
@@ -254,7 +344,9 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
return;
}
} else if (!memcmp (buf + o2, "\0\x1b", 2)) {
- n->version = 2;
+ n->version = nikonV2;
+ /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
+ n->order = EXIF_BYTE_ORDER_MOTOROLA;
} else {
return;
}
@@ -347,7 +439,7 @@ exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
if (!n) return NULL;
if (i >= n->count) return NULL;
- return mnote_olympus_tag_get_title (n->entries[i].tag);
+ return mnote_olympus_tag_get_description (n->entries[i].tag);
}
static void