[solang] Improved content-type guessing and Gdk::PixbufLoader selection
- From: Debarshi Ray <debarshir src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [solang] Improved content-type guessing and Gdk::PixbufLoader selection
- Date: Fri, 25 Dec 2009 10:36:26 +0000 (UTC)
commit 10293221d0b5715b1c7842faf4535248995ea5e9
Author: Debarshi Ray <rishi gnu org>
Date: Mon Dec 7 03:38:00 2009 +0200
Improved content-type guessing and Gdk::PixbufLoader selection
+ ContentTypeRepo::get_content_type should pass some data from the
beginning of the file to Gio::content_type_guess. Otherwise if a
file has been renamed to have a weird extension it will lead to
uncertainty.
+ ThumbbufMaker should explicitly chose a Gdk::PixbufLoader. This
prevents things like trying to load a RAW using the TIFF loader
instead of a RAW loader like the one provided by libopenraw.
src/attribute/thumbnail.cpp | 4 ++
src/common/content-type-repo.cpp | 27 +++++++++++-
src/common/thumbbuf-maker.cpp | 92 +++++++++++++++++++++++++++++++++++---
src/common/thumbbuf-maker.h | 3 +
4 files changed, 118 insertions(+), 8 deletions(-)
---
diff --git a/src/attribute/thumbnail.cpp b/src/attribute/thumbnail.cpp
index 223690f..1bd2ebe 100644
--- a/src/attribute/thumbnail.cpp
+++ b/src/attribute/thumbnail.cpp
@@ -255,6 +255,10 @@ Thumbnail::generate_using_gdkpixbuf(const PhotoPtr & photo,
new_size_hint.get_y(),
true);
const PixbufPtr thumbnail = thumbbuf_maker(photo);
+ if (0 == thumbnail)
+ {
+ return;
+ }
thumbnail->save( get_path(), "jpeg" );
diff --git a/src/common/content-type-repo.cpp b/src/common/content-type-repo.cpp
index c7c52f6..e70f118 100644
--- a/src/common/content-type-repo.cpp
+++ b/src/common/content-type-repo.cpp
@@ -67,10 +67,35 @@ ContentTypeRepo::init() throw()
Glib::ustring
ContentTypeRepo::get_content_type(const std::string &filename ) const throw()
{
+ DataInputStreamPtr fin;
+
+ if (true == Glib::file_test(filename, Glib::FILE_TEST_EXISTS))
+ {
+ const FilePtr file = Gio::File::create_for_path(filename);
+
+ try
+ {
+ fin = Gio::DataInputStream::create(file->read());
+ }
+ catch(const Gio::Error & e)
+ {
+ g_warning("%s", e.what().c_str());
+ }
+ }
+
+ const gint SNIFF_BUFFER_SIZE = 4096; // From gdk-pixbuf-io.c
+ guint8 buffer[SNIFF_BUFFER_SIZE];
+ gssize nread = 0;
+
+ if (0 != fin)
+ {
+ nread = fin->read(buffer, sizeof(buffer));
+ }
+
bool uncertain = false;
Glib::ustring contentType
= Gio::content_type_guess(
- filename, std::string(), uncertain );
+ filename, buffer, nread, uncertain );
if( uncertain )
return Glib::ustring();
diff --git a/src/common/thumbbuf-maker.cpp b/src/common/thumbbuf-maker.cpp
index a7c0fd5..6e9ed7b 100644
--- a/src/common/thumbbuf-maker.cpp
+++ b/src/common/thumbbuf-maker.cpp
@@ -20,6 +20,11 @@
#include "config.h"
#endif // HAVE_CONFIG_H
+#include <cstdio>
+
+#include <giomm.h>
+
+#include "content-type-repo.h"
#include "photo.h"
#include "thumbbuf-maker.h"
#include "thumbnail.h"
@@ -48,6 +53,23 @@ ThumbbufMaker::~ThumbbufMaker() throw()
{
}
+PixbufLoaderPtr
+ThumbbufMaker::create_pixbuf_loader(const std::string & path) const
+ throw(Gdk::PixbufError)
+{
+ const ContentTypeRepoPtr content_type_repo
+ = ContentTypeRepo::instance();
+ const Glib::ustring content_type
+ = content_type_repo->get_content_type(path);
+
+ if (false == content_type_repo->is_gdk_supported(content_type))
+ {
+ throw Gdk::PixbufError(Gdk::PixbufError::UNKNOWN_TYPE, "");
+ }
+
+ return Gdk::PixbufLoader::create(content_type, true);
+}
+
ThumbbufMaker &
ThumbbufMaker::operator=(const ThumbbufMaker & source) throw()
{
@@ -93,19 +115,67 @@ ThumbbufMaker::operator()(const PhotoPtr & photo) throw()
}
}
- PixbufPtr pixbuf;
+ PixbufLoaderPtr pixbuf_loader;
try
{
- pixbuf = Gdk::Pixbuf::create_from_file(path, width_, -1, true);
+ pixbuf_loader = create_pixbuf_loader(path);
}
- catch (const Glib::FileError & e)
+ catch(const Gdk::PixbufError & e)
{
g_warning("%s", e.what().c_str());
return PixbufPtr(0);
}
+
+ const FilePtr file = Gio::File::create_for_path(path);
+ DataInputStreamPtr fin;
+
+ try
+ {
+ fin = Gio::DataInputStream::create(file->read());
+ }
+ catch(const Gio::Error & e)
+ {
+ g_warning("%s", e.what().c_str());
+ return PixbufPtr(0);
+ }
+
+ gssize nread;
+ guint8 buffer[BUFSIZ];
+
+ while (0 < (nread = fin->read(buffer, sizeof(buffer))))
+ {
+ try
+ {
+ pixbuf_loader->write(buffer, nread);
+ }
+ catch (const Glib::FileError & e)
+ {
+ g_warning("%s", e.what().c_str());
+ break;
+ }
+ catch (const Gdk::PixbufError & e)
+ {
+ g_warning("%s", e.what().c_str());
+ break;
+ }
+ }
+
+ try
+ {
+ pixbuf_loader->close();
+ }
+ catch (const Glib::FileError & e)
+ {
+ g_warning("%s", e.what().c_str());
+ }
catch (const Gdk::PixbufError & e)
{
g_warning("%s", e.what().c_str());
+ }
+
+ PixbufPtr pixbuf = pixbuf_loader->get_pixbuf();
+ if (0 == pixbuf)
+ {
return PixbufPtr(0);
}
@@ -115,16 +185,24 @@ ThumbbufMaker::operator()(const PhotoPtr & photo) throw()
pixbuf->gobj()), false);
}
- const double height = static_cast<double>(pixbuf->get_height());
+ const gint height = pixbuf->get_height();
+ const gint width = pixbuf->get_width();
+ const gdouble aspect_ratio = static_cast<gdouble>(width)
+ / static_cast<gdouble>(height);
- if (height_ < height)
+ if (height > width)
{
- const double width = static_cast<double>(pixbuf->get_width());
- const double aspect_ratio = width / height;
pixbuf = pixbuf->scale_simple(
static_cast<gint>(height_ * aspect_ratio),
height_, Gdk::INTERP_BILINEAR);
}
+ else
+ {
+ pixbuf = pixbuf->scale_simple(
+ width_,
+ static_cast<gint>(width_ / aspect_ratio),
+ Gdk::INTERP_BILINEAR);
+ }
return pixbuf;
}
diff --git a/src/common/thumbbuf-maker.h b/src/common/thumbbuf-maker.h
index ed454d8..c8df27f 100644
--- a/src/common/thumbbuf-maker.h
+++ b/src/common/thumbbuf-maker.h
@@ -46,6 +46,9 @@ class ThumbbufMaker :
operator()(const PhotoPtr & photo) throw();
protected:
+ PixbufLoaderPtr
+ create_pixbuf_loader(const std::string & path) const
+ throw(Gdk::PixbufError);
private:
bool rotate_;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]