[gthumb] get the image type from the file content when loading the image
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] get the image type from the file content when loading the image
- Date: Wed, 15 Aug 2012 10:40:26 +0000 (UTC)
commit ea4af725c3bdecee5a61bae1fea37717e6ad1640
Author: Paolo Bacchilega <paobac src gnome org>
Date: Wed Aug 15 12:23:04 2012 +0200
get the image type from the file content when loading the image
gthumb/gth-file-data.c | 126 +++++++++++++++++++++++++++++++++++++++++++-
gthumb/gth-file-data.h | 3 +
gthumb/gth-image-loader.c | 2 +-
gthumb/gth-thumb-loader.c | 2 +-
4 files changed, 128 insertions(+), 5 deletions(-)
---
diff --git a/gthumb/gth-file-data.c b/gthumb/gth-file-data.c
index 3f41f2b..1182e58 100644
--- a/gthumb/gth-file-data.c
+++ b/gthumb/gth-file-data.c
@@ -28,6 +28,9 @@
#include "gth-string-list.h"
+#define BUFFER_SIZE_FOR_SNIFFING 32
+
+
const char *FileDataDigitalizationTags[] = {
"Exif::Photo::DateTimeOriginal",
"Xmp::exif::DateTimeOriginal",
@@ -220,10 +223,127 @@ gth_file_data_get_mime_type (GthFileData *self)
return NULL;
filename = g_file_get_basename (self->file);
- if (filename != NULL) {
- content_type = g_content_type_guess (filename, NULL, 0, NULL);
- g_free (filename);
+ if (filename == NULL)
+ return NULL;
+
+ content_type = g_content_type_guess (filename, NULL, 0, NULL);
+ g_file_info_set_attribute_string (self->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, content_type);
+
+ g_free (filename);
+ }
+
+ return get_static_string (content_type);
+}
+
+
+static const char *
+get_mime_type_from_magic_numbers (void *buffer,
+ gsize buffer_size)
+{
+#if ENABLE_MAGIC
+
+ static magic_t magic = NULL;
+
+ if (magic == NULL) {
+ magic = magic_open (MAGIC_MIME_TYPE);
+ if (magic != NULL)
+ magic_load (magic, NULL);
+ else
+ g_warning ("unable to open magic database");
+ }
+
+ if (magic != NULL) {
+ const char * mime_type;
+
+ mime_type = magic_buffer (magic, buffer, buffer_size);
+ if (mime_type)
+ return mime_type;
+
+ g_warning ("unable to detect filetype from magic: %s", magic_error (magic));
+ }
+
+#else
+
+ static const struct magic {
+ const unsigned int off;
+ const unsigned int len;
+ const char * const id;
+ const char * const mime_type;
+ }
+ magic_ids [] = {
+ /* magic ids taken from magic/Magdir/archive from the file-4.21 tarball */
+ { 0, 8, "\x89PNG\x0d\x0a\x1a\x0a", "image/png" },
+ { 0, 4, "MM\x00\x2a", "image/tiff" },
+ { 0, 4, "II\x2a\x00", "image/tiff" },
+ { 0, 4, "GIF8", "image/gif" },
+ { 0, 2, "\xff\xd8", "image/jpeg" },
+ };
+
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (magic_ids); i++) {
+ const struct magic * const magic = &magic_ids[i];
+
+ if ((magic->off + magic->len) > buffer_size)
+ g_warning ("buffer underrun for mime-type '%s' magic", magic->mime_type);
+ else if (! memcmp (buffer + magic->off, magic->id, magic->len))
+ return magic->mime_type;
+ }
+
+#endif
+
+ return NULL;
+}
+
+
+const char *
+gth_file_data_get_mime_type_from_content (GthFileData *self,
+ GCancellable *cancellable)
+{
+ const char *content_type;
+
+ if (self->info == NULL)
+ return NULL;
+
+ content_type = g_file_info_get_attribute_string (self->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
+ if (content_type == NULL) {
+ char *filename;
+ GFileInputStream *istream;
+ GError *error = NULL;
+ guchar buffer[BUFFER_SIZE_FOR_SNIFFING];
+ gssize n = 0;
+ gboolean result_uncertain;
+
+ if (self->file == NULL)
+ return NULL;
+
+ filename = g_file_get_basename (self->file);
+ if (filename == NULL)
+ return NULL;
+
+ istream = g_file_read (self->file, cancellable, &error);
+ if (istream != NULL) {
+ n = g_input_stream_read (G_INPUT_STREAM (istream),
+ buffer,
+ BUFFER_SIZE_FOR_SNIFFING,
+ cancellable,
+ NULL);
+ g_object_unref (istream);
}
+ else {
+ g_warning ("%s", error->message);
+ g_clear_error (&error);
+ }
+
+ result_uncertain = FALSE;
+ content_type = get_mime_type_from_magic_numbers (buffer, n);
+ if (content_type == NULL)
+ content_type = g_content_type_guess (NULL, buffer, n, &result_uncertain);
+ if ((content_type == NULL) || (strcmp (content_type, "application/xml") == 0) || result_uncertain)
+ content_type = g_content_type_guess (filename, NULL, n, NULL);
+ g_file_info_set_attribute_string (self->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, content_type);
+
+ g_free (filename);
}
return get_static_string (content_type);
diff --git a/gthumb/gth-file-data.h b/gthumb/gth-file-data.h
index aad7ed8..24fe58a 100644
--- a/gthumb/gth-file-data.h
+++ b/gthumb/gth-file-data.h
@@ -76,6 +76,9 @@ void gth_file_data_set_info (GthFileData *self,
void gth_file_data_set_mime_type (GthFileData *self,
const char *mime_type);
const char * gth_file_data_get_mime_type (GthFileData *self);
+const char * gth_file_data_get_mime_type_from_content
+ (GthFileData *self,
+ GCancellable *cancellable);
const char * gth_file_data_get_filename_sort_key (GthFileData *self);
time_t gth_file_data_get_mtime (GthFileData *self);
GTimeVal * gth_file_data_get_modification_time (GthFileData *self);
diff --git a/gthumb/gth-image-loader.c b/gthumb/gth-image-loader.c
index a0f8b51..3b8c2b6 100644
--- a/gthumb/gth-image-loader.c
+++ b/gthumb/gth-image-loader.c
@@ -190,7 +190,7 @@ load_pixbuf_thread (GSimpleAsyncResult *result,
else {
GthImageLoaderFunc loader_func;
- loader_func = gth_main_get_image_loader_func (gth_file_data_get_mime_type (load_data->file_data),
+ loader_func = gth_main_get_image_loader_func (gth_file_data_get_mime_type_from_content (load_data->file_data, cancellable),
self->priv->preferred_format);
if (loader_func != NULL)
image = loader_func (load_data->file_data,
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index b2dad2a..73c21da 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -134,7 +134,7 @@ generate_thumbnail (GthFileData *file_data,
uri = g_file_get_uri (file_data->file);
pixbuf = gnome_desktop_thumbnail_factory_generate_no_script (self->priv->thumb_factory,
uri,
- gth_file_data_get_mime_type (file_data),
+ gth_file_data_get_mime_type_from_content (file_data, cancellable),
cancellable);
if (g_cancellable_is_cancelled (cancellable)) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]