1 /* load.c - load image from file
3 * Raster graphics library
5 * Copyright (c) 1997 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.
41 typedef struct RCachedImage
{
44 time_t last_modif
; /* last time file was modified */
45 time_t last_use
; /* last time image was used */
52 static int RImageCacheSize
= -1;
55 * Max. size of image to store in cache
57 static int RImageCacheMaxImage
= -1; /* 0 = any size */
59 #define IMAGE_CACHE_SIZE 8
61 #define IMAGE_CACHE_MAX_IMAGE 64*64
63 static RCachedImage
*RImageCache
;
77 /* How many image types do we have. */
78 /* Increase this when adding new image types! */
82 static int identFile(char *path
);
84 extern RImage
*RLoadPPM(RContext
*context
, char *file_name
, int index
);
86 extern RImage
*RLoadXPM(RContext
*context
, char *file
, int index
);
90 extern RImage
*RLoadTIFF(RContext
*context
, char *file
, int index
);
93 extern RImage
*RLoadPNG(RContext
*context
, char *file
, int index
);
96 extern RImage
*RLoadJPEG(RContext
*context
, char *file_name
, int index
);
99 extern RImage
*RLoadGIF(RContext
*context
, char *file_name
, int index
);
108 tmp
= malloc(strlen(s
)+1);
111 return strcpy(tmp
, s
);
115 RSupportedFileFormats(void)
120 tmp
= malloc(sizeof(char*)*(IM_TYPES
+1));
123 memset(tmp
, 0, sizeof(char*)*(IM_TYPES
+1));
126 tmp
[i
++] = wstrdup("XPM");
128 RFreeStringList(tmp
);
132 tmp
[i
++] = wstrdup("PPM");
134 RFreeStringList(tmp
);
138 tmp
[i
++] = wstrdup("TIFF");
140 RFreeStringList(tmp
);
145 tmp
[i
++] = wstrdup("PNG");
147 RFreeStringList(tmp
);
152 tmp
[i
++] = wstrdup("JPEG");
154 RFreeStringList(tmp
);
159 tmp
[i
++] = wstrdup("GIF");
161 RFreeStringList(tmp
);
172 RFreeStringList(char **list
)
176 for (i
= 0; list
[i
]!=NULL
; i
++) {
188 tmp
= getenv("RIMAGE_CACHE");
189 if (!tmp
|| sscanf(tmp
, "%i", &RImageCacheSize
)!=1) {
190 RImageCacheSize
= IMAGE_CACHE_SIZE
;
192 if (RImageCacheSize
<0)
195 tmp
= getenv("RIMAGE_CACHE_SIZE");
196 if (!tmp
|| sscanf(tmp
, "%i", &RImageCacheMaxImage
)!=1) {
197 RImageCacheMaxImage
= IMAGE_CACHE_MAX_IMAGE
;
200 if (RImageCacheSize
>0) {
201 RImageCache
= malloc(sizeof(RCachedImage
)*RImageCacheSize
);
202 if (RImageCache
==NULL
) {
203 printf("wrlib: out of memory for image cache\n");
206 memset(RImageCache
, 0, sizeof(RCachedImage
)*RImageCacheSize
);
212 RLoadImage(RContext
*context
, char *file
, int index
)
214 RImage
*image
= NULL
;
220 if (RImageCacheSize
<0) {
224 if (RImageCacheSize
>0) {
226 for (i
=0; i
<RImageCacheSize
; i
++) {
227 if (RImageCache
[i
].file
228 && strcmp(file
, RImageCache
[i
].file
)==0) {
230 if (stat(file
, &st
)==0
231 && st
.st_mtime
== RImageCache
[i
].last_modif
) {
232 RImageCache
[i
].last_use
= time(NULL
);
234 return RCloneImage(RImageCache
[i
].image
);
237 free(RImageCache
[i
].file
);
238 RImageCache
[i
].file
= NULL
;
239 RDestroyImage(RImageCache
[i
].image
);
245 switch (identFile(file
)) {
250 RErrorCode
= RERR_BADFORMAT
;
254 image
= RLoadXPM(context
, file
, index
);
259 image
= RLoadTIFF(context
, file
, index
);
261 #endif /* USE_TIFF */
265 image
= RLoadPNG(context
, file
, index
);
271 image
= RLoadJPEG(context
, file
, index
);
273 #endif /* USE_JPEG */
277 image
= RLoadGIF(context
, file
, index
);
282 image
= RLoadPPM(context
, file
, index
);
286 RErrorCode
= RERR_BADFORMAT
;
291 /* store image in cache */
292 if (RImageCacheSize
>0 && image
&&
293 (RImageCacheMaxImage
==0
294 || RImageCacheMaxImage
>= image
->width
*image
->height
)) {
295 time_t oldest
=time(NULL
);
299 for (i
=0; i
<RImageCacheSize
; i
++) {
300 if (!RImageCache
[i
].file
) {
301 RImageCache
[i
].file
= malloc(strlen(file
)+1);
302 strcpy(RImageCache
[i
].file
, file
);
303 RImageCache
[i
].image
= RCloneImage(image
);
304 RImageCache
[i
].last_modif
= st
.st_mtime
;
305 RImageCache
[i
].last_use
= time(NULL
);
309 if (oldest
> RImageCache
[i
].last_use
) {
310 oldest
= RImageCache
[i
].last_use
;
316 /* if no slot available, dump least recently used one */
318 free(RImageCache
[oldest_idx
].file
);
319 RDestroyImage(RImageCache
[oldest_idx
].image
);
320 RImageCache
[oldest_idx
].file
= malloc(strlen(file
)+1);
321 strcpy(RImageCache
[oldest_idx
].file
, file
);
322 RImageCache
[oldest_idx
].image
= RCloneImage(image
);
323 RImageCache
[oldest_idx
].last_modif
= st
.st_mtime
;
324 RImageCache
[oldest_idx
].last_use
= time(NULL
);
336 identFile(char *path
)
339 unsigned char buffer
[32];
343 fd
= open(path
, O_RDONLY
);
345 RErrorCode
= RERR_OPEN
;
348 if (read(fd
, buffer
, 32)<1) {
350 RErrorCode
= RERR_READ
;
356 if (strncmp((char*)buffer
, "/* XPM */", 9)==0)
360 if ((buffer
[0]=='I' && buffer
[1]=='I' && buffer
[2]=='*' && buffer
[3]==0)
361 ||(buffer
[0]=='M' && buffer
[1]=='M' && buffer
[2]==0 && buffer
[3]=='*'))
366 if (png_check_sig(buffer
, 8))
370 /* check for raw PPM or PGM */
371 if (buffer
[0]=='P' && (buffer
[1]=='5' || buffer
[1]=='6'))
375 if (buffer
[0] == 0xff && buffer
[1] == 0xd8)
379 if (buffer
[0] == 'G' && buffer
[1] == 'I' && buffer
[2] == 'F')