📄 exif.c
字号:
if (format_raw_img_exif_offsets(f, size, NULL, &offset)) { res = exif_tiff_parse(exif, (unsigned char*)f + offset, size - offset, ExifKnownMarkersList); } } if (res != 0) { exif_free(exif); exif = NULL; } unmap_file(f, size); if (exif) exif->items = g_list_reverse(exif->items);#if 0 exif_write_data_list(exif, stdout, TRUE); exif_write_data_list(exif, stdout, FALSE);#endif return exif;}ExifItem *exif_get_item(ExifData *exif, const gchar *key){ GList *work; if (!key) return NULL; work = exif->items; while (work) { ExifItem *item; item = work->data; work = work->next; if (item->marker->key && strcmp(key, item->marker->key) == 0) return item; } return NULL;}gchar *exif_item_get_data_as_text(ExifItem *item){ const ExifMarker *marker; gpointer data; GString *string; gchar *text; gint ne; gint i; if (!item) return NULL; marker = item->marker; if (!marker) return NULL; data = item->data; ne = item->elements; string = g_string_new(""); switch (item->format) { case EXIF_FORMAT_UNKNOWN: break; case EXIF_FORMAT_BYTE_UNSIGNED: case EXIF_FORMAT_BYTE: case EXIF_FORMAT_UNDEFINED: if (ne == 1 && marker->list) { gchar *result; unsigned char val; if (item->format == EXIF_FORMAT_BYTE_UNSIGNED || item->format == EXIF_FORMAT_UNDEFINED) { val = ((unsigned char *)data)[0]; } else { val = (unsigned char)(((signed char *)data)[0]); } result = exif_text_list_find_value(marker->list, (guint)val); string = g_string_append(string, result); g_free(result); } else { string = string_append_raw_bytes(string, data, ne); } break; case EXIF_FORMAT_STRING: string = g_string_append(string, (gchar *)(item->data)); break; case EXIF_FORMAT_SHORT_UNSIGNED: if (ne == 1 && marker->list) { gchar *result; result = exif_text_list_find_value(marker->list, ((unsigned short *)data)[0]); string = g_string_append(string, result); g_free(result); } else for (i = 0; i < ne; i++) { g_string_append_printf(string, "%s%hd", (i > 0) ? ", " : "", ((unsigned short *)data)[i]); } break; case EXIF_FORMAT_LONG_UNSIGNED: for (i = 0; i < ne; i++) { g_string_append_printf(string, "%s%ld", (i > 0) ? ", " : "", ((unsigned long *)data)[i]); } break; case EXIF_FORMAT_RATIONAL_UNSIGNED: for (i = 0; i < ne; i++) { ExifRational *r; r = &((ExifRational *)data)[i]; g_string_append_printf(string, "%s%ld/%ld", (i > 0) ? ", " : "", (unsigned long)r->num, (unsigned long)r->den); } break; case EXIF_FORMAT_SHORT: for (i = 0; i < ne; i++) { g_string_append_printf(string, "%s%hd", (i > 0) ? ", " : "", ((short *)data)[i]); } break; case EXIF_FORMAT_LONG: for (i = 0; i < ne; i++) { g_string_append_printf(string, "%s%ld", (i > 0) ? ", " : "", ((long *)data)[i]); } break; case EXIF_FORMAT_RATIONAL: for (i = 0; i < ne; i++) { ExifRational *r; r = &((ExifRational *)data)[i]; g_string_append_printf(string, "%s%ld/%ld", (i > 0) ? ", " : "", (long)r->num, (long)r->den); } break; case EXIF_FORMAT_FLOAT: for (i = 0; i < ne; i++) { g_string_append_printf(string, "%s%f", (i > 0) ? ", " : "", ((float *)data)[i]); } break; case EXIF_FORMAT_DOUBLE: for (i = 0; i < ne; i++) { g_string_append_printf(string, "%s%f", (i > 0) ? ", " : "", ((double *)data)[i]); } break; } text = g_strdup(string->str); g_string_free(string, TRUE); return text;}gint exif_item_get_integer(ExifItem *item, gint *value){ if (!item) return FALSE; switch (item->format) { case EXIF_FORMAT_SHORT: *value = (gint)(((short *)(item->data))[0]); return TRUE; break; case EXIF_FORMAT_SHORT_UNSIGNED: *value = (gint)(((unsigned short *)(item->data))[0]); return TRUE; break; case EXIF_FORMAT_LONG: *value = (gint)(((long *)(item->data))[0]); return TRUE; break; case EXIF_FORMAT_LONG_UNSIGNED: /* FIXME: overflow possible */ *value = (gint)(((unsigned long *)(item->data))[0]); return TRUE; default: /* all other type return FALSE */ break; } return FALSE;}gint exif_get_integer(ExifData *exif, const gchar *key, gint *value){ ExifItem *item; item = exif_get_item(exif, key); return exif_item_get_integer(item, value);}ExifRational *exif_item_get_rational(ExifItem *item, gint *sign){ if (!item) return NULL; if (item->format == EXIF_FORMAT_RATIONAL || item->format == EXIF_FORMAT_RATIONAL_UNSIGNED) { if (sign) *sign = (item->format == EXIF_FORMAT_RATIONAL); return &((ExifRational *)(item->data))[0]; } return NULL;}ExifRational *exif_get_rational(ExifData *exif, const gchar *key, gint *sign){ ExifItem *item; item = exif_get_item(exif, key); return exif_item_get_rational(item, sign);}double exif_rational_to_double(ExifRational *r, gint sign){ if (!r || r->den == 0.0) return 0.0; if (sign) return (double)((int)r->num) / (double)((int)r->den); return (double)r->num / r->den;}static double exif_get_rational_as_double(ExifData *exif, const gchar *key){ ExifRational *r; gint sign; r = exif_get_rational(exif, key, &sign); return exif_rational_to_double(r, sign);}static GString *append_comma_text(GString *string, const gchar *text){ string = g_string_append(string, ", "); string = g_string_append(string, text); return string;}static gchar *exif_get_formatted_by_key(ExifData *exif, const gchar *key, gint *key_valid){ /* must begin with f, else not formatted */ if (key[0] != 'f') { if (key_valid) *key_valid = FALSE; return NULL; } if (key_valid) *key_valid = TRUE; if (strcmp(key, "fCamera") == 0) { gchar *text; gchar *make = exif_get_data_as_text(exif, "Make"); gchar *model = exif_get_data_as_text(exif, "Model"); gchar *software = exif_get_data_as_text(exif, "Software"); text = g_strdup_printf("%s%s%s%s%s%s", (make) ? make : "", ((make) && (model)) ? " " : "", (model) ? model : "", (software) ? " (" : "", (software) ? software : "", (software) ? ")" : ""); g_free(make); g_free(model); g_free(software); return text; } if (strcmp(key, "fDateTime") == 0) { gchar *text = exif_get_data_as_text(exif, "DateTimeOriginal"); gchar *subsec = NULL; if (text) subsec = exif_get_data_as_text(exif, "SubsecTimeOriginal"); if (!text) { text = exif_get_data_as_text(exif, "DateTime"); if (text) subsec = exif_get_data_as_text(exif, "SubsecTime"); } if (subsec) { gchar *tmp = text; text = g_strconcat(tmp, ".", subsec, NULL); g_free(tmp); g_free(subsec); } return text; } if (strcmp(key, "fShutterSpeed") == 0) { ExifRational *r; r = exif_get_rational(exif, "ExposureTime", NULL); if (r && r->num && r->den) { double n = (double)r->den / (double)r->num; return g_strdup_printf("%s%.0fs", n > 1.0 ? "1/" : "", n > 1.0 ? n : 1.0 / n); } r = exif_get_rational(exif, "ShutterSpeedValue", NULL); if (r && r->num && r->den) { double n = pow(2.0, exif_rational_to_double(r, TRUE)); /* Correct exposure time to avoid values like 1/91s (seen on Minolta DImage 7) */ if (n > 1.0 && (int)n - ((int)(n/10))*10 == 1) n--; return g_strdup_printf("%s%.0fs", n > 1.0 ? "1/" : "", n > 1.0 ? floor(n) : 1.0 / n); } return NULL; } if (strcmp(key, "fAperture") == 0) { double n; n = exif_get_rational_as_double(exif, "FNumber"); if (n == 0.0) n = exif_get_rational_as_double(exif, "ApertureValue"); if (n == 0.0) return NULL; return g_strdup_printf("f/%.1f", n); } if (strcmp(key, "fExposureBias") == 0) { ExifRational *r; gint sign; double n; r = exif_get_rational(exif, "ExposureBiasValue", &sign); if (!r) return NULL; n = exif_rational_to_double(r, sign); return g_strdup_printf("%+.1f", n); } if (strcmp(key, "fFocalLength") == 0) { double n; n = exif_get_rational_as_double(exif, "FocalLength"); if (n == 0.0) return NULL; return g_strdup_printf("%.2f mm", n); } if (strcmp(key, "fISOSpeedRating") == 0) { gchar *text; text = exif_get_data_as_text(exif, "ISOSpeedRatings"); /* kodak may set this instead */ if (!text) text = exif_get_data_as_text(exif, "ExposureIndex"); return text; } if (strcmp(key, "fSubjectDistance") == 0) { ExifRational *r; gint sign; double n; r = exif_get_rational(exif, "SubjectDistance", &sign); if (!r) return NULL; if ((long)r->num == 0xffffffff) return g_strdup(_("infinity")); if ((long)r->num == 0) return g_strdup(_("unknown")); n = exif_rational_to_double(r, sign); if (n == 0.0) return _("unknown"); return g_strdup_printf("%.3f m", n); } if (strcmp(key, "fFlash") == 0) { /* grr, flash is a bitmask... */ GString *string; gchar *text; gint n; gint v; if (!exif_get_integer(exif, "Flash", &n)) return NULL; /* Exif 2.1 only defines first 3 bits */ if (n <= 0x07) return exif_text_list_find_value(ExifFlashList, n); /* must be Exif 2.2 */ string = g_string_new(""); /* flash fired (bit 0) */ string = g_string_append(string, (n & 0x01) ? _("yes") : _("no")); /* flash mode (bits 3, 4) */ v = (n >> 3) & 0x03; if (v) string = append_comma_text(string, _("mode:")); switch (v) { case 1: string = g_string_append(string, _("on")); break; case 2: string = g_string_append(string, _("off")); break; case 3: string = g_string_append(string, _("auto")); break; } /* return light (bits 1, 2) */ v = (n >> 1) & 0x03; if (v == 2) string = append_comma_text(string, _("not detected by strobe")); if (v == 3) string = append_comma_text(string, _("detected by strobe")); /* we ignore flash function (bit 5) */ /* red-eye (bit 6) */ if ((n >> 5) & 0x01) string = append_comma_text(string, _("red-eye reduction")); text = string->str; g_string_free(string, FALSE); return text; } if (strcmp(key, "fResolution") == 0) { ExifRational *rx, *ry; gchar *units; gchar *text; rx = exif_get_rational(exif, "XResolution", NULL); ry = exif_get_rational(exif, "YResolution", NULL); if (!rx || !ry) return NULL; units = exif_get_data_as_text(exif, "ResolutionUnit"); text = g_strdup_printf("%0.f x %0.f (%s/%s)", rx->den ? (double)rx->num / rx->den : 1.0, ry->den ? (double)ry->num / ry->den : 1.0, _("dot"), (units) ? units : _("unknown")); g_free(units); return text; } if (key_valid) *key_valid = FALSE; return NULL;}gchar *exif_get_data_as_text(ExifData *exif, const gchar *key){ ExifItem *item; gchar *text; gint key_valid; if (!key) return NULL; text = exif_get_formatted_by_key(exif, key, &key_valid); if (key_valid) return text; item = exif_get_item(exif, key); if (item) return exif_item_get_data_as_text(item); return NULL;}const gchar *exif_get_description_by_key(const gchar *key){ gint i; if (!key) return NULL; i = 0; while (ExifFormattedList[i].key != NULL) { if (strcmp(key, ExifFormattedList[i].key) == 0) return _(ExifFormattedList[i].description); i++; } i = 0; while (ExifKnownMarkersList[i].tag > 0) { if (strcmp(key, ExifKnownMarkersList[i].key) == 0) return _(ExifKnownMarkersList[i].description); i++; } return NULL;}static void exif_write_item(FILE *f, ExifItem *item){ gchar *text; text = exif_item_get_data_as_text(item); if (text) { fprintf(f, "%4x %9s %30s %s\n", item->tag, ExifFormatList[item->format].short_name, exif_item_get_tag_name(item), text); } g_free(text);}void exif_write_data_list(ExifData *exif, FILE *f, gint human_readable_list){ if (!f || !exif) return; fprintf(f, " tag format key value\n"); fprintf(f, "----------------------------------------------------\n"); if (human_readable_list) { gint i; i = 0; while (ExifFormattedList[i].key) { gchar *text; text = exif_get_formatted_by_key(exif, ExifFormattedList[i].key, NULL); if (text) { fprintf(f, " %9s %30s %s\n", "string", ExifFormattedList[i].key, text); } i++; } } else { GList *work; work = exif->items; while (work) { ExifItem *item; item = work->data; work = work->next; exif_write_item(f, item); } } fprintf(f, "----------------------------------------------------\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -