diff src/exif.c @ 51:276ea4c98d33

Sat Jun 4 22:24:00 2005 John Ellis <johne@verizon.net> * exif.[ch]: Use glib provided data types and byte order functions for consistency with rest of application. Made several more functions available in the header. Use MakerNote parsing from format_raw.c. * format_canon.[ch]: Changes to match exif.h and format_raw.h. * format_fuji.[ch]: Add support for Fuji EXIF MakerNote. * format_nikon.[ch]: New files, add support for Nikon EXIF MakerNote. * format_raw.[ch]: Add EXIF MakerNote parser functions to gather all camera formats here (similar to existing raw format list). * src/Makefile.am: Add format_nikon.[ch]. ##### Note: GQview CVS on sourceforge is not always up to date, please use ##### ##### an offical release when making enhancements and translation updates. #####
author gqview
date Sun, 05 Jun 2005 02:48:54 +0000
parents aa4c0e1b54b0
children b58cac75ad12
line wrap: on
line diff
--- a/src/exif.c	Sat Jun 04 08:06:47 2005 +0000
+++ b/src/exif.c	Sun Jun 05 02:48:54 2005 +0000
@@ -73,8 +73,6 @@
 #include "format_raw.h"
 #include "ui_fileops.h"
 
-/* makernote parsers */
-#include "format_canon.h"
 
 /*
  *-----------------------------------------------------------------------------
@@ -436,10 +434,6 @@
  *-----------------------------------------------------------------------------
  */
 
-#define BYTE_ORDER_INTEL	1
-#define BYTE_ORDER_MOTOROLA	2
-
-
 #define MARKER_UNKNOWN		0x00
 #define MARKER_SOI		0xD8
 #define MARKER_APP1		0xE1
@@ -461,7 +455,7 @@
 } IFDEntry;
 
 
-static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *list);
+static const ExifMarker *exif_marker_from_tag(guint16 tag, const ExifMarker *list);
 
 /*
  *-----------------------------------------------------------------------------
@@ -469,8 +463,8 @@
  *-----------------------------------------------------------------------------
  */
 
-ExifItem *exif_item_new(ExifFormatType format, unsigned int tag,
-			unsigned int elements, const ExifMarker *marker)
+ExifItem *exif_item_new(ExifFormatType format, guint tag,
+			guint elements, const ExifMarker *marker)
 {
 	ExifItem *item;
 
@@ -495,10 +489,10 @@
 			item->data_len = sizeof(char) * elements;
 			break;
 		case EXIF_FORMAT_SHORT_UNSIGNED:
-			item->data_len = sizeof(unsigned short int) * elements;
+			item->data_len = sizeof(guint16) * elements;
 			break;
 		case EXIF_FORMAT_LONG_UNSIGNED:
-			item->data_len = sizeof(unsigned long int) * elements;
+			item->data_len = sizeof(guint32) * elements;
 			break;
 		case EXIF_FORMAT_RATIONAL_UNSIGNED:
 			item->data_len = sizeof(ExifRational) * elements;
@@ -510,10 +504,10 @@
 			item->data_len = sizeof(char) * elements;
 			break;
 		case EXIF_FORMAT_SHORT:
-			item->data_len = sizeof(short int) * elements;
+			item->data_len = sizeof(gint16) * elements;
 			break;
 		case EXIF_FORMAT_LONG:
-			item->data_len = sizeof(long int) * elements;
+			item->data_len = sizeof(gint32) * elements;
 			break;
 		case EXIF_FORMAT_RATIONAL:
 			item->data_len = sizeof(ExifRational) * elements;
@@ -596,7 +590,7 @@
 	return string;
 }
 
-static gchar *text_list_find_value(ExifTextList *list, gint value)
+static gchar *text_list_find_value(ExifTextList *list, guint value)
 {
 	gchar *result = NULL;
 	gint i;
@@ -618,45 +612,42 @@
  *-------------------------------------------------------------------
  */
 
-static uint16_t get_int16(unsigned char *f, int bo)
+guint16 exif_byte_get_int16(unsigned char *f, ExifByteOrder bo)
 {
-	if (bo == BYTE_ORDER_INTEL)
-		return *f + (*(f+1)<<8);
+	if (bo == EXIF_BYTE_ORDER_INTEL)
+		return GUINT16_FROM_LE(*(guint16*)f);
 	else
-		return ((*f)<<8) + *(f+1);
+		return GUINT16_FROM_BE(*(guint16*)f);
 }
 
-#if 0
-/* not used ? */
-static uint32_t get_int32(unsigned char *f, int bo)
+guint32 exif_byte_get_int32(unsigned char *f, ExifByteOrder bo)
 {
-	if (bo == BYTE_ORDER_INTEL)
-		return get_int16(f, BYTE_ORDER_INTEL) + (get_int16(f+2, BYTE_ORDER_INTEL)<<16);
+	if (bo == EXIF_BYTE_ORDER_INTEL)
+		return GUINT32_FROM_LE(*(guint32*)f);
 	else
-		return (get_int16(f, BYTE_ORDER_MOTOROLA)<<16) + get_int16(f+2, BYTE_ORDER_MOTOROLA);
+		return GUINT32_FROM_BE(*(guint32*)f);
 }
+
+guint16 exif_byte_swab_int16(guint16 n, ExifByteOrder bo)
+{
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+	if (bo == EXIF_BYTE_ORDER_MOTOROLA)
+#else
+	if (bo == EXIF_BYTE_ORDER_INTEL)
 #endif
-
-static uint16_t swab_int16(uint16_t n, int bo)
-{
-#if BYTE_ORDER == LITTLE_ENDIAN
-	if (bo == BYTE_ORDER_MOTOROLA)
-#else
-	if (bo == BYTE_ORDER_INTEL)
-#endif
-		return n>>8 | n<<8 ;
+		return GUINT16_SWAP_LE_BE(n);
 	else
 		return n;
 }
 
-static uint32_t swab_int32(uint32_t n, int bo)
+guint32 exif_byte_swab_int32(guint32 n, ExifByteOrder bo)
 {
-#if BYTE_ORDER == LITTLE_ENDIAN
-	if (bo == BYTE_ORDER_MOTOROLA)
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+	if (bo == EXIF_BYTE_ORDER_MOTOROLA)
 #else
-	if (bo == BYTE_ORDER_INTEL)
+	if (bo == EXIF_BYTE_ORDER_INTEL)
 #endif
-		return n<<24 | n>>24 | (n & 0xFF0000)>>8 | (n & 0xFF00)<<8;
+		return GUINT32_SWAP_LE_BE(n);
 	else
 		return n;
 }
@@ -670,7 +661,7 @@
 static int get_marker_size(unsigned char *f)
 {
 	/* Size is always in Motorola byte order */
-	return get_int16(f+2, BYTE_ORDER_MOTOROLA);
+	return exif_byte_get_int16(f+2, EXIF_BYTE_ORDER_MOTOROLA);
 }
 
 static int goto_next_marker(unsigned char **f, int *size, int *marker)
@@ -713,9 +704,9 @@
  *-------------------------------------------------------------------
  */
 
-static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *list)
+static const ExifMarker *exif_marker_from_tag(guint16 tag, const ExifMarker *list)
 {
-	int i = 0;
+	gint i = 0;
 
 	if (!list) return NULL;
 
@@ -727,18 +718,19 @@
 	return (list[i].tag == 0 ? NULL : &list[i]);
 }
 
-static void rational_from_data(ExifRational *r, void *src, int byte_order)
+static void rational_from_data(ExifRational *r, void *src, ExifByteOrder byte_order)
 {
-	r->num = swab_int32(*(uint32_t*)src, byte_order);
-	r->den = swab_int32(*(uint32_t*)(src + sizeof(uint32_t)), byte_order);
+	r->num = exif_byte_swab_int32(*(guint32*)src, byte_order);
+	r->den = exif_byte_swab_int32(*(guint32*)(src + sizeof(guint32)), byte_order);
 }
 
-void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatType src_format, int byte_order)
+void exif_item_copy_data(ExifItem *item, void *src, guint len,
+			 ExifFormatType src_format, ExifByteOrder byte_order)
 {
-	int bs;
-	int ne;
+	gint bs;
+	gint ne;
 	gpointer dest;
-	int i;
+	gint i;
 
 	bs = ExifFormatList[item->format].size;
 	ne = item->elements;
@@ -768,7 +760,7 @@
 		case EXIF_FORMAT_SHORT:
 			for (i = 0; i < ne; i++)
 				{
-				((short *)dest)[i] = swab_int16(*(uint16_t*)(src + i * bs), byte_order);
+				((guint16 *)dest)[i] = exif_byte_swab_int16(*(guint16*)(src + i * bs), byte_order);
 				}
 			break;
 		case EXIF_FORMAT_LONG_UNSIGNED:
@@ -782,14 +774,16 @@
 				ss = ExifFormatList[src_format].size;
 				for (i = 0; i < ne; i++)
 					{
-					((long *)dest)[i] = (long)swab_int16(*(uint16_t*)(src + i * ss), byte_order);
+					((gint32 *)dest)[i] =
+						(gint32)exif_byte_swab_int16(*(guint16*)(src + i * ss), byte_order);
 					}
 				}
 			else
 				{
 				for (i = 0; i < ne; i++)
 					{
-					((long *)dest)[i] = swab_int32(*(uint32_t*)(src + i * bs), byte_order);
+					((gint32 *)dest)[i] =
+						exif_byte_swab_int32(*(guint32*)(src + i * bs), byte_order);
 					}
 				}
 			break;
@@ -803,7 +797,7 @@
 		case EXIF_FORMAT_FLOAT:
 			for (i = 0; i < ne; i++)
 				{
-				((float *)dest)[i] = swab_int32(*(uint32_t*)(src + i * bs), byte_order);
+				((float *)dest)[i] = exif_byte_swab_int32(*(guint32*)(src + i * bs), byte_order);
 				}
 			break;
 		case EXIF_FORMAT_DOUBLE:
@@ -818,21 +812,21 @@
 		}
 }
 
-static int exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset,
-				int size, int byte_order,
-				const ExifMarker *list)
+static gint exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, guint offset,
+				 guint size, ExifByteOrder byte_order,
+				 const ExifMarker *list)
 {
 	IFDEntry *ent = (IFDEntry*)(tiff+offset);
-	uint32_t swabed_data;
+	guint32 swabed_data;
 	void *data;
-	int data_len;
+	guint data_len;
 	const ExifMarker *marker;
 	ExifItem *item;
 
-	ent->tag = swab_int16(ent->tag, byte_order);
-	ent->format = swab_int16(ent->format, byte_order);
-	ent->nb = swab_int32(ent->nb, byte_order);
-	swabed_data = swab_int32(ent->data, byte_order);
+	ent->tag = exif_byte_swab_int16(ent->tag, byte_order);
+	ent->format = exif_byte_swab_int16(ent->format, byte_order);
+	ent->nb = exif_byte_swab_int32(ent->nb, byte_order);
+	swabed_data = exif_byte_swab_int32(ent->data, byte_order);
 
 	/* Check tag type. If it does not match, either the format is wrong,
 	 * either it is a unknown tag; so it is not really an error.
@@ -866,12 +860,14 @@
 			if (ent->format <= EXIF_FORMAT_DOUBLE)
 				{
 				printf("warning: exif tag %s format mismatch, found %s exif spec requests %s\n",
-					marker->key, ExifFormatList[ent->format].short_name, ExifFormatList[marker->format].short_name);
+					marker->key, ExifFormatList[ent->format].short_name,
+					ExifFormatList[marker->format].short_name);
 				}
 			else
 				{
 				printf("warning: exif tag %s format mismatch, found unknown id %d exif spec requests %d (%s)\n",
-					marker->key, ent->format, marker->format, ExifFormatList[marker->format].short_name);
+					marker->key, ent->format, marker->format,
+					ExifFormatList[marker->format].short_name);
 				}
 			return 0;
 			}
@@ -881,7 +877,8 @@
 	 */
 	if (marker->components > 0 && marker->components != ent->nb)
 		{
-		printf("warning: exif tag %s has %d elements, exif spec requests %d\n", marker->key, ent->nb, marker->components);
+		printf("warning: exif tag %s has %d elements, exif spec requests %d\n",
+			marker->key, ent->nb, marker->components);
 		}
 	data_len = ExifFormatList[marker->format].size * ent->nb;
 	if (data_len > sizeof(ent->data))
@@ -910,7 +907,7 @@
 				exif_parse_IFD_table(exif, tiff, swabed_data, size, byte_order, list);
 				break;
 			case TAG_EXIFMAKERNOTE:
-				format_exif_makernote_canon_parse(exif, tiff, swabed_data, size, byte_order);
+				format_exif_makernote_parse(exif, tiff, swabed_data, size, byte_order);
 				break;
 			}
 		}
@@ -918,17 +915,17 @@
 	return 0;
 }
 
-int exif_parse_IFD_table(ExifData *exif,
-			 unsigned char *tiff, int offset,
-			 int size, int byte_order,
-			 const ExifMarker *list)
+gint exif_parse_IFD_table(ExifData *exif,
+			  unsigned char *tiff, guint offset,
+			  guint size, ExifByteOrder byte_order,
+			  const ExifMarker *list)
 {
-	int i, nb_entries;
+	gint i, nb_entries;
 
 	/* We should be able to read number of entries in IFD0) */
 	if (size < offset+2) return -1;
 
-	nb_entries = get_int16(tiff+offset, byte_order);
+	nb_entries = exif_byte_get_int16(tiff+offset, byte_order);
 
 	/* Entries and next IFD offset must be readable */
 	if (size < offset+nb_entries*12+4) return -1;
@@ -947,9 +944,10 @@
  *-------------------------------------------------------------------
  */
 
-static int parse_TIFF(ExifData *exif, unsigned char *tiff, int size)
+gint exif_parse_TIFF(ExifData *exif, unsigned char *tiff, guint size, ExifMarker *list)
 {
-	int byte_order, offset=0;
+	ExifByteOrder byte_order;
+	guint offset=0;
 
 	if (size < sizeof(TIFFHeader))
 		{
@@ -958,30 +956,30 @@
 
 	if (strncmp(((TIFFHeader*)tiff)->byte_order, "II", 2) == 0)
 		{
-		byte_order = BYTE_ORDER_INTEL;
+		byte_order = EXIF_BYTE_ORDER_INTEL;
 		}
 	else if (strncmp(((TIFFHeader*)tiff)->byte_order, "MM", 2) == 0)
 		{
-		byte_order = BYTE_ORDER_MOTOROLA;
+		byte_order = EXIF_BYTE_ORDER_MOTOROLA;
 		}
 	else
 		{
 		return -1;
 		}
 
-	if (swab_int16(((TIFFHeader*)tiff)->magic, byte_order) != 0x002A)
+	if (exif_byte_swab_int16(((TIFFHeader*)tiff)->magic, byte_order) != 0x002A)
 		{
 		return -1;
 		}
 
-	offset = swab_int32(((TIFFHeader*)tiff)->IFD_offset, byte_order);
+	offset = exif_byte_swab_int32(((TIFFHeader*)tiff)->IFD_offset, byte_order);
 
-	return exif_parse_IFD_table(exif, tiff, offset, size, byte_order, ExifKnownMarkersList);
+	return exif_parse_IFD_table(exif, tiff, offset, size, byte_order, list);
 }
 
-static int parse_JPEG(ExifData *exif, unsigned char *f, int size)
+static gint exif_parse_JPEG(ExifData *exif, unsigned char *f, guint size, ExifMarker *list)
 {
-	int marker, marker_size;
+	guint marker, marker_size;
 
 	if (size<2 || *f!=0xFF || *(f+1)!=MARKER_SOI)
 		{
@@ -1007,7 +1005,7 @@
 		return -2;
 		}
 
-	return parse_TIFF(exif, f+10, marker_size-6);
+	return exif_parse_TIFF(exif, f+10, marker_size-6, list);
 }
 
 static gint map_file(const gchar *path, void **mapping, int *size)
@@ -1090,9 +1088,9 @@
 	exif = g_new0(ExifData, 1);
 	exif->items = NULL;
 
-	if ((res = parse_JPEG(exif, (unsigned char *)f, size)) == -2)
+	if ((res = exif_parse_JPEG(exif, (unsigned char *)f, size, ExifKnownMarkersList)) == -2)
 		{
-		res = parse_TIFF(exif, (unsigned char *)f, size);
+		res = exif_parse_TIFF(exif, (unsigned char *)f, size, ExifKnownMarkersList);
 		}
 
 	if (res != 0)
@@ -1101,7 +1099,7 @@
 		
 		if (format_raw_img_exif_offsets(f, size, NULL, &offset))
 			{
-			res = parse_TIFF(exif, (unsigned char*)f + offset, size - offset);
+			res = exif_parse_TIFF(exif, (unsigned char*)f + offset, size - offset, ExifKnownMarkersList);
 			}
 		}
 
@@ -1180,7 +1178,7 @@
 					val = (unsigned char)(((signed char *)data)[0]);
 					}
 
-				result = text_list_find_value(marker->list, (unsigned short)val);
+				result = text_list_find_value(marker->list, (guint)val);
 				string = g_string_append(string, result);
 				g_free(result);
 				}