diff src/image-load.c @ 1008:68b0cb6ca8f0

use mmaped files image loader implemented new interface for extracting raw previews experiments with previews support in SVN version of Exiv2
author nadvornik
date Thu, 28 Aug 2008 22:26:09 +0000
parents 4fe8f9656107
children dd311dae857a
line wrap: on
line diff
--- a/src/image-load.c	Thu Aug 28 12:51:02 2008 +0000
+++ b/src/image-load.c	Thu Aug 28 22:26:09 2008 +0000
@@ -19,6 +19,7 @@
 #include "ui_fileops.h"
 
 #include <fcntl.h>
+#include <sys/mman.h>
 
 
 static const gchar *image_loader_path(ImageLoader *il)
@@ -155,10 +156,17 @@
 		il->loader = NULL;
 		}
 
-	if (il->load_fd != -1)
+	if (il->mapped_file)
 		{
-		close(il->load_fd);
-		il->load_fd = -1;
+		if (il->preview)
+			{
+			exif_free_preview(il->mapped_file);
+			}
+		else
+			{
+			munmap(il->mapped_file, il->bytes_total);
+			}
+		il->mapped_file = NULL;
 		}
 
 	il->done = TRUE;
@@ -208,7 +216,7 @@
 	c = il->idle_read_loop_count ? il->idle_read_loop_count : 1;
 	while (c > 0)
 		{
-		b = read(il->load_fd, il->read_buffer, il->read_buffer_size);
+		b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read);
 
 		if (b == 0)
 			{
@@ -216,7 +224,7 @@
 			return FALSE;
 			}
 
-		if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->read_buffer, b, NULL)))
+		if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->mapped_file + il->bytes_read, b, NULL)))
 			{
 			image_loader_error(il);
 			return FALSE;
@@ -238,19 +246,10 @@
 static gint image_loader_begin(ImageLoader *il)
 {
 	gint b;
-	guint offset = 0;
 
 	if (!il->loader || il->pixbuf) return FALSE;
 
-	b = read(il->load_fd, il->read_buffer, il->read_buffer_size);
-
-	if (b > 0 &&
-	    format_raw_img_exif_offsets_fd(il->load_fd, image_loader_path(il), il->read_buffer, b, &offset, NULL))
-		{
-		DEBUG_1("Raw file %s contains embedded image", image_loader_path(il));
-
-		b = read(il->load_fd, il->read_buffer, il->read_buffer_size);
-		}
+	b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read);
 
 	if (b < 1)
 		{
@@ -258,19 +257,19 @@
 		return FALSE;
 		}
 
-	if (!gdk_pixbuf_loader_write(il->loader, il->read_buffer, b, NULL))
+	if (!gdk_pixbuf_loader_write(il->loader, il->mapped_file + il->bytes_read, b, NULL))
 		{
 		image_loader_stop(il);
 		return FALSE;
 		}
 
-	il->bytes_read += b + offset;
+	il->bytes_read += b;
 
 	/* read until size is known */
 	while (il->loader && !gdk_pixbuf_loader_get_pixbuf(il->loader) && b > 0)
 		{
-		b = read(il->load_fd, il->read_buffer, il->read_buffer_size);
-		if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->read_buffer, b, NULL)))
+		b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read);
+		if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->mapped_file + il->bytes_read, b, NULL)))
 			{
 			image_loader_stop(il);
 			return FALSE;
@@ -307,18 +306,56 @@
 	struct stat st;
 	gchar *pathl;
 
-	if (!il || il->load_fd != -1 || il->loader) return FALSE;
+	if (!il || il->loader || il->mapped_file) return FALSE;
+
+	il->mapped_file = NULL;
+
+	if (il->fd)
+		{
+		ExifData *exif = exif_read_fd(il->fd);
+
+		il->mapped_file = exif_get_preview(exif, &il->bytes_total);
+		
+		if (il->mapped_file)
+			{
+			il->preview = TRUE;
+			DEBUG_1("Raw file %s contains embedded image", image_loader_path(il));
+			}
+		exif_free_fd(il->fd, exif);
+		}
 
-	pathl = path_from_utf8(image_loader_path(il));
-	il->load_fd = open(pathl, O_RDONLY | O_NONBLOCK);
-	g_free(pathl);
-	if (il->load_fd == -1) return FALSE;
+	
+	if (!il->mapped_file)
+		{
+		/* normal file */
+		gint load_fd;
+	
+		pathl = path_from_utf8(image_loader_path(il));
+		load_fd = open(pathl, O_RDONLY | O_NONBLOCK);
+		g_free(pathl);
+		if (load_fd == -1) return FALSE;
 
-	if (fstat(il->load_fd, &st) == 0)
-		{
-		il->bytes_total = st.st_size;
+		if (fstat(load_fd, &st) == 0)
+			{
+			il->bytes_total = st.st_size;
+			}
+		else
+			{
+			close(load_fd);
+			return FALSE;
+			}
+		
+		il->mapped_file = mmap(0, il->bytes_total, PROT_READ|PROT_WRITE, MAP_PRIVATE, load_fd, 0);
+		close(load_fd);
+		if (il->mapped_file == MAP_FAILED)
+			{
+			il->mapped_file = 0;
+			return FALSE;
+			}
+		il->preview = FALSE;
 		}
 
+
 	il->loader = gdk_pixbuf_loader_new();
 	g_signal_connect(G_OBJECT(il->loader), "area_updated",
 			 G_CALLBACK(image_loader_area_updated_cb), il);
@@ -346,7 +383,6 @@
 	il->idle_priority = G_PRIORITY_DEFAULT_IDLE;
 	il->done = FALSE;
 	il->loader = NULL;
-	il->load_fd = -1;
 
 	il->bytes_read = 0;
 	il->bytes_total = 0;
@@ -355,7 +391,7 @@
 
 	il->idle_read_loop_count = options->image.idle_read_loop_count;
 	il->read_buffer_size = options->image.read_buffer_size;
-	il->read_buffer = g_new(guchar, il->read_buffer_size);
+	il->mapped_file = NULL;
 
 	il->requested_width = 0;
 	il->requested_height = 0;
@@ -383,7 +419,6 @@
 	if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf);
 	if (il->fd) file_data_unref(il->fd);
 	if (il->path) g_free(il->path);
-	if (il->read_buffer) g_free(il->read_buffer);
 	DEBUG_1("freeing image loader %p bytes_read=%d", il, il->bytes_read);
 	g_free(il);
 }