diff --git a/src/lib/Imlib2.h b/src/lib/Imlib2.h index 10ebbd0..cd27178 100644 --- a/src/lib/Imlib2.h +++ b/src/lib/Imlib2.h @@ -219,6 +219,7 @@ EAPI Imlib_Image imlib_load_image_immediately(const char *file); EAPI Imlib_Image imlib_load_image_without_cache(const char *file); EAPI Imlib_Image imlib_load_image_immediately_without_cache(const char *file); +EAPI Imlib_Image imlib_load_image_fd(int fd, const char *file); EAPI Imlib_Image imlib_load_image_with_error_return(const char *file, Imlib_Load_Error * error_return); diff --git a/src/lib/api.c b/src/lib/api.c index e94bebf..2d6a829 100644 --- a/src/lib/api.c +++ b/src/lib/api.c @@ -1314,7 +1314,8 @@ imlib_load_image(const char *file) CHECK_CONTEXT(ctx); CHECK_PARAM_POINTER_RETURN("imlib_load_image", "file", file, NULL); prev_ctxt_image = ctx->image; - im = __imlib_LoadImage(file, (ImlibProgressFunction) ctx->progress_func, + im = __imlib_LoadImage(file, NULL, + (ImlibProgressFunction) ctx->progress_func, ctx->progress_granularity, 0, 0, NULL); ctx->image = prev_ctxt_image; return (Imlib_Image) im; @@ -1339,7 +1340,8 @@ imlib_load_image_immediately(const char *file) CHECK_PARAM_POINTER_RETURN("imlib_load_image_immediately", "file", file, NULL); prev_ctxt_image = ctx->image; - im = __imlib_LoadImage(file, (ImlibProgressFunction) ctx->progress_func, + im = __imlib_LoadImage(file, NULL, + (ImlibProgressFunction) ctx->progress_func, ctx->progress_granularity, 1, 0, NULL); ctx->image = prev_ctxt_image; return (Imlib_Image) im; @@ -1362,7 +1364,8 @@ imlib_load_image_without_cache(const char *file) CHECK_PARAM_POINTER_RETURN("imlib_load_image_without_cache", "file", file, NULL); prev_ctxt_image = ctx->image; - im = __imlib_LoadImage(file, (ImlibProgressFunction) ctx->progress_func, + im = __imlib_LoadImage(file, NULL, + (ImlibProgressFunction) ctx->progress_func, ctx->progress_granularity, 0, 1, NULL); ctx->image = prev_ctxt_image; return (Imlib_Image) im; @@ -1386,12 +1389,49 @@ imlib_load_image_immediately_without_cache(const char *file) CHECK_PARAM_POINTER_RETURN("imlib_load_image_immediately_without_cache", "file", file, NULL); prev_ctxt_image = ctx->image; - im = __imlib_LoadImage(file, (ImlibProgressFunction) ctx->progress_func, + im = __imlib_LoadImage(file, NULL, + (ImlibProgressFunction) ctx->progress_func, ctx->progress_granularity, 1, 1, NULL); ctx->image = prev_ctxt_image; return (Imlib_Image) im; } +/** + * @param fd Image file descriptor. + * @param file Image file. + * @return An image handle. + * + * Loads the image without deferred image data decoding (i.e. it is + * decoded straight away) and without looking in the cache. Returns an + * image handle on success or NULL on failure. + * fd will be closed after calling this function. + */ +EAPI Imlib_Image +imlib_load_image_fd(int fd, const char *file) +{ + Imlib_Image im = NULL; + Imlib_Image prev_ctxt_image; + FILE *fp; + + CHECK_CONTEXT(ctx); + CHECK_PARAM_POINTER_RETURN("imlib_load_image_fd", "file", file, NULL); + fp = fdopen(fd, "rb"); + if (fp) + { + prev_ctxt_image = ctx->image; + im = __imlib_LoadImage(file, fp, + (ImlibProgressFunction) ctx->progress_func, + ctx->progress_granularity, 1, 1, NULL); + fclose(fp); + ctx->image = prev_ctxt_image; + } + else + { + close(fd); + } + return (Imlib_Image) im; +} + /** * @param file Image file. * @param error_return The returned error. @@ -1413,7 +1453,8 @@ imlib_load_image_with_error_return(const char *file, CHECK_PARAM_POINTER_RETURN("imlib_load_image_with_error_return", "file", file, NULL); prev_ctxt_image = ctx->image; - im = __imlib_LoadImage(file, (ImlibProgressFunction) ctx->progress_func, + im = __imlib_LoadImage(file, NULL, + (ImlibProgressFunction) ctx->progress_func, ctx->progress_granularity, 1, 0, &er); ctx->image = prev_ctxt_image; if (im) diff --git a/src/lib/file.c b/src/lib/file.c index 5616859..7dcd219 100644 --- a/src/lib/file.c +++ b/src/lib/file.c @@ -167,6 +167,17 @@ __imlib_FileModDate(const char *s) return (st.st_mtime > st.st_ctime) ? st.st_mtime : st.st_ctime; } +time_t +__imlib_FileModDateFd(int fd) +{ + struct stat st; + + if (fstat(fd, &st) < 0) + return 0; + + return (st.st_mtime > st.st_ctime) ? st.st_mtime : st.st_ctime; +} + int __imlib_FileCanRead(const char *s) { diff --git a/src/lib/file.h b/src/lib/file.h index 414ef7a..7265d14 100644 --- a/src/lib/file.h +++ b/src/lib/file.h @@ -35,6 +35,7 @@ int __imlib_FileExists(const char *s); int __imlib_FileIsFile(const char *s); int __imlib_FileIsDir(const char *s); time_t __imlib_FileModDate(const char *s); +time_t __imlib_FileModDateFd(int fd); int __imlib_FileCanRead(const char *s); char **__imlib_FileDir(const char *dir, int *num); diff --git a/src/lib/image.c b/src/lib/image.c index 2f343f9..7f3069f 100644 --- a/src/lib/image.c +++ b/src/lib/image.c @@ -527,13 +527,14 @@ __imlib_ErrorFromErrno(int err, int save) } static int -__imlib_FileCheck(const char *file, struct stat *st, ImlibLoadError * er) +__imlib_FileCheck(const char *file, FILE * fp, struct stat *st, + ImlibLoadError * er) { int err; err = 0; - if (__imlib_FileStat(file, st)) + if (fp ? fstat(fileno(fp), st) : __imlib_FileStat(file, st)) err = IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST; else if (__imlib_StatIsDir(st)) err = IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY; @@ -660,7 +661,7 @@ __imlib_LoadEmbedded(ImlibLoader * l, ImlibImage * im, const char *file, } ImlibImage * -__imlib_LoadImage(const char *file, ImlibProgressFunction progress, +__imlib_LoadImage(const char *file, FILE * fp, ImlibProgressFunction progress, char progress_granularity, char immediate_load, char dont_cache, ImlibLoadError * er) { @@ -685,7 +686,9 @@ __imlib_LoadImage(const char *file, ImlibProgressFunction progress, { time_t current_modified_time; - current_modified_time = __imlib_FileModDate(im->real_file); + current_modified_time = fp ? + __imlib_FileModDateFd(fileno(fp)) : + __imlib_FileModDate(im->real_file); /* if the file on disk is newer than the cached one */ if (current_modified_time != im->moddate) { @@ -707,7 +710,7 @@ __imlib_LoadImage(const char *file, ImlibProgressFunction progress, } } - if (__imlib_FileCheck(file, &st, er)) + if (__imlib_FileCheck(file, fp, &st, er)) return NULL; /* either image in cache is invalid or we dont even have it in cache */ @@ -726,7 +729,11 @@ __imlib_LoadImage(const char *file, ImlibProgressFunction progress, im->key = __imlib_FileKey(file); } - im->fp = fopen(im->real_file, "rb"); + if (fp) + im->fp = fp; + else + im->fp = fopen(im->real_file, "rb"); + if (!im->fp) { if (er) @@ -795,7 +802,8 @@ __imlib_LoadImage(const char *file, ImlibProgressFunction progress, im->lc = NULL; - fclose(im->fp); + if (!fp) + fclose(im->fp); im->fp = NULL; /* all loaders have been tried and they all failed. free the skeleton */ diff --git a/src/lib/image.h b/src/lib/image.h index 11e2af1..64ebdb3 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -108,7 +108,7 @@ void __imlib_LoaderSetFormats(ImlibLoader * l, unsigned int num); ImlibImage *__imlib_CreateImage(int w, int h, DATA32 * data); -ImlibImage *__imlib_LoadImage(const char *file, +ImlibImage *__imlib_LoadImage(const char *file, FILE * fp, ImlibProgressFunction progress, char progress_granularity, char immediate_load, char dont_cache,