Compare commits
3 Commits
4cbf9239ee
...
68009c1d3e
Author | SHA1 | Date | |
---|---|---|---|
68009c1d3e | |||
5d659d208c | |||
4d9236336c |
@ -522,9 +522,21 @@ static struct tiff_entry tiff_entries[] = {
|
|||||||
{"ReferenceBlackWhite", 532, NULL},
|
{"ReferenceBlackWhite", 532, NULL},
|
||||||
{"ImageID", 32781, NULL}, // Adobe PageMaker 6.0 TIFF Technical Notes
|
{"ImageID", 32781, NULL}, // Adobe PageMaker 6.0 TIFF Technical Notes
|
||||||
{"Copyright", 33432, NULL},
|
{"Copyright", 33432, NULL},
|
||||||
|
{"Exif IFD Pointer", 34665, NULL}, // Exif 2.3
|
||||||
|
{"GPS Info IFD Pointer", 34853, NULL}, // Exif 2.3
|
||||||
|
{"Interoperability IFD Pointer", 40965, NULL}, // Exif 2.3
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO(p): Consider if these can't be inlined into the above table.
|
||||||
|
static uint16_t tiff_subifd_tags[] = {
|
||||||
|
330, // SubIFDs
|
||||||
|
34665, // Exif IFD Pointer
|
||||||
|
34853, // GPS Info IFD Pointer
|
||||||
|
40965, // Interoperability IFD Pointer
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
// TODO(p): Insert tags and values from other documentation,
|
// TODO(p): Insert tags and values from other documentation,
|
||||||
// so far only tags and non-bit-field values from TIFF 6.0 and PM6 are present.
|
// so far only tags and non-bit-field values from TIFF 6.0 and PM6 are present.
|
||||||
|
|
||||||
@ -594,43 +606,71 @@ parse_exif_ascii(struct tiffer_entry *entry)
|
|||||||
a = jv_array_append(a,
|
a = jv_array_append(a,
|
||||||
jv_string_sized((const char *) entry->p, entry->remaining_count));
|
jv_string_sized((const char *) entry->p, entry->remaining_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(p): May extract this into a function, and reuse it below.
|
|
||||||
if (jv_array_length(jv_copy(a)) == 1)
|
|
||||||
return jv_array_get(a, 0);
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jv
|
||||||
|
parse_exif_undefined(struct tiffer_entry *entry)
|
||||||
|
{
|
||||||
|
const char *alphabet = "0123456789abcdef";
|
||||||
|
char *buf = calloc(1, 2 * entry->remaining_count + 1);
|
||||||
|
for (uint32_t i = 0; i < entry->remaining_count; i++) {
|
||||||
|
buf[2 * i + 0] = alphabet[entry->p[i] >> 4];
|
||||||
|
buf[2 * i + 1] = alphabet[entry->p[i] & 0xF];
|
||||||
|
}
|
||||||
|
jv s = jv_string(buf);
|
||||||
|
free(buf);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jv
|
||||||
|
parse_exif_value(const struct tiff_value *values, double real)
|
||||||
|
{
|
||||||
|
if (values) {
|
||||||
|
for (; values->name; values++)
|
||||||
|
if (values->value == real)
|
||||||
|
return jv_string(values->name);
|
||||||
|
}
|
||||||
|
return jv_number(real);
|
||||||
|
}
|
||||||
|
static jv
|
||||||
|
parse_exif_extract_sole_array_element(jv a)
|
||||||
|
{
|
||||||
|
return jv_array_length(jv_copy(a)) == 1 ? jv_array_get(a, 0) : a;
|
||||||
|
}
|
||||||
|
|
||||||
static jv
|
static jv
|
||||||
parse_exif_entry(jv o, struct tiffer *T, struct tiffer_entry *entry)
|
parse_exif_entry(jv o, struct tiffer *T, struct tiffer_entry *entry)
|
||||||
{
|
{
|
||||||
jv value = jv_true();
|
const struct tiff_entry *info = tiff_entries;
|
||||||
bool numeric = false;
|
for (; info->name; info++)
|
||||||
|
if (info->tag == entry->tag)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bool is_subifd = false;
|
||||||
|
for (const uint16_t *p = tiff_subifd_tags; *p; p++)
|
||||||
|
is_subifd |= *p == entry->tag;
|
||||||
|
|
||||||
|
jv v = jv_true();
|
||||||
double real = 0;
|
double real = 0;
|
||||||
if (!entry->remaining_count) {
|
if (!entry->remaining_count) {
|
||||||
value = jv_null();
|
v = jv_null();
|
||||||
} else if (entry->type == IFD) {
|
} else if (entry->type == IFD || is_subifd) {
|
||||||
value = parse_exif_subifds(T, entry);
|
v = parse_exif_subifds(T, entry);
|
||||||
} else if (entry->type == ASCII) {
|
} else if (entry->type == ASCII) {
|
||||||
value = parse_exif_ascii(entry);
|
v = parse_exif_extract_sole_array_element(parse_exif_ascii(entry));
|
||||||
} else if ((numeric = tiffer_real(T, entry, &real))) {
|
} else if (entry->type == UNDEFINED) {
|
||||||
value = jv_number(real);
|
v = parse_exif_undefined(entry);
|
||||||
|
} else if (tiffer_real(T, entry, &real)) {
|
||||||
|
v = jv_array();
|
||||||
|
do v = jv_array_append(v, parse_exif_value(info->values, real));
|
||||||
|
while (tiffer_next_value(entry) && tiffer_real(T, entry, &real));
|
||||||
|
v = parse_exif_extract_sole_array_element(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(p): Decode UNDEFINED as a hex dump, and iterate over all values.
|
if (info->name)
|
||||||
for (const struct tiff_entry *p = tiff_entries; p->name; p++) {
|
return jv_set(o, jv_string(info->name), v);
|
||||||
if (p->tag != entry->tag)
|
return jv_set(o, jv_string_fmt("%u", entry->tag), v);
|
||||||
continue;
|
|
||||||
|
|
||||||
if (numeric && p->values) {
|
|
||||||
for (const struct tiff_value *q = p->values; q->name; q++) {
|
|
||||||
if (q->value == real)
|
|
||||||
return jv_set(o, jv_string(p->name), jv_string(q->name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return jv_set(o, jv_string(p->name), value);
|
|
||||||
}
|
|
||||||
return jv_set(o, jv_string_fmt("%u", entry->tag), value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static jv
|
static jv
|
||||||
|
Loading…
x
Reference in New Issue
Block a user