diff src/exif.c @ 449:115db540bd0c

read color profiles from jpeg also with Exiv2
author nadvornik
date Sun, 20 Apr 2008 21:35:03 +0000
parents 4b2d7f9af171
children 48c8e49b571c
line wrap: on
line diff
--- a/src/exif.c	Sun Apr 20 21:30:36 2008 +0000
+++ b/src/exif.c	Sun Apr 20 21:35:03 2008 +0000
@@ -992,6 +992,7 @@
 	return exif_parse_IFD_table(exif, tiff, offset, size, bo, 0, list);
 }
 
+
 /*
  *-------------------------------------------------------------------
  * jpeg marker utils
@@ -1015,133 +1016,23 @@
 	     length of NN... == SSSS - 2.
        NNN.: the data in this segment
  */
-
-static gint exif_jpeg_segment_find(unsigned char *data, guint size,
-				   guchar app_marker, const gchar *magic, guint magic_len,
-				   guint *seg_offset, guint *seg_length)
-{
-	guchar marker = 0;
-	guint offset = 0;
-	guint length = 0;
-
-	while (marker != app_marker &&
-	       marker != JPEG_MARKER_EOI)
-		{
-		offset += length;
-		length = 2;
-
-		if (offset + 2 >= size ||
-		    data[offset] != JPEG_MARKER) return FALSE;
-
-		marker = data[offset + 1];
-		if (marker != JPEG_MARKER_SOI &&
-		    marker != JPEG_MARKER_EOI)
-			{
-			if (offset + 4 >= size) return FALSE;
-			length += exif_byte_get_int16(data + offset + 2, EXIF_BYTE_ORDER_MOTOROLA);
-			}
-		}
-
-	if (marker == app_marker &&
-	    offset + length < size &&
-	    length >= 4 + magic_len &&
-	    memcmp(data + offset + 4, magic, magic_len) == 0)
-		{
-		*seg_offset = offset + 4;
-		*seg_length = length - 4;
-		return TRUE;
-		}
-
-	return FALSE;
-}
-
 static ExifMarker jpeg_color_marker = { 0x8773, EXIF_FORMAT_UNDEFINED, -1, "Exif.Image.InterColorProfile", NULL, NULL };
 
-static gint exif_jpeg_parse_color(ExifData *exif, unsigned char *data, guint size)
+void exif_add_jpeg_color_profile(ExifData *exif, unsigned char *cp_data, guint cp_length)
 {
-	guint seg_offset = 0;
-	guint seg_length = 0;
-	guint chunk_offset[255];
-	guint chunk_length[255];
-	guint chunk_count = 0;
-
-	/* For jpeg/jfif, ICC color profile data can be in more than one segment.
-	   the data is in APP2 data segments that start with "ICC_PROFILE\x00\xNN\xTT"
-	   NN = segment number for data
-	   TT = total number of ICC segments (TT in each ICC segment should match)
-	 */
-
-	while (exif_jpeg_segment_find(data + seg_offset + seg_length,
-				      size - seg_offset - seg_length,
-				      JPEG_MARKER_APP2,
-				      "ICC_PROFILE\x00", 12,
-				      &seg_offset, &seg_length))
-		{
-		guchar chunk_num;
-		guchar chunk_tot;
-
-		if (seg_length < 14) return FALSE;
-
-		chunk_num = data[seg_offset + 12];
-		chunk_tot = data[seg_offset + 13];
-
-		if (chunk_num == 0 || chunk_tot == 0) return FALSE;
-
-		if (chunk_count == 0)
-			{
-			guint i;
-
-			chunk_count = (guint)chunk_tot;
-			for (i = 0; i < chunk_count; i++) chunk_offset[i] = 0;
-			for (i = 0; i < chunk_count; i++) chunk_length[i] = 0;
-			}
+	ExifItem *item = exif_item_new(jpeg_color_marker.format, jpeg_color_marker.tag, 1,
+				     &jpeg_color_marker);
+	g_free(item->data);
+	item->data = cp_data;
+	item->elements = cp_length;
+	item->data_len = cp_length;
+	exif->items = g_list_prepend(exif->items, item);
 
-		if (chunk_tot != chunk_count ||
-		    chunk_num > chunk_count) return FALSE;
-
-		chunk_num--;
-		chunk_offset[chunk_num] = seg_offset + 14;
-		chunk_length[chunk_num] = seg_length - 14;
-		}
-
-	if (chunk_count > 0)
-		{
-		ExifItem *item;
-		unsigned char *cp_data;
-		guint cp_length = 0;
-		guint i;
-
-		for (i = 0; i < chunk_count; i++) cp_length += chunk_length[i];
-		cp_data = g_malloc(cp_length);
-
-		for (i = 0; i < chunk_count; i++)
-			{
-			if (chunk_offset[i] == 0)
-				{
-				/* error, we never saw this chunk */
-				g_free(cp_data);
-				return FALSE;
-				}
-			memcpy(cp_data, data + chunk_offset[i], chunk_length[i]);
-			}
-
-		item = exif_item_new(jpeg_color_marker.format, jpeg_color_marker.tag, 1,
-				     &jpeg_color_marker);
-		g_free(item->data);
-		item->data = cp_data;
-		item->elements = cp_length;
-		item->data_len = cp_length;
-		exif->items = g_list_prepend(exif->items, item);
-
-		return TRUE;
-		}
-
-	return FALSE;
 }
 
 static gint exif_jpeg_parse(ExifData *exif,
 			    unsigned char *data, guint size,
-			    ExifMarker *list, gint parse_color)
+			    ExifMarker *list)
 {
 	guint seg_offset = 0;
 	guint seg_length = 0;
@@ -1160,8 +1051,7 @@
 		res = exif_tiff_parse(exif, data + seg_offset + 6, seg_length - 6, list);
 		}
 
-	if (parse_color &&
-	    exif_jpeg_parse_color(exif, data, size))
+	if (exif_jpeg_parse_color(exif, data, size))
 		{
 		res = 0;
 		}
@@ -1169,6 +1059,14 @@
 	return res;
 }
 
+unsigned char *exif_get_color_profile(ExifData *exif, guint *data_len)
+{
+	ExifItem *prof_item = exif_get_item(exif, "Exif.Image.InterColorProfile");
+	if (prof_item && exif_item_get_format_id(prof_item) == EXIF_FORMAT_UNDEFINED)
+		return (unsigned char*) exif_item_get_data(prof_item, data_len);
+	return NULL;
+}
+
 
 /*
  *-------------------------------------------------------------------
@@ -1200,8 +1098,6 @@
 	return NULL;
 }
 
-
-
 static gint map_file(const gchar *path, void **mapping, int *size)
 {
 	int fd;
@@ -1262,7 +1158,7 @@
 	g_free(exif);
 }
 
-ExifData *exif_read(gchar *path, gchar *sidecar_path, gint parse_color_profile)
+ExifData *exif_read(gchar *path, gchar *sidecar_path)
 {
 	ExifData *exif;
 	void *f;
@@ -1284,8 +1180,7 @@
 	exif->current = NULL;
 
 	if ((res = exif_jpeg_parse(exif, (unsigned char *)f, size,
-				   ExifKnownMarkersList,
-				   parse_color_profile)) == -2)
+				   ExifKnownMarkersList)) == -2)
 		{
 		res = exif_tiff_parse(exif, (unsigned char *)f, size, ExifKnownMarkersList);
 		}
@@ -1308,7 +1203,7 @@
 				break;
 			case FORMAT_RAW_EXIF_JPEG:
 				res = exif_jpeg_parse(exif, (unsigned char*)f + offset, size - offset,
-						      ExifKnownMarkersList, FALSE);
+						      ExifKnownMarkersList);
 				break;
 			case FORMAT_RAW_EXIF_IFD_II:
 			case FORMAT_RAW_EXIF_IFD_MM: