gthumb r2186 - in trunk: . libgthumb src



Author: mjc
Date: Tue Jan 15 13:26:09 2008
New Revision: 2186
URL: http://svn.gnome.org/viewvc/gthumb?rev=2186&view=rev

Log:
2008-01-15  Michael J. Chudobiak  <mjc svn gnome org>

        * libgthumb/gth-exif-utils.h:
        * libgthumb/gth-exiv2-utils.cpp:
        * src/gth-exif-data-viewer.c: (update_metadata):
        Apply customized tag sorting to exiv2 exif metadata. Tweaked version
        of patch by Martin SchmeiÃer <Waschbaehr gmx de>, via ghop.



Modified:
   trunk/ChangeLog
   trunk/libgthumb/gth-exif-utils.h
   trunk/libgthumb/gth-exiv2-utils.cpp
   trunk/src/gth-exif-data-viewer.c

Modified: trunk/libgthumb/gth-exif-utils.h
==============================================================================
--- trunk/libgthumb/gth-exif-utils.h	(original)
+++ trunk/libgthumb/gth-exif-utils.h	Tue Jan 15 13:26:09 2008
@@ -57,7 +57,6 @@
 	GTH_METADATA_CATEGORY_IPTC,
         GTH_METADATA_CATEGORY_XMP_EMBEDDED, 
 	GTH_METADATA_CATEGORY_XMP_SIDECAR,
-	GTH_METADATA_CATEGORY_EXIV2,
 	GTH_METADATA_CATEGORY_GSTREAMER,
         GTH_METADATA_CATEGORY_OTHER, 
         GTH_METADATA_CATEGORIES 

Modified: trunk/libgthumb/gth-exiv2-utils.cpp
==============================================================================
--- trunk/libgthumb/gth-exiv2-utils.cpp	(original)
+++ trunk/libgthumb/gth-exiv2-utils.cpp	Tue Jan 15 13:26:09 2008
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2003 Free Software Foundation, Inc.
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -30,7 +30,6 @@
 #include <string>
 #include <sstream>
 #include <vector>
-#include <iomanip>
 
 #ifdef HAVE_EXIV2_XMP_HPP
 #include <exiv2/xmp.hpp>
@@ -38,6 +37,300 @@
 
 using namespace std;
 
+#define MAX_TAGS_PER_CATEGORY 50
+
+static int exif_tag_category_map[GTH_METADATA_CATEGORIES][MAX_TAGS_PER_CATEGORY] = {
+
+	/* GTH_METADATA_CATEGORY_FILE */
+	/* The filesystem info is generated and inserted by gthumb in the
+	   correct order, so we don't need to sort it. */
+	{ -1 },
+
+	/* GTH_METADATA_CATEGORY_EXIF_CAMERA */
+	/* This is general information about the camera, date and user,
+	   that exists in the IFD0 or EXIF blocks. */
+	{ 
+	271,	//EXIF_TAG_MAKE
+	272,	//EXIF_TAG_MODEL
+	305,	//EXIF_TAG_SOFTWARE
+
+	306,	//EXIF_TAG_DATE_TIME
+	37520,	//EXIF_TAG_SUB_SEC_TIME
+	36867,	//EXIF_TAG_DATE_TIME_ORIGINAL
+	37521,	//EXIF_TAG_SUB_SEC_TIME_ORIGINAL
+	36868,	//EXIF_TAG_DATE_TIME_DIGITIZED
+	37522,	//EXIF_TAG_SUB_SEC_TIME_DIGITIZED
+
+	37510,	//EXIF_TAG_USER_COMMENT
+	270,	//EXIF_TAG_IMAGE_DESCRIPTION
+	315,	//EXIF_TAG_ARTIST
+	33432,	//EXIF_TAG_COPYRIGHT
+
+	42016,	//EXIF_TAG_IMAGE_UNIQUE_ID
+
+	40964,	//EXIF_TAG_RELATED_SOUND_FILE
+	-1 },
+
+	/* GTH_METADATA_CATEGORY_EXIF_CONDITIONS */
+	/* These tags describe the conditions when the photo was taken,
+	   and are located in the IFD0 or EXIF blocks. */
+	{ 
+	34855,	//EXIF_TAG_ISO_SPEED_RATINGS
+	37379,	//EXIF_TAG_BRIGHTNESS_VALUE
+
+	33437,	//EXIF_TAG_FNUMBER
+	37378,	//EXIF_TAG_APERTURE_VALUE
+	37381,	//EXIF_TAG_MAX_APERTURE_VALUE
+
+	33434,	//EXIF_TAG_EXPOSURE_TIME
+	34850,	//EXIF_TAG_EXPOSURE_PROGRAM
+	41493,	//EXIF_TAG_EXPOSURE_INDEX
+	37380,	//EXIF_TAG_EXPOSURE_BIAS_VALUE
+	41986,	//EXIF_TAG_EXPOSURE_MODE
+	37377,	//EXIF_TAG_SHUTTER_SPEED_VALUE
+
+	37383,	//EXIF_TAG_METERING_MODE
+	37384,	//EXIF_TAG_LIGHT_SOURCE
+	41987,	//EXIF_TAG_WHITE_BALANCE
+	37385,	//EXIF_TAG_FLASH
+	41483,	//EXIF_TAG_FLASH_ENERGY
+
+	37382,	//EXIF_TAG_SUBJECT_DISTANCE
+	41996,	//EXIF_TAG_SUBJECT_DISTANCE_RANGE
+	37396,	//EXIF_TAG_SUBJECT_AREA
+	41492,	//EXIF_TAG_SUBJECT_LOCATION
+
+	37386,	//EXIF_TAG_FOCAL_LENGTH
+	41989,	//EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM
+	41486,	//EXIF_TAG_FOCAL_PLANE_X_RESOLUTION
+	41487,	//EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION
+	41488,	//EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT
+
+	41992,	//EXIF_TAG_CONTRAST
+	41993,	//EXIF_TAG_SATURATION
+	41994,	//EXIF_TAG_SHARPNESS
+
+	41729,	//EXIF_TAG_SCENE_TYPE
+	41990,	//EXIF_TAG_SCENE_CAPTURE_TYPE
+
+	41985,	//EXIF_TAG_CUSTOM_RENDERED
+
+	41988,	//EXIF_TAG_DIGITAL_ZOOM_RATIO
+
+	41728,	//EXIF_TAG_FILE_SOURCE
+
+	41495,	//EXIF_TAG_SENSING_METHOD
+	33422,	//EXIF_TAG_CFA_PATTERN	exif.image
+	41730,	//EXIF_TAG_CFA_PATTERN	exif.photo
+
+	41995,	//EXIF_TAG_DEVICE_SETTING_DESCRIPTION
+	34856,	//EXIF_TAG_OECF
+	41484,	//EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE
+	34852,	//EXIF_TAG_SPECTRAL_SENSITIVITY
+	41991,	//EXIF_TAG_GAIN_CONTROL
+
+	  -1 },
+
+	/* GTH_METADATA_CATEGORY_MAKERNOTE */
+	/* These tags are semi-proprietary and vary from manufacturer to
+	   manufacturer, so we don't bother trying to sort them. They are
+	   listed in the order that they appear in the jpeg file. */
+	{ -1 },
+
+	/* GTH_METADATA_CATEGORY_GPS */
+	/* GPS data is stored in a special IFD (GPS) */
+	{ 
+	1,	//EXIF_TAG_GPS_LATITUDE_REF
+	2,	//EXIF_TAG_GPS_LATITUDE
+	3,	//EXIF_TAG_GPS_LONGITUDE_REF
+	4,	//EXIF_TAG_GPS_LONGITUDE
+	5,	//EXIF_TAG_GPS_ALTITUDE_REF
+	6,	//EXIF_TAG_GPS_ALTITUDE
+	7,	//EXIF_TAG_GPS_TIME_STAMP
+	8,	//EXIF_TAG_GPS_SATELLITES
+	9,	//EXIF_TAG_GPS_STATUS
+	10,	//EXIF_TAG_GPS_MEASURE_MODE
+	11,	//EXIF_TAG_GPS_DOP
+	12,	//EXIF_TAG_GPS_SPEED_REF
+	13,	//EXIF_TAG_GPS_SPEED
+	14,	//EXIF_TAG_GPS_TRACK_REF
+	15,	//EXIF_TAG_GPS_TRACK
+	16,	//EXIF_TAG_GPS_IMG_DIRECTION_REF
+	17,	//EXIF_TAG_GPS_IMG_DIRECTION
+	18,	//EXIF_TAG_GPS_MAP_DATUM
+	19,	//EXIF_TAG_GPS_DEST_LATITUDE_REF
+	20,	//EXIF_TAG_GPS_DEST_LATITUDE
+	21,	//EXIF_TAG_GPS_DEST_LONGITUDE_REF
+	22,	//EXIF_TAG_GPS_DEST_LONGITUDE
+	23,	//EXIF_TAG_GPS_DEST_BEARING_REF
+	24,	//EXIF_TAG_GPS_DEST_BEARING
+	25,	//EXIF_TAG_GPS_DEST_DISTANCE_REF
+	26,	//EXIF_TAG_GPS_DEST_DISTANCE
+	27,	//EXIF_TAG_GPS_PROCESSING_METHOD
+	28,	//EXIF_TAG_GPS_AREA_INFORMATION
+	29,	//EXIF_TAG_GPS_DATE_STAMP
+	30,	//EXIF_TAG_GPS_DIFFERENTIAL
+ 	0,	//EXIF_TAG_GPS_VERSION_ID
+	  -1 },
+
+	/* GTH_METADATA_CATEGORY_EXIF_IMAGE */
+	/* These tags describe the main image data structures, and
+	   come from the IFD0 and EXIF blocks. */
+	{
+
+	  // Image data structure
+
+	256,	//EXIF_TAG_IMAGE_WIDTH
+	257,	//EXIF_TAG_IMAGE_LENGTH
+	40962,	//EXIF_TAG_PIXEL_X_DIMENSION
+	40963,	//EXIF_TAG_PIXEL_Y_DIMENSION
+
+	274,	//EXIF_TAG_ORIENTATION
+
+	282,	//EXIF_TAG_X_RESOLUTION
+	283,	//EXIF_TAG_Y_RESOLUTION
+	296,	//EXIF_TAG_RESOLUTION_UNIT
+
+	259,	//EXIF_TAG_COMPRESSION
+
+	277,	//EXIF_TAG_SAMPLES_PER_PIXEL
+	258,	//EXIF_TAG_BITS_PER_SAMPLE
+
+	284,	//EXIF_TAG_PLANAR_CONFIGURATION
+	530,	//EXIF_TAG_YCBCR_SUB_SAMPLING
+	531,	//EXIF_TAG_YCBCR_POSITIONING
+	262,	//EXIF_TAG_PHOTOMETRIC_INTERPRETATION
+	37121,	//EXIF_TAG_COMPONENTS_CONFIGURATION
+	37122,	//EXIF_TAG_COMPRESSED_BITS_PER_PIXEL
+
+	  // Offsets
+
+	273,	//EXIF_TAG_STRIP_OFFSETS
+	278,	//EXIF_TAG_ROWS_PER_STRIP
+	279,	//EXIF_TAG_STRIP_BYTE_COUNTS
+	513,	//EXIF_TAG_JPEG_INTERCHANGE_FORMAT
+	514,	//EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH
+
+	  // Image data characteristics
+
+	301,	//EXIF_TAG_TRANSFER_FUNCTION
+	318,	//EXIF_TAG_WHITE_POINT
+	319,	//EXIF_TAG_PRIMARY_CHROMATICITIES
+	529,	//EXIF_TAG_YCBCR_COEFFICIENTS
+	532,	//EXIF_TAG_REFERENCE_BLACK_WHITE
+
+	40961,	//EXIF_TAG_COLOR_SPACE
+
+	  -1 },
+
+	/* GTH_METADATA_CATEGORY_EXIF_THUMBNAIL */
+	/* There are normally only a few of these tags, so we don't bother
+	   sorting them. They are displayed in the order that they appear in
+	   the file. IFD0 (main image) and IFD1 (thumbnail) share many of the
+	   same tags. The IFD0 tags are sorted by the structures above. The
+	   IFD1 tags are placed into this category. */
+	{ -1 },
+
+	/* GTH_METADATA_CATEGORY_VERSIONS */
+	/* From IFD0, EXIF,or INTEROPERABILITY blocks. */
+	{ 
+	36864,	//EXIF_TAG_EXIF_VERSION
+	40960,	//EXIF_TAG_FLASH_PIX_VERSION
+	1,	//EXIF_TAG_INTEROPERABILITY_INDEX
+	2,	//EXIF_TAG_INTEROPERABILITY_VERSION
+	4096,	//EXIF_TAG_RELATED_IMAGE_FILE_FORMAT
+	4097,	//EXIF_TAG_RELATED_IMAGE_WIDTH
+	4098,	//EXIF_TAG_RELATED_IMAGE_LENGTH
+	  -1 },
+
+        /* GTH_METADATA_CATEGORY_IPTC */
+        /* Reserved for IPTC, not exif */
+        { -1},
+
+	/* GTH_METADATA_CATEGORY_XMP_EMBEDDED */
+	/* Reserved for XMP, not exif */
+	{ -1},
+
+	/* GTH_METADATA_CATEGORY_XMP_SIDECAR */
+	/* Reserved for XMP, not exif */
+	{ -1},
+
+        /* GTH_METADATA_CATEGORY_GSTREAMER */
+        /* Reserved for audio/video stuff, not exif */
+        { -1},
+
+	/* GTH_METADATA_CATEGORY_OTHER */
+	/* New and unrecognized tags automatically go here. */
+	{ -1 }
+};
+
+static GthMetadataCategory
+tag_category_exiv2 (const Exiv2::Exifdatum &md,
+	      int     &position)
+{
+	GthMetadataCategory category;
+	int tempCategory;
+
+	/* Tags that are not explicitly sorted by this function will be sorted
+	   alphabetically by the display functions. This function categorizes 
+	   tags (always) and applies sorting overrides (sometimes). */
+
+	/* Makernotes are easily identified. No special sorting. */
+        if (Exiv2::ExifTags::isMakerIfd(md.ifdId()))
+                return GTH_METADATA_CATEGORY_MAKERNOTE;
+
+	/* Standard (non-Makernote) IFDs are processed here. */
+	switch (md.ifdId()) {
+		/* Some IFDs require special handling to ensure proper categorization.
+		   This is because:
+		   	1) IFD0 and IFD1 may duplicate some tags (with different values)
+			2) Some tag IDs (numeric values) overlap in the GPS and
+			   INTEROPERABILITY IFDs.					*/
+	case Exiv2::ifd1Id:
+		/* Data in IFD1 is for the embedded thumbnail. Keep it separate, do not sort */
+		return GTH_METADATA_CATEGORY_EXIF_THUMBNAIL;
+		break;
+
+	case Exiv2::gpsIfdId:
+		/* Go straight to the GPS category if this is in a GPS IFD, to
+		   avoid the tag ID overlap problem. Do sort. */
+		category = GTH_METADATA_CATEGORY_GPS;
+		break;
+
+	case Exiv2::iopIfdId:
+		/* Go straight to the version category if this is in an
+		   interop IFD, to avoid the tag ID overlap problem. Do sort. */
+		category = GTH_METADATA_CATEGORY_VERSIONS;
+		break;
+
+	default:
+		/* Start the tag search at the beginning, and use the first match */
+		category = (GthMetadataCategory)1;
+	}
+
+	/* Apply sorting overrides by setting the "position" parameter 
+	   to a non-zero value. */
+	while (category < GTH_METADATA_CATEGORIES) {
+		int j = 0;
+		while (exif_tag_category_map[category][j] != -1) {
+			if  (exif_tag_category_map[category][j] == md.tag()) {
+				position = j+1;
+				return category;
+			}
+			j++;
+		}
+		tempCategory = (int)category;
+		++tempCategory;
+		category = (GthMetadataCategory)tempCategory;
+	}
+
+	/* Hmm, didn't recognize that tag! */
+	return GTH_METADATA_CATEGORY_OTHER;
+}
+
+/* Exiv2 sometimes reports numeric values in a fractional
+   form, like "28/5". This function converts such fractions
+   to a more user-friendly decimal form (e.g., 5.6). */
 string improve(string value) {
 	if (value.find('/') != value.npos) {
 		vector<string> res;		
@@ -67,12 +360,14 @@
 	else return value;
 }
 
+/* Add the tag the gThumb metadata store. */
 inline static GList *
 add (GList              *metadata,
      const gchar        *writeable_path, 
      const gchar        *display_name,
      const gchar	*value,
-     GthMetadataCategory category)
+     GthMetadataCategory category,
+     const int		position)
 {
 	GthMetadata *new_entry;
 
@@ -80,8 +375,8 @@
 	new_entry->category = category;
 	new_entry->writeable_path = g_strdup (writeable_path);
 	new_entry->display_name = g_strdup (display_name);
-	new_entry->value = g_strdup (value);
-	new_entry->position = 0;
+	new_entry->value = g_strdup (value);	
+	new_entry->position = position;
 	metadata = g_list_prepend (metadata, new_entry);
 
 	return metadata;
@@ -115,17 +410,9 @@
 			Exiv2::ExifData::const_iterator end = exifData.end();
 			for (Exiv2::ExifData::const_iterator md = exifData.begin(); md != end; ++md) {
 				//determine metadata category
-				GthMetadataCategory cat;
-
-				// FIXME - add category map
-				switch (md->ifdId ()) {
-					//case Exiv2::ifd0Id : cat = GTH_METADATA_CATEGORY_EXIF_IMAGE; break;
-					//case Exiv2::exifIfdId : cat = GTH_METADATA_CATEGORY_EXIF_IMAGE; break;
-					//case Exiv2::iopIfdId : cat = GTH_METADATA_CATEGORY_VERSIONS; break;
-					//case Exiv2::gpsIfdId : cat = GTH_METADATA_CATEGORY_GPS; break;
-					//default : cat = GTH_METADATA_CATEGORY_OTHER; break;
-					default : cat = GTH_METADATA_CATEGORY_EXIV2; break;				
-				}
+				int pos;
+				GthMetadataCategory cat = tag_category_exiv2 (*md, pos);
+				
 				//fill entry
 				stringstream stream;
 				stream << *md;
@@ -140,7 +427,7 @@
 					short_name << md->tagName();	
 				}
 
-				metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), improve(value).c_str(), cat);
+				metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), improve(value).c_str(), cat, pos);
 			}
 		}
 
@@ -160,10 +447,10 @@
 				stringstream value;
 				value << *md;
 
-                                stringstream short_name;
-                                short_name << md->tagName();
+				stringstream short_name;
+				short_name << md->tagName();
 
-				metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), value.str().c_str(), cat);
+				metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), value.str().c_str(), cat, 0);
 			}
 		}
 
@@ -186,7 +473,7 @@
 				stringstream short_name;
 				short_name << md->groupName() << "." << md->tagName();
 
-				metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), value.str().c_str(), cat);
+				metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), value.str().c_str(), cat, 0);
 			}
 		}
 #endif
@@ -206,40 +493,40 @@
 {
 	try {
 #ifdef HAVE_EXIV2_XMP_HPP
-	        Exiv2::DataBuf buf = Exiv2::readFile(uri);
-        	std::string xmpPacket;
-	        xmpPacket.assign(reinterpret_cast<char*>(buf.pData_), buf.size_);
-	        Exiv2::XmpData xmpData;
+		Exiv2::DataBuf buf = Exiv2::readFile(uri);
+		std::string xmpPacket;
+		xmpPacket.assign(reinterpret_cast<char*>(buf.pData_), buf.size_);
+		Exiv2::XmpData xmpData;
 
-	        if (0 != Exiv2::XmpParser::decode(xmpData, xmpPacket))
+		if (0 != Exiv2::XmpParser::decode(xmpData, xmpPacket))
 			return metadata;
 
-	        if (!xmpData.empty()) {
+		if (!xmpData.empty()) {
 
-                        //add xmp-metadata to glist
-                        GthMetadata *new_entry;
-                        Exiv2::XmpData::iterator end = xmpData.end();
-                        for (Exiv2::XmpData::iterator md = xmpData.begin(); md != end; ++md) {
+			//add xmp-metadata to glist
+			GthMetadata *new_entry;
+			Exiv2::XmpData::iterator end = xmpData.end();
+			for (Exiv2::XmpData::iterator md = xmpData.begin(); md != end; ++md) {
 
-                                //determine metadata category
-                                GthMetadataCategory cat = GTH_METADATA_CATEGORY_XMP_SIDECAR;
+				//determine metadata category
+				GthMetadataCategory cat = GTH_METADATA_CATEGORY_XMP_SIDECAR;
 
-                                //fill entry
-                                stringstream value;
-                                value << *md;
+				//fill entry
+				stringstream value;
+				value << *md;
 
-                                stringstream short_name;
-                                short_name << md->groupName() << "." << md->tagName();
+				stringstream short_name;
+				short_name << md->groupName() << "." << md->tagName();
 
-                                metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), value.str().c_str(), cat);
+				metadata = add (metadata, md->key().c_str(), short_name.str().c_str(), value.str().c_str(), cat, 0);
 			}
 		}
-	        Exiv2::XmpParser::terminate();
+		Exiv2::XmpParser::terminate();
 #endif
-	        return metadata;
+		return metadata;
 	} 
 	catch (Exiv2::AnyError& e) {
-	        std::cout << "Caught Exiv2 exception '" << e << "'\n";
-	        return metadata;
+		std::cout << "Caught Exiv2 exception '" << e << "'\n";
+		return metadata;
 	}
 }

Modified: trunk/src/gth-exif-data-viewer.c
==============================================================================
--- trunk/src/gth-exif-data-viewer.c	(original)
+++ trunk/src/gth-exif-data-viewer.c	Tue Jan 15 13:26:09 2008
@@ -60,7 +60,6 @@
 	N_("IPTC"),
         N_("XMP Embedded"),  
 	N_("XMP Sidecar"),
-	N_("Exiv2 Experimental"),
 	N_("Audio / Video"),
         N_("Other")  
 };  
@@ -808,8 +807,8 @@
 	if ( mime_type_is_image (mime_type))
 		metadata = gth_read_exiv2 (uri, metadata);
 
-	if ( mime_type_is (mime_type, "image/jpeg"))
-		metadata = gth_read_exif (uri, metadata, existing_edata);
+	/*if ( mime_type_is (mime_type, "image/jpeg"))
+		metadata = gth_read_exif (uri, metadata, existing_edata);*/
 
 	if ( mime_type_is_audio (mime_type) || mime_type_is_video (mime_type))
 		metadata = gth_read_gstreamer (uri, metadata);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]