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 */
56 static int RImageCacheSize
= -1;
59 * Max. size of image to store in cache
61 static int RImageCacheMaxImage
= -1; /* 0 = any size */
63 #define IMAGE_CACHE_SIZE 8
65 #define IMAGE_CACHE_MAX_IMAGE 64*64
67 static RCachedImage
*RImageCache
;
81 /* How many image types do we have. */
82 /* Increase this when adding new image types! */
86 static int identFile(char *path
);
88 extern RImage
*RLoadPPM(RContext
*context
, char *file_name
, int index
);
90 extern RImage
*RLoadXPM(RContext
*context
, char *file
, int index
);
94 extern RImage
*RLoadTIFF(RContext
*context
, char *file
, int index
);
97 extern RImage
*RLoadPNG(RContext
*context
, char *file
, int index
);
100 extern RImage
*RLoadJPEG(RContext
*context
, char *file_name
, int index
);
103 extern RImage
*RLoadGIF(RContext
*context
, char *file_name
, int index
);
108 RSupportedFileFormats(void)
110 static char *tmp
[IM_TYPES
+1];
140 tmp
= getenv("RIMAGE_CACHE");
141 if (!tmp
|| sscanf(tmp
, "%i", &RImageCacheSize
)!=1) {
142 RImageCacheSize
= IMAGE_CACHE_SIZE
;
144 if (RImageCacheSize
<0)
147 tmp
= getenv("RIMAGE_CACHE_SIZE");
148 if (!tmp
|| sscanf(tmp
, "%i", &RImageCacheMaxImage
)!=1) {
149 RImageCacheMaxImage
= IMAGE_CACHE_MAX_IMAGE
;
152 if (RImageCacheSize
>0) {
153 RImageCache
= malloc(sizeof(RCachedImage
)*RImageCacheSize
);
154 if (RImageCache
==NULL
) {
155 printf("wrlib: out of memory for image cache\n");
158 memset(RImageCache
, 0, sizeof(RCachedImage
)*RImageCacheSize
);
164 RLoadImage(RContext
*context
, char *file
, int index
)
166 RImage
*image
= NULL
;
172 if (RImageCacheSize
<0) {
176 if (RImageCacheSize
>0) {
178 for (i
=0; i
<RImageCacheSize
; i
++) {
179 if (RImageCache
[i
].file
180 && strcmp(file
, RImageCache
[i
].file
)==0) {
182 if (stat(file
, &st
)==0
183 && st
.st_mtime
== RImageCache
[i
].last_modif
) {
184 RImageCache
[i
].last_use
= time(NULL
);
186 return RCloneImage(RImageCache
[i
].image
);
189 free(RImageCache
[i
].file
);
190 RImageCache
[i
].file
= NULL
;
191 RReleaseImage(RImageCache
[i
].image
);
197 switch (identFile(file
)) {
202 RErrorCode
= RERR_BADFORMAT
;
206 image
= RLoadXPM(context
, file
, index
);
211 image
= RLoadTIFF(context
, file
, index
);
213 #endif /* USE_TIFF */
217 image
= RLoadPNG(context
, file
, index
);
223 image
= RLoadJPEG(context
, file
, index
);
225 #endif /* USE_JPEG */
229 image
= RLoadGIF(context
, file
, index
);
234 image
= RLoadPPM(context
, file
, index
);
238 RErrorCode
= RERR_BADFORMAT
;
243 /* store image in cache */
244 if (RImageCacheSize
>0 && image
&&
245 (RImageCacheMaxImage
==0
246 || RImageCacheMaxImage
>= image
->width
*image
->height
)) {
247 time_t oldest
=time(NULL
);
251 for (i
=0; i
<RImageCacheSize
; i
++) {
252 if (!RImageCache
[i
].file
) {
253 RImageCache
[i
].file
= malloc(strlen(file
)+1);
254 strcpy(RImageCache
[i
].file
, file
);
255 RImageCache
[i
].image
= RCloneImage(image
);
256 RImageCache
[i
].last_modif
= st
.st_mtime
;
257 RImageCache
[i
].last_use
= time(NULL
);
261 if (oldest
> RImageCache
[i
].last_use
) {
262 oldest
= RImageCache
[i
].last_use
;
268 /* if no slot available, dump least recently used one */
270 free(RImageCache
[oldest_idx
].file
);
271 RReleaseImage(RImageCache
[oldest_idx
].image
);
272 RImageCache
[oldest_idx
].file
= malloc(strlen(file
)+1);
273 strcpy(RImageCache
[oldest_idx
].file
, file
);
274 RImageCache
[oldest_idx
].image
= RCloneImage(image
);
275 RImageCache
[oldest_idx
].last_modif
= st
.st_mtime
;
276 RImageCache
[oldest_idx
].last_use
= time(NULL
);
285 RGetImageFileFormat(char *file
)
287 switch (identFile(file
)) {
294 #endif /* USE_TIFF */
304 #endif /* USE_JPEG */
321 identFile(char *path
)
324 unsigned char buffer
[32];
328 fd
= open(path
, O_RDONLY
|O_BINARY
);
330 RErrorCode
= RERR_OPEN
;
333 if (read(fd
, buffer
, 32)<1) {
335 RErrorCode
= RERR_READ
;
341 if (strncmp((char*)buffer
, "/* XPM */", 9)==0)
345 if ((buffer
[0]=='I' && buffer
[1]=='I' && buffer
[2]=='*' && buffer
[3]==0)
346 ||(buffer
[0]=='M' && buffer
[1]=='M' && buffer
[2]==0 && buffer
[3]=='*'))
351 if (png_check_sig(buffer
, 8))
355 /* check for raw PPM or PGM */
356 if (buffer
[0]=='P' && (buffer
[1]=='5' || buffer
[1]=='6'))
360 if (buffer
[0] == 0xff && buffer
[1] == 0xd8)
364 if (buffer
[0] == 'G' && buffer
[1] == 'I' && buffer
[2] == 'F')