2002-04-15 Lutz Müller <lutz@users.sourceforge.net>
authorLutz Mueller <lutz.s.mueller@gmail.com>
Mon, 15 Apr 2002 08:55:02 +0000 (10:55 +0200)
committerLutz Mueller <lutz.s.mueller@gmail.com>
Mon, 15 Apr 2002 08:55:02 +0000 (10:55 +0200)
        Enhancements by Semyon Sosin <sem@best.com>, adapted:

        * libexif/exif-entry.c (exif_entry_get_value): More tags covered.
        * libexif/exif-data.c (exif_data_new_from_file): Don't read the whole
          file into memory.

ChangeLog
libexif/exif-data.c
libexif/exif-entry.c

index c127878..aca9638 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2002-04-15  Lutz Müller <lutz@users.sourceforge.net>
+
+       Enhancements by Semyon Sosin <sem@best.com>, adapted:
+
+       * libexif/exif-entry.c (exif_entry_get_value): More tags covered.
+       * libexif/exif-data.c (exif_data_new_from_file): Don't read the whole
+         file into memory.
+
 2002-04-04  Hans Ulrich Niedermann <gp@n-dimensional.de>
 
        * Makefile.am: dded .tar.bz2 packaging to "make dist"
index d3c2bc2..e926945 100644 (file)
@@ -582,15 +582,41 @@ exif_data_new_from_file (const char *path)
        unsigned int size;
        unsigned char *data;
        ExifData *edata;
+       int marker, ll, lh;
 
        f = fopen (path, "rb");
        if (!f)
                return (NULL);
 
-       /* For now, we read the data into memory. Patches welcome... */
-       fseek (f, 0, SEEK_END);
-       size = ftell (f);
-       fseek (f, 0, SEEK_SET);
+       while (1) {
+               while ((marker = fgetc (f)) == 0xff);
+
+               /* JPEG_MARKER_SOI */
+               if (marker == JPEG_MARKER_SOI)
+                       continue;
+
+               /* JPEG_MARKER_APP0 */
+               if (marker == JPEG_MARKER_APP0) {
+                       lh = fgetc (f);
+                       ll = fgetc (f);
+                       size = (lh << 8) | ll;
+                       if (fseek (f, size - 2, SEEK_CUR) < 0)
+                               return (NULL);
+                       continue;
+               }
+
+               /* JPEG_MARKER_APP1 */
+               if (marker == JPEG_MARKER_APP1)
+                       break;
+
+               /* Unknown marker or data. Give up. */
+               return (NULL);
+       }
+
+       /* EXIF data found. Allocate the necessary memory and read the data. */
+       lh = fgetc (f);
+       ll = fgetc (f);
+       size = (lh << 8) | ll;
        data = malloc (sizeof (char) * size);
        if (!data)
                return (NULL);
@@ -695,6 +721,9 @@ void
 exif_data_foreach_content (ExifData *data, ExifDataForeachContentFunc func,
                           void *user_data)
 {
+       if (!data || !func)
+               return;
+
        func (data->ifd0,                 user_data);
        func (data->ifd1,                 user_data);
        func (data->ifd_exif,             user_data);
index 7a03c7b..007b65a 100644 (file)
@@ -150,6 +150,8 @@ exif_entry_get_value (ExifEntry *e)
        static char v[1024], b[1024];
        const char *c;
        ExifByteOrder o;
+       double d;
+       ExifEntry *entry;
 
        /* We need the byte order */
        if (!e || !e->parent || !e->parent->parent)
@@ -190,20 +192,88 @@ exif_entry_get_value (ExifEntry *e)
                        strncat (v, "[None]", sizeof (v));
                strncat (v, " (Editor)", sizeof (v));
                break;
+       case EXIF_TAG_FNUMBER:
+               CF (e->format, EXIF_FORMAT_RATIONAL, v);
+               CC (e->components, 1, v);
+               v_rat = exif_get_rational (e->data, o);
+               if (!v_rat.denominator)
+                       return (NULL);
+               snprintf (v, sizeof (v), "f/%.01f", (float) v_rat.numerator /
+                                                   (float) v_rat.denominator);
+               break;
        case EXIF_TAG_APERTURE_VALUE:
                CF (e->format, EXIF_FORMAT_RATIONAL, v);
                CC (e->components, 1, v);
                v_rat = exif_get_rational (e->data, o);
-               snprintf (b, sizeof (b), "%i/%i", (int) v_rat.numerator,
-                                                 (int) v_rat.denominator);
-               snprintf (v, sizeof (v), "%s (APEX: f%.01f)", b,
+               if (!v_rat.denominator)
+                       return (NULL);
+               snprintf (v, sizeof (v), "f/%.01f",
                          pow (2 , ((float) v_rat.numerator /
                                    (float) v_rat.denominator) / 2.));
                break;
+       case EXIF_TAG_FOCAL_LENGTH:
+               CF (e->format, EXIF_FORMAT_RATIONAL, v);
+               CC (e->components, 1, v);
+               v_rat = exif_get_rational (e->data, o);
+               if (!v_rat.denominator)
+                       return (NULL);
+
+               /*
+                * For calculation of the 35mm equivalent,
+                * Minolta cameras need a multiplier that depends on the
+                * camera model.
+                */
+               d = 0.;
+               entry = exif_content_get_entry (e->parent->parent->ifd0,
+                                               EXIF_TAG_MAKE);
+               if (entry && entry->data &&
+                   !strncmp (entry->data, "Minolta", 7)) {
+                       entry = exif_content_get_entry (e->parent->parent->ifd0,
+                                                       EXIF_TAG_MODEL);
+                       if (entry && entry->data) {
+                               if (!strncmp (entry->data, "DiMAGE 7", 8))
+                                       d = 3.9;
+                               else if (!strncmp (entry->data, "DiMAGE 5", 8))
+                                       d = 4.9;
+                       }
+               }
+               if (d)
+                       snprintf (b, sizeof (b), _(" (35 equivalent: %d mm)"),
+                                 (int) (d * (double) v_rat.numerator /
+                                            (double) v_rat.denominator));
+
+               snprintf (v, sizeof (v), "%.1f mm%s",
+                         (float) v_rat.numerator / (float) v_rat.denominator,
+                         b);
+               break;
+       case EXIF_TAG_SUBJECT_DISTANCE:
+               CF (e->format, EXIF_FORMAT_RATIONAL, v);
+               CC (e->components, 1, v);
+               v_rat = exif_get_rational (e->data, o);
+               if (!v_rat.denominator)
+                       return (NULL);
+               snprintf (v, sizeof (v), "%.1f m", (float) v_rat.numerator /
+                                                  (float) v_rat.denominator);
+               break;
+       case EXIF_TAG_EXPOSURE_TIME:
+               CF (e->format, EXIF_FORMAT_RATIONAL, v);
+               CC (e->components, 1, v);
+               v_rat = exif_get_rational (e->data, o);
+               if (!v_rat.denominator)
+                       return (NULL);
+               d = (double) v_srat.numerator / (double) v_srat.denominator;
+               if (d < 1)
+                       snprintf (v, sizeof (v), _("1/%d sec."),
+                                 (int) (1. / d));
+               else
+                       snprintf (v, sizeof (v), _("%d sec."), (int) d);
+               break;
        case EXIF_TAG_SHUTTER_SPEED_VALUE:
                CF (e->format, EXIF_FORMAT_SRATIONAL, v);
                CC (e->components, 1, v);
                v_srat = exif_get_srational (e->data, o);
+               if (!v_rat.denominator)
+                       return (NULL);
                snprintf (b, sizeof (b), "%.0f/%.0f sec.",
                          (float) v_srat.numerator, (float) v_srat.denominator);
                snprintf (v, sizeof (v), "%s (APEX: %i)", b,
@@ -493,6 +563,17 @@ exif_entry_get_value (ExifEntry *e)
                        break;
                }
                break;
+       case EXIF_TAG_EXPOSURE_BIAS_VALUE:
+               CF (e->format, EXIF_FORMAT_SRATIONAL, v);
+               CC (e->components, 1, v);
+               v_srat = exif_get_srational (e->data, o);
+               if (!v_srat.denominator)
+                       return (NULL);
+               snprintf (v, sizeof (v), "%s%.01f",
+                         v_srat.denominator * v_srat.numerator > 0 ? "+" : "",
+                         (double) v_srat.numerator /
+                         (double) v_srat.denominator);
+               break;
        case EXIF_TAG_ORIENTATION:
                CF (e->format, EXIF_FORMAT_SHORT, v);
                CC (e->components, 1, v);