[gthumb/ext] added raw files support
- From: Paolo Bacchilega <paobac src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gthumb/ext] added raw files support
- Date: Fri, 4 Dec 2009 20:26:18 +0000 (UTC)
commit 10c3213b05f754914b2632c8175553af0e148aa2
Author: Paolo Bacchilega <paobac src gnome org>
Date: Fri Dec 4 21:22:14 2009 +0100
added raw files support
configure.ac | 21 +
extensions/Makefile.am | 1 +
extensions/raw_files/Makefile.am | 26 ++
extensions/raw_files/main.c | 470 ++++++++++++++++++++++++
extensions/raw_files/raw_files.extension.in.in | 10 +
gthumb/Makefile.am | 2 +-
6 files changed, 529 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3382299..b94b9b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,6 +32,7 @@ EXIV2_REQUIRED=0.18
CLUTTER_REQUIRED=1.0.0
CLUTTER_GTK_REQUIRED=0.10.0
GSTREAMER_REQUIRED=0.10
+OPENRAW_REQUIRED=0.0.8
dnl ===========================================================================
@@ -270,6 +271,24 @@ AC_MSG_RESULT($enable_tiff)
dnl ===========================================================================
+AC_ARG_ENABLE([libopenraw],
+ [AS_HELP_STRING([--enable-libopenraw],[use the libopenraw library to read raw files [default=no]])],,
+ [enable_libopenraw=no])
+
+if test x$enable_libopenraw = xyes ; then
+ PKG_CHECK_MODULES(LIBOPENRAW,
+ libopenraw-1.0 >= $OPENRAW_REQUIRED,
+ [enable_libopenraw=yes],
+ [enable_libopenraw=no])
+ if test "x$enable_libopenraw" = "xyes"; then
+ AC_DEFINE(ENABLE_LIBOPENRAW, 1, [Define to 1 if libopenraw must be used to read raw files])
+ fi
+fi
+AC_SUBST(LIBOPENRAW_LIBS)
+AC_SUBST(LIBOPENRAW_CFLAGS)
+
+dnl ===========================================================================
+
AC_CONFIG_FILES([
Makefile
copy-n-paste/Makefile
@@ -329,6 +348,7 @@ extensions/photo_importer/data/ui/Makefile
extensions/pixbuf_savers/Makefile
extensions/pixbuf_savers/data/Makefile
extensions/pixbuf_savers/data/ui/Makefile
+extensions/raw_files/Makefile
extensions/red_eye_removal/Makefile
extensions/red_eye_removal/data/Makefile
extensions/red_eye_removal/data/ui/Makefile
@@ -368,4 +388,5 @@ Configuration:
TIFF tools : ${enable_tiff}
Clutter support : ${enable_clutter}
GStreamer support : ${enable_gstreamer}
+ Use libopenraw : ${enable_libopenraw}
"
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index e811849..df88586 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -15,6 +15,7 @@ SUBDIRS = \
list_tools \
photo_importer \
pixbuf_savers \
+ raw_files \
red_eye_removal \
rename_series \
resize_images \
diff --git a/extensions/raw_files/Makefile.am b/extensions/raw_files/Makefile.am
new file mode 100644
index 0000000..cb28096
--- /dev/null
+++ b/extensions/raw_files/Makefile.am
@@ -0,0 +1,26 @@
+extensiondir = $(libdir)/gthumb-2.0/extensions
+extension_LTLIBRARIES = libraw_files.la
+
+libraw_files_la_SOURCES = \
+ main.c
+
+libraw_files_la_CFLAGS = $(GTHUMB_CFLAGS) $(LIBOPENRAW_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
+libraw_files_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
+libraw_files_la_LIBADD = $(GTHUMB_LIBS)
+libraw_files_la_DEPENDENCIES = $(top_builddir)/gthumb/gthumb$(EXEEXT)
+
+extensioninidir = $(extensiondir)
+extensionini_in_files = raw_files.extension.in.in
+extensionini_DATA = $(extensionini_in_files:.extension.in.in=.extension)
+
+%.extension.in: %.extension.in.in $(extension_LTLIBRARIES)
+ sed -e "s|%LIBRARY%|`. ./$(extension_LTLIBRARIES) && echo $$dlname`|" \
+ $< > $@
+
+%.extension: %.extension.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
+EXTRA_DIST = $(extensionini_in_files)
+
+DISTCLEANFILES = $(extensionini_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/extensions/raw_files/main.c b/extensions/raw_files/main.c
new file mode 100644
index 0000000..8f145d1
--- /dev/null
+++ b/extensions/raw_files/main.c
@@ -0,0 +1,470 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <config.h>
+
+
+#ifdef ENABLE_LIBOPENRAW
+
+
+#define GDK_PIXBUF_ENABLE_BACKEND
+#include <gtk/gtk.h>
+#include <gthumb.h>
+#include <libopenraw/libopenraw.h>
+
+
+static void
+free_pixels (guchar *pixels,
+ gpointer data)
+{
+ free (pixels);
+}
+
+
+static GdkPixbuf *
+_or_thumbnail_to_pixbuf (ORThumbnailRef thumbnail,
+ int32_t orientation)
+{
+ GdkPixbuf *pixbuf = NULL;
+ const guchar *buf;
+ size_t buf_size;
+ or_data_type format;
+
+ buf = (const guchar *) or_thumbnail_data (thumbnail);
+ buf_size = or_thumbnail_data_size (thumbnail);
+ format = or_thumbnail_format (thumbnail);
+ switch (format) {
+ case OR_DATA_TYPE_PIXMAP_8RGB: {
+ guchar *data;
+ uint32_t x, y;
+
+ data = (guchar*) malloc (buf_size);
+ memcpy (data, buf, buf_size);
+ or_thumbnail_dimensions (thumbnail, &x, &y);
+ pixbuf = gdk_pixbuf_new_from_data (data,
+ GDK_COLORSPACE_RGB,
+ FALSE,
+ 8,
+ x,
+ y,
+ x * 3,
+ free_pixels,
+ NULL);
+ break;
+ }
+ case OR_DATA_TYPE_JPEG:
+ case OR_DATA_TYPE_TIFF:
+ case OR_DATA_TYPE_PNG: {
+ GdkPixbufLoader *loader;
+
+ loader = gdk_pixbuf_loader_new ();
+ gdk_pixbuf_loader_write (loader, buf, buf_size, NULL);
+ gdk_pixbuf_loader_close (loader, NULL);
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return pixbuf;
+}
+
+
+static GdkPixbuf *
+openraw_extract_thumbnail_from_file (GthFileData *file_data,
+ int requested_size,
+ GError **error)
+{
+ GdkPixbuf *pixbuf = NULL;
+ char *filename;
+ ORRawFileRef raw_file = NULL;
+
+ filename = g_file_get_path (file_data->file);
+ if (filename == NULL)
+ return NULL;
+
+ raw_file = or_rawfile_new (filename, OR_DATA_TYPE_NONE);
+ if (raw_file != NULL) {
+ int32_t orientation;
+ ORThumbnailRef thumbnail;
+ or_error err;
+
+ orientation = or_rawfile_get_orientation (raw_file);
+ thumbnail = or_thumbnail_new ();
+ err = or_rawfile_get_thumbnail (raw_file, requested_size, thumbnail);
+ if (err == OR_ERROR_NONE) {
+ GdkPixbuf *tmp;
+
+ tmp = _or_thumbnail_to_pixbuf (thumbnail, orientation);
+ pixbuf = _gdk_pixbuf_transform (tmp, orientation);
+ g_object_unref (tmp);
+ }
+
+ or_thumbnail_release (thumbnail);
+ or_rawfile_release (raw_file);
+ }
+
+ g_free (filename);
+
+ return pixbuf;
+}
+
+
+static void
+free_bitmapdata (guchar *pixels,
+ gpointer data)
+{
+ or_bitmapdata_release ((ORBitmapDataRef) data);
+}
+
+
+static GdkPixbuf *
+openraw_get_pixbuf_from_file (GthFileData *file_data,
+ GError **error)
+{
+ GdkPixbuf *pixbuf = NULL;
+ char *filename;
+ ORRawFileRef raw_file = NULL;
+
+ filename = g_file_get_path (file_data->file);
+ if (filename == NULL)
+ return NULL;
+
+ raw_file = or_rawfile_new (filename, OR_DATA_TYPE_NONE);
+ if (raw_file != NULL) {
+ ORBitmapDataRef bitmapdata;
+ or_error err;
+
+ bitmapdata = or_bitmapdata_new ();
+ err = or_rawfile_get_rendered_image (raw_file, bitmapdata, 0);
+ if (err == OR_ERROR_NONE) {
+ uint32_t x, y;
+
+ or_bitmapdata_dimensions (bitmapdata, &x, &y);
+ pixbuf = gdk_pixbuf_new_from_data (or_bitmapdata_data (bitmapdata),
+ GDK_COLORSPACE_RGB,
+ FALSE,
+ 8,
+ x,
+ y,
+ (x - 2) * 3,
+ free_bitmapdata,
+ bitmapdata);
+ }
+
+ or_rawfile_release (raw_file);
+ }
+
+ g_free (filename);
+
+ return pixbuf;
+}
+
+
+static GdkPixbufAnimation *
+openraw_pixbuf_animation_new_from_file (GthFileData *file_data,
+ GError **error,
+ int requested_width,
+ int requested_height)
+{
+ GdkPixbufAnimation *animation;
+ GdkPixbuf *pixbuf;
+
+ if ((requested_width == 0) || (requested_height == 0))
+ pixbuf = openraw_extract_thumbnail_from_file (file_data, requested_width, error);
+ else
+ pixbuf = openraw_get_pixbuf_from_file (file_data, error);
+
+ if (pixbuf != NULL) {
+ animation = gdk_pixbuf_non_anim_new (pixbuf);
+ g_object_unref (pixbuf);
+ }
+ else
+ animation = NULL;
+
+ return animation;
+}
+
+
+#else /* ! ENABLE_LIBOPENRAW */
+
+
+#define GDK_PIXBUF_ENABLE_BACKEND
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+
+static gboolean
+_g_mime_type_is_raw (const char *mime_type)
+{
+ return (g_content_type_is_a (mime_type, "application/x-crw") /* ? */
+ || g_content_type_is_a (mime_type, "image/x-raw") /* mimelnk */
+ || g_content_type_is_a (mime_type, "image/x-dcraw")); /* freedesktop.org.xml - this should
+ catch most RAW formats, which are
+ registered as sub-classes of
+ image/x-dcraw */
+}
+
+
+static gboolean
+_g_mime_type_is_hdr (const char *mime_type)
+{
+ /* Note that some HDR file extensions have been hard-coded into
+ the get_file_mime_type function above. */
+ return g_content_type_is_a (mime_type, "image/x-hdr");
+}
+
+
+static char *
+get_cache_full_path (const char *filename,
+ const char *extension)
+{
+ char *name;
+ char *cache_filename;
+
+ if (extension == NULL)
+ name = g_strdup (filename);
+ else
+ name = g_strconcat (filename, ".", extension, NULL);
+ gth_user_dir_make_dir_for_file (GTH_DIR_CACHE, "gthumb", name, NULL);
+ cache_filename = gth_user_dir_get_file (GTH_DIR_CACHE, "gthumb", name, NULL);
+
+ g_free (name);
+
+ return cache_filename;
+}
+
+
+static time_t
+get_file_mtime (const char *path)
+{
+ GFile *file;
+ time_t t;
+
+ file = g_file_new_for_path (path);
+ t = _g_file_get_mtime (file);
+ g_object_unref (file);
+
+ return t;
+}
+
+
+static GdkPixbufAnimation *
+openraw_pixbuf_animation_new_from_file (GthFileData *file_data,
+ GError **error,
+ int requested_width,
+ int requested_height)
+{
+ GdkPixbufAnimation *animation;
+ GdkPixbuf *pixbuf;
+ gboolean is_thumbnail;
+ gboolean is_raw;
+ gboolean is_hdr;
+ char *local_file;
+ char *local_file_md5;
+ char *cache_file;
+ char *cache_file_esc;
+ char *local_file_esc;
+ char *command = NULL;
+
+ is_thumbnail = requested_width > 0;
+ is_raw = _g_mime_type_is_raw (gth_file_data_get_mime_type (file_data));
+ is_hdr = _g_mime_type_is_hdr (gth_file_data_get_mime_type (file_data));
+
+ /* The output filename, and its persistence, depend on the input file
+ * type, and whether or not a thumbnail has been requested. */
+
+ local_file = g_file_get_path (file_data->file);
+ local_file_md5 = gnome_desktop_thumbnail_md5 (local_file);
+
+ if (is_raw && !is_thumbnail)
+ /* Full-sized converted RAW file */
+ cache_file = get_cache_full_path (local_file_md5, "conv.pnm");
+ else if (is_raw && is_thumbnail)
+ /* RAW: thumbnails generated in pnm format. The converted file is later removed. */
+ cache_file = get_cache_full_path (local_file_md5, "conv-thumb.pnm");
+ else if (is_hdr && is_thumbnail)
+ /* HDR: thumbnails generated in tiff format. The converted file is later removed. */
+ cache_file = get_cache_full_path (local_file_md5, "conv-thumb.tiff");
+ else
+ /* Full-sized converted HDR files */
+ cache_file = get_cache_full_path (local_file_md5, "conv.tiff");
+
+ g_free (local_file_md5);
+
+ if (cache_file == NULL) {
+ g_free (local_file);
+ return NULL;
+ }
+
+ local_file_esc = g_shell_quote (local_file);
+ cache_file_esc = g_shell_quote (cache_file);
+
+ /* Do nothing if an up-to-date converted file is already in the cache */
+ if (! g_file_test (cache_file, G_FILE_TEST_EXISTS)
+ || (gth_file_data_get_mtime (file_data) > get_file_mtime (cache_file)))
+ {
+ if (is_raw) {
+ if (is_thumbnail) {
+ char *first_part;
+ char *jpg_thumbnail;
+ char *tiff_thumbnail;
+ char *ppm_thumbnail;
+ char *thumb_command;
+
+ thumb_command = g_strdup_printf ("dcraw -e %s", local_file_esc);
+ g_spawn_command_line_sync (thumb_command, NULL, NULL, NULL, NULL);
+ g_free (thumb_command);
+
+ first_part = _g_uri_remove_extension (local_file);
+ jpg_thumbnail = g_strdup_printf ("%s.thumb.jpg", first_part);
+ tiff_thumbnail = g_strdup_printf ("%s.thumb.tiff", first_part);
+ ppm_thumbnail = g_strdup_printf ("%s.thumb.ppm", first_part);
+
+ if (g_file_test (jpg_thumbnail, G_FILE_TEST_EXISTS)) {
+ g_free (cache_file);
+ cache_file = g_strdup (jpg_thumbnail);
+ }
+ else if (g_file_test (tiff_thumbnail, G_FILE_TEST_EXISTS)) {
+ g_free (cache_file);
+ cache_file = g_strdup (tiff_thumbnail);
+ }
+ else if (g_file_test (ppm_thumbnail, G_FILE_TEST_EXISTS)) {
+ g_free (cache_file);
+ cache_file = g_strdup (ppm_thumbnail);
+ }
+ else {
+ /* No embedded thumbnail. Read the whole file. */
+ /* Add -h option to speed up thumbnail generation. */
+ command = g_strdup_printf ("dcraw -w -c -h %s > %s",
+ local_file_esc,
+ cache_file_esc);
+ }
+
+ g_free (first_part);
+ g_free (jpg_thumbnail);
+ g_free (tiff_thumbnail);
+ g_free (ppm_thumbnail);
+ }
+ else {
+ /* -w option = camera-specified white balance */
+ command = g_strdup_printf ("dcraw -w -c %s > %s",
+ local_file_esc,
+ cache_file_esc);
+ }
+ }
+
+ if (is_hdr) {
+ /* HDR files. We can use the pfssize tool to speed up
+ thumbnail generation considerably, so we treat
+ thumbnailing as a special case. */
+ char *resize_command;
+
+ if (is_thumbnail)
+ resize_command = g_strdup_printf (" | pfssize --maxx %d --maxy %d",
+ requested_width,
+ requested_height);
+ else
+ resize_command = g_strdup_printf (" ");
+
+ command = g_strconcat ( "pfsin ",
+ local_file_esc,
+ resize_command,
+ " | pfsclamp --rgb | pfstmo_drago03 | pfsout ",
+ cache_file_esc,
+ NULL );
+ g_free (resize_command);
+ }
+
+ if (command != NULL) {
+ system (command);
+ g_free (command);
+ }
+ }
+
+ pixbuf = gdk_pixbuf_new_from_file (cache_file, NULL);
+
+ /* Thumbnail files are already cached, so delete the conversion cache copies */
+ if (is_thumbnail) {
+ GFile *file;
+
+ file = g_file_new_for_path (cache_file);
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+ }
+
+ if (pixbuf != NULL) {
+ animation = gdk_pixbuf_non_anim_new (pixbuf);
+ g_object_unref (pixbuf);
+ }
+ else
+ animation = NULL;
+
+
+ g_free (cache_file_esc);
+ g_free (local_file_esc);
+ g_free (cache_file);
+ g_free (local_file);
+
+ return animation;
+}
+
+
+#endif
+
+
+G_MODULE_EXPORT void
+gthumb_extension_activate (void)
+{
+ gth_main_register_pixbuf_loader (openraw_pixbuf_animation_new_from_file,
+ "image/x-adobe-dng",
+ "image/x-canon-cr2",
+ "image/x-canon-crw",
+ "image/x-epson-erf",
+ "image/x-minolta-mrw",
+ "image/x-nikon-nef",
+ "image/x-olympus-orf",
+ "image/x-pentax-pef",
+ "image/x-sony-arw",
+ NULL);
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_deactivate (void)
+{
+}
+
+
+G_MODULE_EXPORT gboolean
+gthumb_extension_is_configurable (void)
+{
+ return FALSE;
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_configure (GtkWindow *parent)
+{
+}
diff --git a/extensions/raw_files/raw_files.extension.in.in b/extensions/raw_files/raw_files.extension.in.in
new file mode 100644
index 0000000..5f38bf1
--- /dev/null
+++ b/extensions/raw_files/raw_files.extension.in.in
@@ -0,0 +1,10 @@
+[Extension]
+_Name=Raw format support
+_Description=Allow to load raw format images.
+_Authors=gthumb development team
+Copyright=Copyright © 2009 The Free Software Foundation, Inc.
+Version=1.0
+
+[Loader]
+Type=module
+File=%LIBRARY%
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 4c85e54..cce8a86 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -242,6 +242,7 @@ gthumb_LDADD = \
$(TIFF_LIBS) \
$(CLUTTER_LIBS) \
$(GSTREAMER_LIBS) \
+ $(LIBOPENRAW_LIBS) \
$(NULL)
if RUN_IN_PLACE
@@ -256,7 +257,6 @@ endif
gthumb_CFLAGS = \
$(GTHUMB_CFLAGS) \
- $(EXIV2_CFLAGS) \
$(CLUTTER_CFLAGS) \
-I$(top_srcdir)/copy-n-paste/ \
-DGTHUMB_LOCALEDIR=\"$(datadir)/locale\" \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]