1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * Electric Eyes thumbnail support plugin for GImageView
5  * Copyright (C) 2001 Takuro Ashie
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * $Id: ee.c,v 1.18 2003/07/13 13:20:18 makeinu Exp $
22  */
23 
24 #include <string.h>
25 #include <gtk/gtk.h>
26 #include <gmodule.h>
27 
28 #include "fileutil.h"
29 #include "gfileutil.h"
30 #include "intl.h"
31 #include "gimv_plugin.h"
32 #include "gimv_thumb_cache.h"
33 
34 
35 #ifndef BUF_SIZE
36 #define BUF_SIZE 4096
37 #endif
38 
39 #ifndef MAX_PATH_LEN
40 #define MAX_PATH_LEN 1024
41 #endif
42 
43 /* under image directory */
44 #define EE_THUMNAIL_DIRECTORY ".ee"
45 
46 
47 typedef struct EEThumbPrefs_Tag
48 {
49    gint   width;
50    gint   height;
51    gchar *dir;
52 } EEThumbPrefs;
53 
54 
55 static GimvImage *load_thumb (const gchar *filename,
56                               const gchar *cache_type,
57                               GimvImageInfo *info);
58 static GimvImage *save_thumb (const gchar *filename,
59                               const gchar *cache_type,
60                               GimvImage   *image,
61                               GimvImageInfo *info);
62 static gchar     *get_path   (const gchar *filename,
63                               const gchar *cache_type);
64 static gboolean   get_size   (gint         width,
65                               gint         height,
66                               const gchar *cache_type,
67                               gint        *width_ret,
68                               gint        *height_ret);
69 
70 
71 static EEThumbPrefs ee_thumb_prefs [] =
72 {
73    {180, 180, "large"},
74    {256, 64,  "med"},
75    {256, 24,  "small"},
76 };
77 static gint ee_thumb_prefs_num
78 = sizeof (ee_thumb_prefs) / sizeof (ee_thumb_prefs[0]);
79 
80 static GimvThumbCacheLoader plugin_impl[] =
81 {
82    {GIMV_THUMB_CACHE_LOADER_IF_VERSION,
83     N_("Electric Eyes (Preview)"),
84     load_thumb, save_thumb,
85     get_path, get_size,
86     NULL, NULL, NULL, NULL, NULL},
87 
88    {GIMV_THUMB_CACHE_LOADER_IF_VERSION,
89     N_("Electric Eyes (Icon)"),
90     load_thumb, save_thumb,
91     get_path, get_size,
92     NULL, NULL, NULL, NULL, NULL},
93 
94    {GIMV_THUMB_CACHE_LOADER_IF_VERSION,
95     N_("Electric Eyes (Mini)"),
96     load_thumb, save_thumb,
97     get_path, get_size,
98     NULL, NULL, NULL, NULL, NULL},
99 };
100 static gint plugin_impl_num = sizeof (plugin_impl) / sizeof (plugin_impl[0]);
101 
102 GIMV_PLUGIN_GET_IMPL(plugin_impl, GIMV_PLUGIN_THUMB_CACHE)
103 
104 GimvPluginInfo gimv_plugin_info =
105 {
106    if_version:    GIMV_PLUGIN_IF_VERSION,
107    name:          N_("Electric Eyes thumbnail support"),
108    version:       "0.5.0",
109    author:        N_("Takuro Ashie"),
110    description:   NULL,
111    get_implement: gimv_plugin_get_impl,
112    get_mime_type: NULL,
113    get_prefs_ui:  NULL,
114 };
115 
116 
117 gchar *
g_module_check_init(GModule * module)118 g_module_check_init (GModule *module)
119 {
120    return NULL;
121 }
122 
123 
124 void
g_module_unload(GModule * module)125 g_module_unload (GModule *module)
126 {
127    return;
128 }
129 
130 
131 static GimvImage *
load_thumb(const gchar * filename,const gchar * cache_type,GimvImageInfo * info)132 load_thumb (const gchar *filename, const gchar *cache_type,
133             GimvImageInfo *info)
134 {
135    GimvImage *image;
136    gchar *thumb_file;
137 
138    g_return_val_if_fail (filename, NULL);
139    g_return_val_if_fail (cache_type, NULL);
140 
141    thumb_file = get_path (filename, cache_type);
142 
143    g_return_val_if_fail (thumb_file, NULL);
144 
145    image = gimv_image_load_file (thumb_file, FALSE);
146 
147    g_free (thumb_file);
148 
149    return image;
150 }
151 
152 
153 static GimvImage *
save_thumb(const gchar * filename,const gchar * cache_type,GimvImage * image,GimvImageInfo * info)154 save_thumb (const gchar *filename, const gchar *cache_type,
155             GimvImage *image, GimvImageInfo *info)
156 {
157    GimvImage *imcache;
158    gchar *thumb_file;
159    gint im_width = -1, im_height = -1, width = -1, height = -1;
160    gboolean success;
161 
162    /* check args */
163    g_return_val_if_fail (filename, FALSE);
164    g_return_val_if_fail (image, FALSE);
165    g_return_val_if_fail (cache_type, FALSE);
166 
167    thumb_file = get_path (filename, cache_type);
168    g_return_val_if_fail (thumb_file, FALSE);
169 
170    /* get image width & height */
171    gimv_image_get_size (image, &im_width, &im_height);
172    if (im_width < 1 || im_height < 1) return NULL;
173 
174    /* get thumnail width & height */
175    success = get_size (im_width, im_height, cache_type, &width, &height);
176    if (!success || width < 1 || height < 1) return NULL;
177 
178    /* create cache directory if not found */
179    success = mkdirs (thumb_file);
180    if (!success) return NULL;
181 
182    /* scale image */
183    imcache = gimv_image_scale (image, width, height);
184 
185    /* save cache to disk */
186    if (imcache) {
187       g_print (N_("save cache: %s\n"), thumb_file);
188       gimv_image_save_file (imcache, thumb_file, "ppm");
189    }
190 
191    g_free (thumb_file);
192 
193    return imcache;
194 }
195 
196 
197 static gchar *
get_path(const gchar * filename,const gchar * cache_type)198 get_path (const gchar *filename, const gchar *cache_type)
199 {
200    gchar *abspath;
201    gchar buf[MAX_PATH_LEN];
202    gchar *size = NULL;
203    gint i;
204 
205    g_return_val_if_fail (filename, NULL);
206    g_return_val_if_fail (cache_type, NULL);
207 
208    for (i = 0; (i < plugin_impl_num) && (i < ee_thumb_prefs_num); i++) {
209       if (!strcmp (cache_type, plugin_impl[i].label)) {
210          size = ee_thumb_prefs[i].dir;
211          break;
212       }
213    }
214 
215    g_return_val_if_fail (size, NULL);
216 
217    abspath = relpath2abs (filename);
218    g_return_val_if_fail (abspath, NULL);
219 
220    g_snprintf (buf, MAX_PATH_LEN, "%s/%s/%s%s",
221                g_getenv("HOME"), EE_THUMNAIL_DIRECTORY, size, filename);
222 
223    g_free (abspath);
224 
225    return g_strdup (buf);
226 }
227 
228 
229 static gboolean
get_size(gint width,gint height,const gchar * cache_type,gint * width_ret,gint * height_ret)230 get_size (gint width, gint height, const gchar *cache_type,
231           gint *width_ret, gint *height_ret)
232 {
233    gint max_width = -1, max_height = -1;
234    gint i;
235    gboolean use_large = FALSE;
236 
237    /* check args */
238    g_return_val_if_fail (width_ret && height_ret, FALSE);
239    *width_ret = *height_ret = -1;
240 
241    g_return_val_if_fail (cache_type, FALSE);
242 
243    if (width < 1 || height < 1)
244       return FALSE;
245 
246    /* get max thumbnail size */
247    for (i = 0; (i < plugin_impl_num) && (i < ee_thumb_prefs_num); i++) {
248       if (!strcmp (cache_type, plugin_impl[i].label)) {
249          max_width =  ee_thumb_prefs[i].width;
250          max_height = ee_thumb_prefs[i].height;
251          if (i == 0)
252             use_large = TRUE;
253          break;
254       }
255    }
256    g_return_val_if_fail (max_width > 0 && max_height > 0, FALSE);
257 
258    /* no need to scale */
259    if (width < max_width && height < max_height) {
260       *width_ret  = width;
261       *height_ret = height;
262       return TRUE;
263    }
264 
265    /* calculate width & height of thumbnail */
266    if (width < height || !use_large) {
267       *width_ret = (gfloat) width * (gfloat) max_height / (gfloat) height;
268       *height_ret = max_height;
269       if (!use_large && width > max_width) {
270          *width_ret = max_width;
271          *height_ret = (gfloat) height * (gfloat) max_width / (gfloat) width;
272       }
273    } else {
274       *width_ret = max_width;
275       *height_ret = (gfloat) height * (gfloat) max_width / (gfloat) width;
276    }
277 
278    return TRUE;
279 }
280