Mercurial > geeqie.yaz
comparison 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 |
comparison
equal
deleted
inserted
replaced
1007:4303ee1e88ec | 1008:68b0cb6ca8f0 |
---|---|
17 #include "exif.h" | 17 #include "exif.h" |
18 #include "filedata.h" | 18 #include "filedata.h" |
19 #include "ui_fileops.h" | 19 #include "ui_fileops.h" |
20 | 20 |
21 #include <fcntl.h> | 21 #include <fcntl.h> |
22 #include <sys/mman.h> | |
22 | 23 |
23 | 24 |
24 static const gchar *image_loader_path(ImageLoader *il) | 25 static const gchar *image_loader_path(ImageLoader *il) |
25 { | 26 { |
26 if (il->fd) | 27 if (il->fd) |
153 image_loader_sync_pixbuf(il); | 154 image_loader_sync_pixbuf(il); |
154 g_object_unref(G_OBJECT(il->loader)); | 155 g_object_unref(G_OBJECT(il->loader)); |
155 il->loader = NULL; | 156 il->loader = NULL; |
156 } | 157 } |
157 | 158 |
158 if (il->load_fd != -1) | 159 if (il->mapped_file) |
159 { | 160 { |
160 close(il->load_fd); | 161 if (il->preview) |
161 il->load_fd = -1; | 162 { |
163 exif_free_preview(il->mapped_file); | |
164 } | |
165 else | |
166 { | |
167 munmap(il->mapped_file, il->bytes_total); | |
168 } | |
169 il->mapped_file = NULL; | |
162 } | 170 } |
163 | 171 |
164 il->done = TRUE; | 172 il->done = TRUE; |
165 } | 173 } |
166 | 174 |
206 if (il->idle_id == -1) return FALSE; | 214 if (il->idle_id == -1) return FALSE; |
207 | 215 |
208 c = il->idle_read_loop_count ? il->idle_read_loop_count : 1; | 216 c = il->idle_read_loop_count ? il->idle_read_loop_count : 1; |
209 while (c > 0) | 217 while (c > 0) |
210 { | 218 { |
211 b = read(il->load_fd, il->read_buffer, il->read_buffer_size); | 219 b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read); |
212 | 220 |
213 if (b == 0) | 221 if (b == 0) |
214 { | 222 { |
215 image_loader_done(il); | 223 image_loader_done(il); |
216 return FALSE; | 224 return FALSE; |
217 } | 225 } |
218 | 226 |
219 if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->read_buffer, b, NULL))) | 227 if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->mapped_file + il->bytes_read, b, NULL))) |
220 { | 228 { |
221 image_loader_error(il); | 229 image_loader_error(il); |
222 return FALSE; | 230 return FALSE; |
223 } | 231 } |
224 | 232 |
236 } | 244 } |
237 | 245 |
238 static gint image_loader_begin(ImageLoader *il) | 246 static gint image_loader_begin(ImageLoader *il) |
239 { | 247 { |
240 gint b; | 248 gint b; |
241 guint offset = 0; | |
242 | 249 |
243 if (!il->loader || il->pixbuf) return FALSE; | 250 if (!il->loader || il->pixbuf) return FALSE; |
244 | 251 |
245 b = read(il->load_fd, il->read_buffer, il->read_buffer_size); | 252 b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read); |
246 | |
247 if (b > 0 && | |
248 format_raw_img_exif_offsets_fd(il->load_fd, image_loader_path(il), il->read_buffer, b, &offset, NULL)) | |
249 { | |
250 DEBUG_1("Raw file %s contains embedded image", image_loader_path(il)); | |
251 | |
252 b = read(il->load_fd, il->read_buffer, il->read_buffer_size); | |
253 } | |
254 | 253 |
255 if (b < 1) | 254 if (b < 1) |
256 { | 255 { |
257 image_loader_stop(il); | 256 image_loader_stop(il); |
258 return FALSE; | 257 return FALSE; |
259 } | 258 } |
260 | 259 |
261 if (!gdk_pixbuf_loader_write(il->loader, il->read_buffer, b, NULL)) | 260 if (!gdk_pixbuf_loader_write(il->loader, il->mapped_file + il->bytes_read, b, NULL)) |
262 { | 261 { |
263 image_loader_stop(il); | 262 image_loader_stop(il); |
264 return FALSE; | 263 return FALSE; |
265 } | 264 } |
266 | 265 |
267 il->bytes_read += b + offset; | 266 il->bytes_read += b; |
268 | 267 |
269 /* read until size is known */ | 268 /* read until size is known */ |
270 while (il->loader && !gdk_pixbuf_loader_get_pixbuf(il->loader) && b > 0) | 269 while (il->loader && !gdk_pixbuf_loader_get_pixbuf(il->loader) && b > 0) |
271 { | 270 { |
272 b = read(il->load_fd, il->read_buffer, il->read_buffer_size); | 271 b = MIN(il->read_buffer_size, il->bytes_total - il->bytes_read); |
273 if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->read_buffer, b, NULL))) | 272 if (b < 0 || (b > 0 && !gdk_pixbuf_loader_write(il->loader, il->mapped_file + il->bytes_read, b, NULL))) |
274 { | 273 { |
275 image_loader_stop(il); | 274 image_loader_stop(il); |
276 return FALSE; | 275 return FALSE; |
277 } | 276 } |
278 il->bytes_read += b; | 277 il->bytes_read += b; |
305 static gint image_loader_setup(ImageLoader *il) | 304 static gint image_loader_setup(ImageLoader *il) |
306 { | 305 { |
307 struct stat st; | 306 struct stat st; |
308 gchar *pathl; | 307 gchar *pathl; |
309 | 308 |
310 if (!il || il->load_fd != -1 || il->loader) return FALSE; | 309 if (!il || il->loader || il->mapped_file) return FALSE; |
311 | 310 |
312 pathl = path_from_utf8(image_loader_path(il)); | 311 il->mapped_file = NULL; |
313 il->load_fd = open(pathl, O_RDONLY | O_NONBLOCK); | 312 |
314 g_free(pathl); | 313 if (il->fd) |
315 if (il->load_fd == -1) return FALSE; | 314 { |
316 | 315 ExifData *exif = exif_read_fd(il->fd); |
317 if (fstat(il->load_fd, &st) == 0) | 316 |
318 { | 317 il->mapped_file = exif_get_preview(exif, &il->bytes_total); |
319 il->bytes_total = st.st_size; | 318 |
320 } | 319 if (il->mapped_file) |
320 { | |
321 il->preview = TRUE; | |
322 DEBUG_1("Raw file %s contains embedded image", image_loader_path(il)); | |
323 } | |
324 exif_free_fd(il->fd, exif); | |
325 } | |
326 | |
327 | |
328 if (!il->mapped_file) | |
329 { | |
330 /* normal file */ | |
331 gint load_fd; | |
332 | |
333 pathl = path_from_utf8(image_loader_path(il)); | |
334 load_fd = open(pathl, O_RDONLY | O_NONBLOCK); | |
335 g_free(pathl); | |
336 if (load_fd == -1) return FALSE; | |
337 | |
338 if (fstat(load_fd, &st) == 0) | |
339 { | |
340 il->bytes_total = st.st_size; | |
341 } | |
342 else | |
343 { | |
344 close(load_fd); | |
345 return FALSE; | |
346 } | |
347 | |
348 il->mapped_file = mmap(0, il->bytes_total, PROT_READ|PROT_WRITE, MAP_PRIVATE, load_fd, 0); | |
349 close(load_fd); | |
350 if (il->mapped_file == MAP_FAILED) | |
351 { | |
352 il->mapped_file = 0; | |
353 return FALSE; | |
354 } | |
355 il->preview = FALSE; | |
356 } | |
357 | |
321 | 358 |
322 il->loader = gdk_pixbuf_loader_new(); | 359 il->loader = gdk_pixbuf_loader_new(); |
323 g_signal_connect(G_OBJECT(il->loader), "area_updated", | 360 g_signal_connect(G_OBJECT(il->loader), "area_updated", |
324 G_CALLBACK(image_loader_area_updated_cb), il); | 361 G_CALLBACK(image_loader_area_updated_cb), il); |
325 g_signal_connect(G_OBJECT(il->loader), "size_prepared", | 362 g_signal_connect(G_OBJECT(il->loader), "size_prepared", |
344 il->pixbuf = NULL; | 381 il->pixbuf = NULL; |
345 il->idle_id = -1; | 382 il->idle_id = -1; |
346 il->idle_priority = G_PRIORITY_DEFAULT_IDLE; | 383 il->idle_priority = G_PRIORITY_DEFAULT_IDLE; |
347 il->done = FALSE; | 384 il->done = FALSE; |
348 il->loader = NULL; | 385 il->loader = NULL; |
349 il->load_fd = -1; | |
350 | 386 |
351 il->bytes_read = 0; | 387 il->bytes_read = 0; |
352 il->bytes_total = 0; | 388 il->bytes_total = 0; |
353 | 389 |
354 il->idle_done_id = -1; | 390 il->idle_done_id = -1; |
355 | 391 |
356 il->idle_read_loop_count = options->image.idle_read_loop_count; | 392 il->idle_read_loop_count = options->image.idle_read_loop_count; |
357 il->read_buffer_size = options->image.read_buffer_size; | 393 il->read_buffer_size = options->image.read_buffer_size; |
358 il->read_buffer = g_new(guchar, il->read_buffer_size); | 394 il->mapped_file = NULL; |
359 | 395 |
360 il->requested_width = 0; | 396 il->requested_width = 0; |
361 il->requested_height = 0; | 397 il->requested_height = 0; |
362 il->shrunk = FALSE; | 398 il->shrunk = FALSE; |
363 DEBUG_1("new image loader %p, bufsize=%u idle_loop=%u", il, il->read_buffer_size, il->idle_read_loop_count); | 399 DEBUG_1("new image loader %p, bufsize=%u idle_loop=%u", il, il->read_buffer_size, il->idle_read_loop_count); |
381 image_loader_stop(il); | 417 image_loader_stop(il); |
382 if (il->idle_done_id != -1) g_source_remove(il->idle_done_id); | 418 if (il->idle_done_id != -1) g_source_remove(il->idle_done_id); |
383 if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf); | 419 if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf); |
384 if (il->fd) file_data_unref(il->fd); | 420 if (il->fd) file_data_unref(il->fd); |
385 if (il->path) g_free(il->path); | 421 if (il->path) g_free(il->path); |
386 if (il->read_buffer) g_free(il->read_buffer); | |
387 DEBUG_1("freeing image loader %p bytes_read=%d", il, il->bytes_read); | 422 DEBUG_1("freeing image loader %p bytes_read=%d", il, il->bytes_read); |
388 g_free(il); | 423 g_free(il); |
389 } | 424 } |
390 | 425 |
391 /* don't forget to gdk_pixbuf_ref() it if you want to use it after image_loader_free() */ | 426 /* don't forget to gdk_pixbuf_ref() it if you want to use it after image_loader_free() */ |