1
|
1 /*
|
9
|
2 * GQview
|
|
3 * (C) 2004 John Ellis
|
1
|
4 *
|
|
5 * Author: John Ellis
|
|
6 *
|
9
|
7 * This software is released under the GNU General Public License (GNU GPL).
|
|
8 * Please read the included file COPYING for more information.
|
|
9 * This software comes with no warranty of any kind, use at your own risk!
|
1
|
10 */
|
|
11
|
9
|
12
|
1
|
13 #include "gqview.h"
|
9
|
14 #include "thumb.h"
|
1
|
15
|
9
|
16 #include "cache.h"
|
|
17 #include "image-load.h"
|
|
18 #include "pixbuf_util.h"
|
|
19 #include "thumb_standard.h"
|
|
20 #include "ui_fileops.h"
|
1
|
21
|
9
|
22 #include <utime.h>
|
|
23
|
|
24
|
|
25 static void thumb_loader_error_cb(ImageLoader *il, gpointer data);
|
|
26 static void thumb_loader_setup(ThumbLoader *tl, gchar *path);
|
|
27
|
|
28 static gint normalize_thumb(gint *width, gint *height, gint max_w, gint max_h);
|
|
29 static GdkPixbuf *get_xv_thumbnail(gchar *thumb_filename, gint max_w, gint max_h);
|
|
30
|
1
|
31
|
|
32 /*
|
|
33 *-----------------------------------------------------------------------------
|
|
34 * thumbnail routines: creation, caching, and maintenance (public)
|
|
35 *-----------------------------------------------------------------------------
|
|
36 */
|
|
37
|
9
|
38 static gint thumb_loader_save_to_cache(ThumbLoader *tl)
|
1
|
39 {
|
9
|
40 gchar *cache_dir;
|
|
41 gint success = FALSE;
|
|
42 mode_t mode = 0755;
|
1
|
43
|
9
|
44 if (!tl || !tl->pixbuf) return FALSE;
|
1
|
45
|
9
|
46 cache_dir = cache_get_location(CACHE_TYPE_THUMB, tl->path, FALSE, &mode);
|
1
|
47
|
9
|
48 if (cache_ensure_dir_exists(cache_dir, mode))
|
1
|
49 {
|
|
50 gchar *cache_path;
|
9
|
51 gchar *pathl;
|
|
52
|
|
53 cache_path = g_strconcat(cache_dir, "/", filename_from_path(tl->path),
|
|
54 GQVIEW_CACHE_EXT_THUMB, NULL);
|
1
|
55
|
9
|
56 if (debug) printf("Saving thumb: %s\n", cache_path);
|
|
57
|
|
58 pathl = path_from_utf8(cache_path);
|
|
59 success = pixbuf_to_file_as_png(tl->pixbuf, pathl);
|
|
60 if (success)
|
1
|
61 {
|
9
|
62 struct utimbuf ut;
|
|
63 /* set thumb time to that of source file */
|
|
64
|
|
65 ut.actime = ut.modtime = filetime(tl->path);
|
|
66 if (ut.modtime > 0)
|
1
|
67 {
|
9
|
68 utime(pathl, &ut);
|
1
|
69 }
|
|
70 }
|
|
71 else
|
|
72 {
|
9
|
73 if (debug) printf("Saving failed: %s\n", pathl);
|
1
|
74 }
|
9
|
75
|
|
76 g_free(pathl);
|
|
77 g_free(cache_path);
|
|
78 }
|
|
79
|
|
80 g_free(cache_dir);
|
|
81
|
|
82 return success;
|
|
83 }
|
1
|
84
|
9
|
85 static gint thumb_loader_mark_failure(ThumbLoader *tl)
|
|
86 {
|
|
87 gchar *cache_dir;
|
|
88 gint success = FALSE;
|
|
89 mode_t mode = 0755;
|
|
90
|
|
91 if (!tl) return FALSE;
|
|
92
|
|
93 cache_dir = cache_get_location(CACHE_TYPE_THUMB, tl->path, FALSE, &mode);
|
1
|
94
|
9
|
95 if (cache_ensure_dir_exists(cache_dir, mode))
|
|
96 {
|
|
97 gchar *cache_path;
|
|
98 gchar *pathl;
|
|
99 FILE *f;
|
|
100
|
|
101 cache_path = g_strconcat(cache_dir, "/", filename_from_path(tl->path),
|
|
102 GQVIEW_CACHE_EXT_THUMB, NULL);
|
|
103
|
|
104 if (debug) printf("marking thumb failure: %s\n", cache_path);
|
|
105
|
|
106 pathl = path_from_utf8(cache_path);
|
|
107 f = fopen(pathl, "w");
|
|
108 if (f)
|
1
|
109 {
|
9
|
110 struct utimbuf ut;
|
|
111
|
|
112 fclose (f);
|
1
|
113
|
9
|
114 ut.actime = ut.modtime = filetime(tl->path);
|
|
115 if (ut.modtime > 0)
|
1
|
116 {
|
9
|
117 utime(pathl, &ut);
|
1
|
118 }
|
|
119
|
9
|
120 success = TRUE;
|
|
121 }
|
|
122
|
|
123 g_free(pathl);
|
|
124 g_free(cache_path);
|
|
125 }
|
|
126
|
|
127 g_free(cache_dir);
|
|
128 return success;
|
|
129 }
|
|
130
|
|
131 static void thumb_loader_percent_cb(ImageLoader *il, gdouble percent, gpointer data)
|
|
132 {
|
|
133 ThumbLoader *tl = data;
|
|
134
|
|
135 tl->percent_done = percent;
|
|
136
|
|
137 if (tl->func_progress) tl->func_progress(tl, tl->data);
|
|
138 }
|
|
139
|
|
140 static void thumb_loader_done_cb(ImageLoader *il, gpointer data)
|
|
141 {
|
|
142 ThumbLoader *tl = data;
|
|
143 GdkPixbuf *pixbuf;
|
|
144 gint pw, ph;
|
|
145 gint save;
|
|
146
|
|
147 if (debug) printf("thumb done: %s\n", tl->path);
|
1
|
148
|
9
|
149 pixbuf = image_loader_get_pixbuf(tl->il);
|
|
150 if (!pixbuf)
|
|
151 {
|
|
152 if (debug) printf("...but no pixbuf: %s\n", tl->path);
|
|
153 thumb_loader_error_cb(tl->il, tl);
|
|
154 return;
|
|
155 }
|
|
156
|
|
157 pw = gdk_pixbuf_get_width(pixbuf);
|
|
158 ph = gdk_pixbuf_get_height(pixbuf);
|
|
159
|
|
160 if (tl->cache_hit && pw != tl->max_w && ph != tl->max_h)
|
|
161 {
|
|
162 /* requested thumbnail size may have changed, load original */
|
|
163 if (debug) printf("thumbnail size mismatch, regenerating: %s\n", tl->path);
|
|
164 tl->cache_hit = FALSE;
|
|
165
|
|
166 thumb_loader_setup(tl, tl->path);
|
1
|
167
|
9
|
168 if (!image_loader_start(tl->il, thumb_loader_done_cb, tl))
|
|
169 {
|
|
170 image_loader_free(tl->il);
|
|
171 tl->il = NULL;
|
|
172
|
|
173 if (debug) printf("regeneration failure: %s\n", tl->path);
|
|
174 thumb_loader_error_cb(tl->il, tl);
|
|
175 }
|
|
176 return;
|
|
177 }
|
1
|
178
|
9
|
179 /* scale ?? */
|
|
180
|
|
181 if (pw > tl->max_w || ph > tl->max_h)
|
|
182 {
|
|
183 gint w, h;
|
|
184
|
|
185 if (((float)tl->max_w / pw) < ((float)tl->max_h / ph))
|
|
186 {
|
|
187 w = tl->max_w;
|
|
188 h = (float)w / pw * ph;
|
|
189 if (h < 1) h = 1;
|
1
|
190 }
|
|
191 else
|
|
192 {
|
9
|
193 h = tl->max_h;
|
|
194 w = (float)h / ph * pw;
|
|
195 if (w < 1) w = 1;
|
1
|
196 }
|
|
197
|
9
|
198 tl->pixbuf = gdk_pixbuf_scale_simple(pixbuf, w, h, (GdkInterpType)thumbnail_quality);
|
|
199 save = TRUE;
|
1
|
200 }
|
|
201 else
|
|
202 {
|
9
|
203 tl->pixbuf = pixbuf;
|
|
204 gdk_pixbuf_ref(tl->pixbuf);
|
|
205 save = FALSE;
|
|
206 }
|
|
207
|
|
208 /* save it ? */
|
|
209 if (tl->cache_enable && save)
|
|
210 {
|
|
211 thumb_loader_save_to_cache(tl);
|
|
212 }
|
|
213
|
|
214 if (tl->func_done) tl->func_done(tl, tl->data);
|
|
215 }
|
|
216
|
|
217 static void thumb_loader_error_cb(ImageLoader *il, gpointer data)
|
|
218 {
|
|
219 ThumbLoader *tl = data;
|
|
220
|
|
221 /* if at least some of the image is available, go to done_cb */
|
|
222 if (image_loader_get_pixbuf(tl->il) != NULL)
|
|
223 {
|
|
224 thumb_loader_done_cb(il, data);
|
|
225 return;
|
1
|
226 }
|
9
|
227
|
|
228 if (debug) printf("thumb error: %s\n", tl->path);
|
|
229
|
|
230 image_loader_free(tl->il);
|
|
231 tl->il = NULL;
|
|
232
|
|
233 if (tl->func_error) tl->func_error(tl, tl->data);
|
|
234 }
|
|
235
|
|
236 static gint thumb_loader_done_delay_cb(gpointer data)
|
|
237 {
|
|
238 ThumbLoader *tl = data;
|
|
239
|
|
240 tl->idle_done_id = -1;
|
|
241
|
|
242 if (tl->func_done) tl->func_done(tl, tl->data);
|
|
243
|
|
244 return FALSE;
|
|
245 }
|
|
246
|
|
247 static void thumb_loader_delay_done(ThumbLoader *tl)
|
|
248 {
|
|
249 if (tl->idle_done_id == -1) tl->idle_done_id = g_idle_add(thumb_loader_done_delay_cb, tl);
|
|
250 }
|
|
251
|
|
252 static void thumb_loader_setup(ThumbLoader *tl, gchar *path)
|
|
253 {
|
|
254 image_loader_free(tl->il);
|
|
255 tl->il = image_loader_new(path);
|
|
256
|
|
257 #if 0
|
|
258 /* this will speed up jpegs by up to 3x in some cases */
|
|
259 image_loader_set_requested_size(tl->max_w, tl->max_h);
|
|
260 #endif
|
|
261
|
|
262 image_loader_set_error_func(tl->il, thumb_loader_error_cb, tl);
|
|
263 if (tl->func_progress) image_loader_set_percent_func(tl->il, thumb_loader_percent_cb, tl);
|
|
264 }
|
|
265
|
|
266 void thumb_loader_set_callbacks(ThumbLoader *tl,
|
|
267 ThumbLoaderFunc func_done,
|
|
268 ThumbLoaderFunc func_error,
|
|
269 ThumbLoaderFunc func_progress,
|
|
270 gpointer data)
|
|
271 {
|
|
272 if (!tl) return;
|
|
273
|
|
274 if (tl->standard_loader)
|
|
275 {
|
|
276 thumb_loader_std_set_callbacks((ThumbLoaderStd *)tl,
|
|
277 (ThumbLoaderStdFunc) func_done,
|
|
278 (ThumbLoaderStdFunc) func_error,
|
|
279 (ThumbLoaderStdFunc) func_progress,
|
|
280 data);
|
|
281 return;
|
|
282 }
|
|
283
|
|
284 tl->func_done = func_done;
|
|
285 tl->func_error = func_error;
|
|
286 tl->func_progress = func_progress;
|
|
287
|
|
288 tl->data = data;
|
|
289 }
|
|
290
|
|
291 void thumb_loader_set_cache(ThumbLoader *tl, gint enable_cache, gint local, gint retry_failed)
|
|
292 {
|
|
293 if (!tl) return;
|
|
294
|
|
295 if (tl->standard_loader)
|
|
296 {
|
|
297 thumb_loader_std_set_cache((ThumbLoaderStd *)tl, enable_cache, local, retry_failed);
|
|
298 return;
|
|
299 }
|
|
300
|
|
301 tl->cache_enable = enable_cache;
|
|
302 #if 0
|
|
303 tl->cache_local = local;
|
|
304 tl->cache_retry = retry_failed;
|
|
305 #endif
|
1
|
306 }
|
|
307
|
|
308
|
9
|
309 gint thumb_loader_start(ThumbLoader *tl, const gchar *path)
|
|
310 {
|
|
311 gchar *cache_path = NULL;
|
1
|
312
|
9
|
313 if (!tl) return FALSE;
|
1
|
314
|
9
|
315 if (tl->standard_loader)
|
1
|
316 {
|
9
|
317 return thumb_loader_std_start((ThumbLoaderStd *)tl, path);
|
|
318 }
|
|
319
|
|
320 if (!tl->path && !path) return FALSE;
|
1
|
321
|
9
|
322 if (!tl->path) tl->path = g_strdup(path);
|
1
|
323
|
9
|
324 if (tl->cache_enable)
|
|
325 {
|
|
326 cache_path = cache_find_location(CACHE_TYPE_THUMB, tl->path);
|
|
327
|
|
328 if (cache_path)
|
1
|
329 {
|
9
|
330 if (cache_time_valid(cache_path, tl->path))
|
|
331 {
|
|
332 if (debug) printf("Found in cache:%s\n", tl->path);
|
1
|
333
|
9
|
334 if (filesize(cache_path) == 0)
|
1
|
335 {
|
9
|
336 if (debug) printf("Broken image mark found:%s\n", cache_path);
|
|
337 g_free(cache_path);
|
|
338 return FALSE;
|
1
|
339 }
|
9
|
340
|
|
341 if (debug) printf("Cache location:%s\n", cache_path);
|
|
342 }
|
|
343 else
|
|
344 {
|
|
345 g_free(cache_path);
|
|
346 cache_path = NULL;
|
1
|
347 }
|
|
348 }
|
9
|
349 }
|
|
350
|
|
351 if (!cache_path && use_xvpics_thumbnails)
|
|
352 {
|
|
353 tl->pixbuf = get_xv_thumbnail(tl->path, tl->max_w, tl->max_h);
|
|
354 if (tl->pixbuf)
|
|
355 {
|
|
356 thumb_loader_delay_done(tl);
|
|
357 return TRUE;
|
|
358 }
|
|
359 }
|
|
360
|
|
361 if (cache_path)
|
|
362 {
|
|
363 thumb_loader_setup(tl, cache_path);
|
|
364 g_free(cache_path);
|
|
365 tl->cache_hit = TRUE;
|
|
366 }
|
|
367 else
|
|
368 {
|
|
369 thumb_loader_setup(tl, tl->path);
|
|
370 }
|
|
371
|
|
372 if (!image_loader_start(tl->il, thumb_loader_done_cb, tl))
|
|
373 {
|
|
374 /* try from original if cache attempt */
|
|
375 if (tl->cache_hit)
|
|
376 {
|
|
377 tl->cache_hit = FALSE;
|
|
378 print_term(_("Thumbnail image in cache failed to load, trying to recreate.\n"));
|
|
379
|
|
380 thumb_loader_setup(tl, tl->path);
|
|
381 if (image_loader_start(tl->il, thumb_loader_done_cb, tl)) return TRUE;
|
|
382 }
|
|
383 /* mark failed thumbnail in cache with 0 byte file */
|
|
384 if (tl->cache_enable)
|
|
385 {
|
|
386 thumb_loader_mark_failure(tl);
|
|
387 }
|
|
388
|
|
389 image_loader_free(tl->il);
|
|
390 tl->il = NULL;
|
|
391 return FALSE;
|
|
392 }
|
|
393
|
|
394 return TRUE;
|
|
395 }
|
|
396
|
|
397 #if 0
|
|
398 gint thumb_loader_to_pixmap(ThumbLoader *tl, GdkPixmap **pixmap, GdkBitmap **mask)
|
|
399 {
|
|
400 if (!tl || !tl->pixbuf) return -1;
|
|
401
|
|
402 gdk_pixbuf_render_pixmap_and_mask(tl->pixbuf, pixmap, mask, 128);
|
|
403
|
|
404 return thumb_loader_get_space(tl);
|
|
405 }
|
|
406 #endif
|
|
407
|
|
408 GdkPixbuf *thumb_loader_get_pixbuf(ThumbLoader *tl, gint with_fallback)
|
|
409 {
|
|
410 GdkPixbuf *pixbuf;
|
|
411
|
|
412 if (tl && tl->standard_loader)
|
|
413 {
|
|
414 return thumb_loader_std_get_pixbuf((ThumbLoaderStd *)tl, with_fallback);
|
|
415 }
|
|
416
|
|
417 if (tl && tl->pixbuf)
|
|
418 {
|
|
419 pixbuf = tl->pixbuf;
|
|
420 g_object_ref(pixbuf);
|
|
421 }
|
|
422 else if (with_fallback)
|
|
423 {
|
|
424 gint w, h;
|
|
425
|
|
426 pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
|
|
427 w = gdk_pixbuf_get_width(pixbuf);
|
|
428 h = gdk_pixbuf_get_height(pixbuf);
|
|
429 if ((w > tl->max_w || h > tl->max_h) &&
|
|
430 normalize_thumb(&w, &h, tl->max_w, tl->max_h))
|
|
431 {
|
|
432 GdkPixbuf *tmp;
|
|
433
|
|
434 tmp = pixbuf;
|
|
435 pixbuf = gdk_pixbuf_scale_simple(tmp, w, h, GDK_INTERP_NEAREST);
|
|
436 gdk_pixbuf_unref(tmp);
|
|
437 }
|
1
|
438 }
|
9
|
439 else
|
|
440 {
|
|
441 pixbuf = NULL;
|
|
442 }
|
|
443
|
|
444 return pixbuf;
|
|
445 }
|
|
446
|
|
447 #if 0
|
|
448 gint thumb_loader_get_space(ThumbLoader *tl)
|
|
449 {
|
|
450 if (!tl) return 0;
|
|
451
|
|
452 if (tl->pixbuf) return (tl->max_w - gdk_pixbuf_get_width(tl->pixbuf));
|
|
453
|
|
454 return tl->max_w;
|
|
455 }
|
|
456 #endif
|
|
457
|
|
458 ThumbLoader *thumb_loader_new(gint width, gint height)
|
|
459 {
|
|
460 ThumbLoader *tl;
|
|
461
|
|
462 if (thumbnail_spec_standard)
|
|
463 {
|
|
464 return (ThumbLoader *)thumb_loader_std_new(width, height);
|
|
465 }
|
|
466
|
|
467 tl = g_new0(ThumbLoader, 1);
|
|
468 tl->standard_loader = FALSE;
|
|
469 tl->path = NULL;
|
|
470 tl->cache_enable = enable_thumb_caching;
|
|
471 tl->cache_hit = FALSE;
|
|
472 tl->percent_done = 0.0;
|
|
473 tl->max_w = width;
|
|
474 tl->max_h = height;
|
|
475
|
|
476 tl->il = NULL;
|
|
477
|
|
478 tl->idle_done_id = -1;
|
|
479
|
|
480 return tl;
|
1
|
481 }
|
|
482
|
9
|
483 void thumb_loader_free(ThumbLoader *tl)
|
|
484 {
|
|
485 if (!tl) return;
|
|
486
|
|
487 if (tl->standard_loader)
|
|
488 {
|
|
489 thumb_loader_std_free((ThumbLoaderStd *)tl);
|
|
490 return;
|
|
491 }
|
|
492
|
|
493 if (tl->pixbuf) gdk_pixbuf_unref(tl->pixbuf);
|
|
494 image_loader_free(tl->il);
|
|
495 g_free(tl->path);
|
|
496
|
|
497 if (tl->idle_done_id != -1) g_source_remove(tl->idle_done_id);
|
|
498
|
|
499 g_free(tl);
|
|
500 }
|
|
501
|
|
502 #if 0
|
|
503 gint thumb_from_xpm_d(const char **data, gint max_w, gint max_h, GdkPixmap **pixmap, GdkBitmap **mask)
|
|
504 {
|
|
505 GdkPixbuf *pixbuf;
|
|
506 gint w, h;
|
|
507
|
|
508 pixbuf = gdk_pixbuf_new_from_xpm_data(data);
|
|
509 w = gdk_pixbuf_get_width(pixbuf);
|
|
510 h = gdk_pixbuf_get_height(pixbuf);
|
|
511
|
|
512 if ((w > max_w || h > max_h) &&
|
|
513 normalize_thumb(&w, &h, max_w, max_h))
|
|
514 {
|
|
515 /* scale */
|
|
516 GdkPixbuf *tmp;
|
|
517
|
|
518 tmp = pixbuf;
|
|
519 pixbuf = gdk_pixbuf_scale_simple(tmp, w, h, GDK_INTERP_NEAREST);
|
|
520 gdk_pixbuf_unref(tmp);
|
|
521 }
|
|
522
|
|
523 gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap, mask, 128);
|
|
524 gdk_pixbuf_unref(pixbuf);
|
|
525
|
|
526 return w;
|
|
527 }
|
|
528 #endif
|
|
529
|
1
|
530 /*
|
|
531 *-----------------------------------------------------------------------------
|
|
532 * xvpics thumbnail support, read-only (private)
|
|
533 *-----------------------------------------------------------------------------
|
|
534 */
|
|
535
|
|
536 /*
|
|
537 * xvpics code originally supplied by:
|
|
538 * "Diederen Damien" <D.Diederen@student.ulg.ac.be>
|
|
539 *
|
|
540 * Note: Code has been modified to fit the style of the other code, and to use
|
|
541 * a few more glib-isms.
|
9
|
542 * 08-28-2000: Updated to return a gdk_pixbuf, Imlib is dieing a death here.
|
1
|
543 */
|
|
544
|
|
545 #define XV_BUFFER 2048
|
|
546 static guchar *load_xv_thumbnail(gchar *filename, gint *widthp, gint *heightp)
|
|
547 {
|
|
548 FILE *file;
|
|
549 gchar buffer[XV_BUFFER];
|
|
550 guchar *data;
|
|
551 gint width, height, depth;
|
|
552
|
|
553 file = fopen(filename, "rt");
|
|
554 if(!file) return NULL;
|
|
555
|
|
556 fgets(buffer, XV_BUFFER, file);
|
|
557 if(strncmp(buffer, "P7 332", 6) != 0)
|
|
558 {
|
|
559 fclose(file);
|
|
560 return NULL;
|
|
561 }
|
|
562
|
|
563 while(fgets(buffer, XV_BUFFER, file) && buffer[0] == '#') /* do_nothing() */;
|
|
564
|
|
565 if(sscanf(buffer, "%d %d %d", &width, &height, &depth) != 3)
|
|
566 {
|
|
567 fclose(file);
|
|
568 return NULL;
|
|
569 }
|
|
570
|
|
571 data = g_new(guchar, width * height);
|
|
572 fread(data, 1, width * height, file);
|
|
573
|
|
574 fclose(file);
|
|
575 *widthp = width;
|
|
576 *heightp = height;
|
|
577 return data;
|
|
578 }
|
|
579 #undef XV_BUFFER
|
|
580
|
9
|
581 static gint normalize_thumb(gint *width, gint *height, gint max_w, gint max_h)
|
1
|
582 {
|
9
|
583 gdouble scale;
|
|
584 gint new_w, new_h;
|
|
585
|
|
586 scale = MIN((gdouble) max_w / *width, (gdouble) max_h / *height);
|
|
587 new_w = *width * scale;
|
|
588 new_h = *height * scale;
|
|
589
|
|
590 if (new_w != *width || new_h != *height)
|
1
|
591 {
|
9
|
592 *width = new_w;
|
|
593 *height = new_h;
|
|
594 return TRUE;
|
1
|
595 }
|
9
|
596
|
|
597 return FALSE;
|
1
|
598 }
|
|
599
|
9
|
600 static void free_rgb_buffer(guchar *pixels, gpointer data)
|
|
601 {
|
|
602 g_free(pixels);
|
|
603 }
|
|
604
|
|
605 static GdkPixbuf *get_xv_thumbnail(gchar *thumb_filename, gint max_w, gint max_h)
|
1
|
606 {
|
|
607 gint width, height;
|
|
608 gchar *thumb_name;
|
|
609 gchar *tmp_string;
|
|
610 gchar *last_slash;
|
|
611 guchar *packed_data;
|
|
612
|
9
|
613 tmp_string = path_from_utf8(thumb_filename);
|
1
|
614 last_slash = strrchr(tmp_string, '/');
|
9
|
615 if(!last_slash) return NULL;
|
1
|
616 *last_slash++ = '\0';
|
|
617
|
|
618 thumb_name = g_strconcat(tmp_string, "/.xvpics/", last_slash, NULL);
|
|
619 packed_data = load_xv_thumbnail(thumb_name, &width, &height);
|
|
620 g_free(tmp_string);
|
|
621 g_free(thumb_name);
|
|
622
|
|
623 if(packed_data)
|
|
624 {
|
|
625 guchar *rgb_data;
|
9
|
626 GdkPixbuf *pixbuf;
|
1
|
627 gint i;
|
|
628
|
|
629 rgb_data = g_new(guchar, width * height * 3);
|
|
630 for(i = 0; i < width * height; i++)
|
|
631 {
|
|
632 rgb_data[i * 3 + 0] = (packed_data[i] >> 5) * 36;
|
|
633 rgb_data[i * 3 + 1] = ((packed_data[i] & 28) >> 2) * 36;
|
|
634 rgb_data[i * 3 + 2] = (packed_data[i] & 3) * 85;
|
|
635 }
|
9
|
636 g_free(packed_data);
|
1
|
637
|
9
|
638 pixbuf = gdk_pixbuf_new_from_data(rgb_data, GDK_COLORSPACE_RGB, FALSE, 8,
|
|
639 width, height, 3 * width, free_rgb_buffer, NULL);
|
|
640
|
|
641 if (normalize_thumb(&width, &height, max_w, max_h))
|
|
642 {
|
|
643 /* scale */
|
|
644 GdkPixbuf *tmp;
|
|
645
|
|
646 tmp = pixbuf;
|
|
647 pixbuf = gdk_pixbuf_scale_simple(tmp, width, height, GDK_INTERP_NEAREST);
|
|
648 gdk_pixbuf_unref(tmp);
|
|
649 }
|
1
|
650
|
9
|
651 return pixbuf;
|
1
|
652 }
|
|
653
|
9
|
654 return NULL;
|
1
|
655 }
|
|
656
|
9
|
657
|
|
658
|