Mercurial > geeqie
view src/thumb.c @ 2:0591360d4e38
More po.
author | gqview |
---|---|
date | Thu, 13 Apr 2000 12:53:03 +0000 |
parents | b3e0e515fabf |
children | c0e337a01cb7 |
line wrap: on
line source
/* * GQview image viewer * (C)1999 John Ellis * * Author: John Ellis * */ #include "gqview.h" #include "icons/img_unknown.xpm" /* fixme! duplicate, included in image.c too */ #define THUMBNAIL_CACHE_DIR "/.gqview_thmb" static guchar *load_xv_thumbnail(gchar *filename, gint *widthp, gint *heightp); static void normalize_thumb(gint *width, gint *height); static gint get_xv_thumbnail(gchar *thumb_filename, GdkPixmap **thumb_pixmap, GdkBitmap **thumb_mask); /* *----------------------------------------------------------------------------- * thumbnail routines: creation, caching, and maintenance (public) *----------------------------------------------------------------------------- */ gint create_thumbnail(gchar *path, GdkPixmap **thumb_pixmap, GdkBitmap **thumb_mask) { gint width, height; gint space; GdkImlibImage *thumb = NULL; GdkImlibImage *image = NULL; gint cached = FALSE; if (debug) printf("Gen thumbnail:%s\n",path); /* if xvpics enabled, check for that first */ if (use_xvpics_thumbnails) { space = get_xv_thumbnail(path, thumb_pixmap, thumb_mask); if (space != -1) { if (debug) printf("XV thumbnail found, loaded\n"); return space; } } /* start load from cache */ if (enable_thumb_caching) { gchar *cache_path; cache_path = g_strconcat(homedir(), THUMBNAIL_CACHE_DIR, path, ".png", NULL); if (isfile(cache_path) && filetime(cache_path) >= filetime(path)) { if (debug) printf("Found in cache:%s\n", path); image = gdk_imlib_load_image(cache_path); if (image && image->rgb_width != thumb_max_width && image->rgb_height != thumb_max_height) { if (debug) printf("Thumbnail size may have changed, reloading:%s\n", path); unlink(cache_path); gdk_imlib_destroy_image(image); image = gdk_imlib_load_image(path); } else { cached = TRUE; } } else image = gdk_imlib_load_image(path); } else image = gdk_imlib_load_image(path); if (!image) { image = gdk_imlib_create_image_from_xpm_data((gchar **)img_unknown_xpm); cached = TRUE; /* no need to save a thumbnail of the unknown pixmap */ } if (image) { if (image->rgb_width > thumb_max_width || image->rgb_height > thumb_max_height) { if (((float)thumb_max_width / image->rgb_width) < ((float)thumb_max_height / image->rgb_height)) { width = thumb_max_width; height = (float)width / image->rgb_width * image->rgb_height; if (height < 1) height = 1; } else { height = thumb_max_height; width = (float)height / image->rgb_height * image->rgb_width; if (width < 1) width = 1; } } else { width = image->rgb_width; height = image->rgb_height; cached = TRUE; /* don't cache images smaller than thumbnail size */ } if (*thumb_pixmap) gdk_imlib_free_pixmap(*thumb_pixmap); *thumb_pixmap = NULL; *thumb_mask = NULL; /* start save cache */ if (enable_thumb_caching && !cached) { gchar *thumb_path; gchar *base_dir; gchar *thumb_dir; gchar *image_dir; /* attempt at speed-up? move this here */ thumb = gdk_imlib_clone_scaled_image(image, width, height); gdk_imlib_destroy_image(image); image = NULL; base_dir = g_strconcat(homedir(), THUMBNAIL_CACHE_DIR, NULL); if (!isdir(base_dir)) { if (debug) printf("creating thumbnail dir:%s\n", base_dir); if (mkdir(base_dir, 0755) < 0) printf(_("create dir failed: %s\n"), base_dir); } image_dir = remove_level_from_path(path); thumb_dir = g_strconcat(base_dir, image_dir, NULL); g_free(image_dir); if (!isdir(thumb_dir)) { gchar *p = thumb_dir; while (p[0] != '\0') { p++; if (p[0] == '/' || p[0] == '\0') { gint end = TRUE; if (p[0] != '\0') { p[0] = '\0'; end = FALSE; } if (!isdir(thumb_dir)) { if (debug) printf("creating sub dir:%s\n",thumb_dir); if (mkdir(thumb_dir, 0755) < 0) printf(_("create dir failed: %s\n"), thumb_dir); } if (!end) p[0] = '/'; } } } g_free(thumb_dir); thumb_path = g_strconcat(base_dir, path, ".png", NULL); if (debug) printf("Saving thumb: %s\n",thumb_path); gdk_imlib_save_image(thumb, thumb_path, NULL); g_free(base_dir); g_free(thumb_path); } else { thumb = image; } /* end save cache */ gdk_imlib_render(thumb, width, height); *thumb_pixmap = gdk_imlib_move_image(thumb); *thumb_mask = gdk_imlib_move_mask(thumb); if (*thumb_pixmap) space = thumb_max_width - width; gdk_imlib_destroy_image(thumb); thumb = NULL; } else { space = -1; } return space; } gint maintain_thumbnail_dir(gchar *dir, gint recursive) { gchar *thumb_dir; gint base_length; gint still_have_a_file = FALSE; if (debug) printf("maintainance check: %s\n", dir); base_length = strlen(homedir()) + strlen(THUMBNAIL_CACHE_DIR); thumb_dir = g_strconcat(homedir(), THUMBNAIL_CACHE_DIR, dir, NULL); if (isdir(thumb_dir)) { DIR *dp; struct dirent *dirent; struct stat ent_sbuf; if((dp = opendir(thumb_dir))==NULL) { /* dir not found */ g_free(thumb_dir); return FALSE; } while ((dirent = readdir(dp)) != NULL) { /* skips removed files */ if (dirent->d_ino > 0) { int l = 0; gchar *path_buf; if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) continue; path_buf = g_strconcat(thumb_dir, "/", dirent->d_name, NULL); if (strlen(path_buf) > 4) l = strlen(path_buf) - 4; if (stat(path_buf,&ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode)) { /* recurse dir then delete it */ gchar *rdir = g_strconcat(dir, "/", dirent->d_name, NULL); if (recursive && !maintain_thumbnail_dir(rdir, TRUE)) { if (debug) printf("Deleting thumb dir: %s\n",path_buf); if ( (rmdir (path_buf) < 0) ) printf(_("Unable to delete dir: %s\n"), path_buf); } else still_have_a_file = TRUE; g_free(rdir); } else { gchar *fp = path_buf + l; fp[0] = '\0'; if (strlen(path_buf) > base_length && !isfile(path_buf + base_length)) { fp[0] = '.'; if (debug) printf("Deleting thumb: %s\n",path_buf); if ( (unlink (path_buf) < 0) ) printf(_("failed to delete:%s\n"),path_buf); } else still_have_a_file = TRUE; } g_free(path_buf); } } closedir(dp); } g_free(thumb_dir); return still_have_a_file; } /* *----------------------------------------------------------------------------- * xvpics thumbnail support, read-only (private) *----------------------------------------------------------------------------- */ /* * xvpics code originally supplied by: * "Diederen Damien" <D.Diederen@student.ulg.ac.be> * * Note: Code has been modified to fit the style of the other code, and to use * a few more glib-isms. */ #define XV_BUFFER 2048 static guchar *load_xv_thumbnail(gchar *filename, gint *widthp, gint *heightp) { FILE *file; gchar buffer[XV_BUFFER]; guchar *data; gint width, height, depth; file = fopen(filename, "rt"); if(!file) return NULL; fgets(buffer, XV_BUFFER, file); if(strncmp(buffer, "P7 332", 6) != 0) { fclose(file); return NULL; } while(fgets(buffer, XV_BUFFER, file) && buffer[0] == '#') /* do_nothing() */; if(sscanf(buffer, "%d %d %d", &width, &height, &depth) != 3) { fclose(file); return NULL; } data = g_new(guchar, width * height); fread(data, 1, width * height, file); fclose(file); *widthp = width; *heightp = height; return data; } #undef XV_BUFFER static void normalize_thumb(gint *width, gint *height) { if(*width > thumb_max_width || *height > thumb_max_height) { gfloat factor = MAX((gfloat) *width / thumb_max_width, (gfloat) *height / thumb_max_height); *width = (gfloat) *width / factor; *height = (gfloat) *height / factor; } } static gint get_xv_thumbnail(gchar *thumb_filename, GdkPixmap **thumb_pixmap, GdkBitmap **thumb_mask) { gint width, height; gchar *thumb_name; gchar *tmp_string; gchar *last_slash; guchar *packed_data; tmp_string = g_strdup(thumb_filename); last_slash = strrchr(tmp_string, '/'); if(!last_slash) return -1; *last_slash++ = '\0'; thumb_name = g_strconcat(tmp_string, "/.xvpics/", last_slash, NULL); packed_data = load_xv_thumbnail(thumb_name, &width, &height); g_free(tmp_string); g_free(thumb_name); if(packed_data) { guchar *rgb_data; GdkImlibImage *image; gint i; rgb_data = g_new(guchar, width * height * 3); for(i = 0; i < width * height; i++) { rgb_data[i * 3 + 0] = (packed_data[i] >> 5) * 36; rgb_data[i * 3 + 1] = ((packed_data[i] & 28) >> 2) * 36; rgb_data[i * 3 + 2] = (packed_data[i] & 3) * 85; } g_free(packed_data); image = gdk_imlib_create_image_from_data(rgb_data, NULL, width, height); g_free(rgb_data); normalize_thumb(&width, &height); gdk_imlib_render(image, width, height); if(*thumb_pixmap) gdk_imlib_free_pixmap(*thumb_pixmap); *thumb_pixmap = gdk_imlib_move_image(image); *thumb_mask = gdk_imlib_move_mask(image); gdk_imlib_destroy_image(image); return thumb_max_width - width; } return -1; }