aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/thumbnailgtk_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/thumbnailgtk_extractor.c')
-rw-r--r--src/plugins/thumbnailgtk_extractor.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/plugins/thumbnailgtk_extractor.c b/src/plugins/thumbnailgtk_extractor.c
new file mode 100644
index 0000000..63ac359
--- /dev/null
+++ b/src/plugins/thumbnailgtk_extractor.c
@@ -0,0 +1,236 @@
1/*
2 This file is part of libextractor.
3 (C) 2005, 2009, 2012 Vidyut Samanta and Christian Grothoff
4
5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libextractor is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20/**
21 * @file plugins/thumbnailgtk_extractor.c
22 * @author Christian Grothoff
23 * @brief this extractor produces a binary (!) encoded
24 * thumbnail of images (using gdk pixbuf). The bottom
25 * of the file includes a decoder method that can be used
26 * to reproduce the 128x128 PNG thumbnails. We use
27 * libmagic to test if the input data is actually an
28 * image before trying to give it to gtk.
29 */
30#include "platform.h"
31#include "extractor.h"
32#include <magic.h>
33#include <glib.h>
34#include <gdk-pixbuf/gdk-pixbuf.h>
35
36/**
37 * Target size for the thumbnails (width and height).
38 */
39#define THUMBSIZE 128
40
41/**
42 * Maximum image size supported (to avoid unreasonable
43 * allocations)
44 */
45#define MAX_IMAGE_SIZE (32 * 1024 * 1024)
46
47
48/**
49 * Global handle to MAGIC data.
50 */
51static magic_t magic;
52
53
54/**
55 * Main method for the thumbnailer plugin.
56 *
57 * @param ec extraction context
58 */
59void
60EXTRACTOR_thumbnailgtk_extract_method (struct EXTRACTOR_ExtractContext *ec)
61{
62 GdkPixbufLoader *loader;
63 GdkPixbuf *in;
64 GdkPixbuf *out;
65 size_t length;
66 char *thumb;
67 unsigned long width;
68 unsigned long height;
69 char format[64];
70 void *data;
71 uint64_t size;
72 size_t off;
73 ssize_t iret;
74 void *buf;
75 const char *mime;
76
77 iret = ec->read (ec->cls,
78 &data,
79 16 * 1024);
80 if (-1 == iret)
81 return;
82 if (NULL == (mime = magic_buffer (magic, data, iret)))
83 return;
84 if (0 != strncmp (mime,
85 "image/",
86 strlen ("image/")))
87 return; /* not an image */
88
89 /* read entire image into memory */
90 size = ec->get_size (ec->cls);
91 if (UINT64_MAX == size)
92 size = MAX_IMAGE_SIZE; /* unknown size, cap at max */
93 if (size > MAX_IMAGE_SIZE)
94 return; /* FAR too big to be an image */
95 if (NULL == (buf = malloc (size)))
96 return; /* too big to fit into memory on this system */
97
98 /* start with data already read */
99 memcpy (buf, data, iret);
100 off = iret;
101 while (off < size)
102 {
103 iret = ec->read (ec->cls, &data, size - off);
104 if (iret <= 0)
105 {
106 /* io error */
107 free (buf);
108 return;
109 }
110 memcpy (buf + off, data, iret);
111 off += iret;
112 }
113
114 loader = gdk_pixbuf_loader_new ();
115 gdk_pixbuf_loader_write (loader,
116 buf,
117 size, NULL);
118 free (buf);
119 in = gdk_pixbuf_loader_get_pixbuf (loader);
120 gdk_pixbuf_loader_close (loader, NULL);
121 if (NULL == in)
122 {
123 g_object_unref (loader);
124 return;
125 }
126 g_object_ref (in);
127 g_object_unref (loader);
128 height = gdk_pixbuf_get_height (in);
129 width = gdk_pixbuf_get_width (in);
130 snprintf (format,
131 sizeof (format),
132 "%ux%u",
133 (unsigned int) width,
134 (unsigned int) height);
135 if (0 != ec->proc (ec->cls,
136 "thumbnailgtk",
137 EXTRACTOR_METATYPE_IMAGE_DIMENSIONS,
138 EXTRACTOR_METAFORMAT_UTF8,
139 "text/plain",
140 format,
141 strlen (format) + 1))
142 {
143 g_object_unref (in);
144 return;
145 }
146 if ((height <= THUMBSIZE) && (width <= THUMBSIZE))
147 {
148 g_object_unref (in);
149 return;
150 }
151 if (height > THUMBSIZE)
152 {
153 width = width * THUMBSIZE / height;
154 height = THUMBSIZE;
155 }
156 if (width > THUMBSIZE)
157 {
158 height = height * THUMBSIZE / width;
159 width = THUMBSIZE;
160 }
161 if ( (0 == height) || (0 == width) )
162 {
163 g_object_unref (in);
164 return;
165 }
166 out = gdk_pixbuf_scale_simple (in, width, height,
167 GDK_INTERP_BILINEAR);
168 g_object_unref (in);
169 thumb = NULL;
170 length = 0;
171 if (NULL == out)
172 return;
173 if (! gdk_pixbuf_save_to_buffer (out, &thumb,
174 &length,
175 "png", NULL,
176 "compression", "9",
177 NULL))
178 {
179 g_object_unref (out);
180 return;
181 }
182 g_object_unref (out);
183 if (NULL == thumb)
184 return;
185 ec->proc (ec->cls,
186 "thumbnailgtk",
187 EXTRACTOR_METATYPE_THUMBNAIL,
188 EXTRACTOR_METAFORMAT_BINARY,
189 "image/png",
190 thumb, length);
191 free (thumb);
192}
193
194
195/**
196 * This plugin sometimes is installed under the alias 'thumbnail'.
197 * So we need to provide a second entry method.
198 *
199 * @param ec extraction context
200 */
201void
202EXTRACTOR_thumbnail_extract_method (struct EXTRACTOR_ExtractContext *ec)
203{
204 EXTRACTOR_thumbnailgtk_extract_method (ec);
205}
206
207
208/**
209 * Initialize glib and load magic file.
210 */
211void __attribute__ ((constructor))
212ole_gobject_init ()
213{
214 g_type_init ();
215 magic = magic_open (MAGIC_MIME_TYPE);
216 if (0 != magic_load (magic, NULL))
217 {
218 /* FIXME: how to deal with errors? */
219 }
220}
221
222
223/**
224 * Destructor for the library, cleans up.
225 */
226void __attribute__ ((destructor))
227mime_ltdl_fini ()
228{
229 if (NULL != magic)
230 {
231 magic_close (magic);
232 magic = NULL;
233 }
234}
235
236/* end of thumbnailgtk_extractor.c */