1 /* load.c - load image from file
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library 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 GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40 /* Silly hack for Windows systems with cygwin */
45 typedef struct RCachedImage {
48 time_t last_modif; /* last time file was modified */
49 time_t last_use; /* last time image was used */
55 static int RImageCacheSize = -1;
58 * Max. size of image to store in cache
60 static int RImageCacheMaxImage = -1; /* 0 = any size */
62 #define IMAGE_CACHE_SIZE 8
64 #define IMAGE_CACHE_MAX_IMAGE 64*64
66 static RCachedImage *RImageCache;
76 /* How many image types do we have. */
77 /* Increase this when adding new image types! */
80 static int identFile(char *path);
82 extern RImage *RLoadPPM(RContext * context, char *file_name, int index);
84 extern RImage *RLoadXPM(RContext * context, char *file, int index);
87 extern RImage *RLoadTIFF(RContext * context, char *file, int index);
90 extern RImage *RLoadPNG(RContext * context, char *file, int index);
93 extern RImage *RLoadJPEG(RContext * context, char *file_name, int index);
96 extern RImage *RLoadGIF(RContext * context, char *file_name, int index);
99 char **RSupportedFileFormats(void)
101 static char *tmp[IM_TYPES + 1];
125 static void init_cache()
129 tmp = getenv("RIMAGE_CACHE");
130 if (!tmp || sscanf(tmp, "%i", &RImageCacheSize) != 1) {
131 RImageCacheSize = IMAGE_CACHE_SIZE;
133 if (RImageCacheSize < 0)
136 tmp = getenv("RIMAGE_CACHE_SIZE");
137 if (!tmp || sscanf(tmp, "%i", &RImageCacheMaxImage) != 1) {
138 RImageCacheMaxImage = IMAGE_CACHE_MAX_IMAGE;
141 if (RImageCacheSize > 0) {
142 RImageCache = malloc(sizeof(RCachedImage) * RImageCacheSize);
143 if (RImageCache == NULL) {
144 printf("wrlib: out of memory for image cache\n");
147 memset(RImageCache, 0, sizeof(RCachedImage) * RImageCacheSize);
151 RImage *RLoadImage(RContext * context, char *file, int index)
153 RImage *image = NULL;
157 assert(file != NULL);
159 if (RImageCacheSize < 0) {
163 if (RImageCacheSize > 0) {
165 for (i = 0; i < RImageCacheSize; i++) {
166 if (RImageCache[i].file && strcmp(file, RImageCache[i].file) == 0) {
168 if (stat(file, &st) == 0 && st.st_mtime == RImageCache[i].last_modif) {
169 RImageCache[i].last_use = time(NULL);
171 return RCloneImage(RImageCache[i].image);
174 free(RImageCache[i].file);
175 RImageCache[i].file = NULL;
176 RReleaseImage(RImageCache[i].image);
182 switch (identFile(file)) {
187 RErrorCode = RERR_BADFORMAT;
191 image = RLoadXPM(context, file, index);
196 image = RLoadTIFF(context, file, index);
198 #endif /* USE_TIFF */
202 image = RLoadPNG(context, file, index);
208 image = RLoadJPEG(context, file, index);
210 #endif /* USE_JPEG */
214 image = RLoadGIF(context, file, index);
219 image = RLoadPPM(context, file, index);
223 RErrorCode = RERR_BADFORMAT;
227 /* store image in cache */
228 if (RImageCacheSize > 0 && image &&
229 (RImageCacheMaxImage == 0 || RImageCacheMaxImage >= image->width * image->height)) {
230 time_t oldest = time(NULL);
234 for (i = 0; i < RImageCacheSize; i++) {
235 if (!RImageCache[i].file) {
236 RImageCache[i].file = malloc(strlen(file) + 1);
237 strcpy(RImageCache[i].file, file);
238 RImageCache[i].image = RCloneImage(image);
239 RImageCache[i].last_modif = st.st_mtime;
240 RImageCache[i].last_use = time(NULL);
244 if (oldest > RImageCache[i].last_use) {
245 oldest = RImageCache[i].last_use;
251 /* if no slot available, dump least recently used one */
253 free(RImageCache[oldest_idx].file);
254 RReleaseImage(RImageCache[oldest_idx].image);
255 RImageCache[oldest_idx].file = malloc(strlen(file) + 1);
256 strcpy(RImageCache[oldest_idx].file, file);
257 RImageCache[oldest_idx].image = RCloneImage(image);
258 RImageCache[oldest_idx].last_modif = st.st_mtime;
259 RImageCache[oldest_idx].last_use = time(NULL);
266 char *RGetImageFileFormat(char *file)
268 switch (identFile(file)) {
275 #endif /* USE_TIFF */
285 #endif /* USE_JPEG */
300 static int identFile(char *path)
303 unsigned char buffer[32];
305 assert(path != NULL);
307 fd = open(path, O_RDONLY | O_BINARY);
309 RErrorCode = RERR_OPEN;
312 if (read(fd, buffer, 32) < 1) {
314 RErrorCode = RERR_READ;
320 if (strncmp((char *)buffer, "/* XPM */", 9) == 0)
324 if ((buffer[0] == 'I' && buffer[1] == 'I' && buffer[2] == '*' && buffer[3] == 0)
325 || (buffer[0] == 'M' && buffer[1] == 'M' && buffer[2] == 0 && buffer[3] == '*'))
330 if (png_check_sig(buffer, 8))
334 /* check for raw PPM or PGM */
335 if (buffer[0] == 'P' && (buffer[1] == '5' || buffer[1] == '6'))
339 if (buffer[0] == 0xff && buffer[1] == 0xd8)
343 if (buffer[0] == 'G' && buffer[1] == 'I' && buffer[2] == 'F')