aboutsummaryrefslogtreecommitdiff
path: root/src/loader.c
diff options
context:
space:
mode:
authorHarry Jeffery <harry@exec64.co.uk>2016-01-15 16:16:10 +0000
committerHarry Jeffery <harry@exec64.co.uk>2016-01-15 16:16:10 +0000
commit58fe28b650dfcdd3efe78fb0559cab5b7e811bb5 (patch)
tree73d290727b720e39b36c8165e1ea9202374726f3 /src/loader.c
parentefa33ab844a09f05907a5de2d66ed7331c4f8ec9 (diff)
parent1ae8a7fe6030771352e347e7564639ea181802ba (diff)
downloadimv-58fe28b650dfcdd3efe78fb0559cab5b7e811bb5.tar.gz
Merge pull request #76 from czarkoff/loader
Loading image data from standard input
Diffstat (limited to 'src/loader.c')
-rw-r--r--src/loader.c116
1 files changed, 79 insertions, 37 deletions
diff --git a/src/loader.c b/src/loader.c
index 883e857..1250289 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -17,10 +17,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "loader.h"
#include "texture.h"
+#include <limits.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
+static void block_usr1_signal(void);
+static int is_thread_cancelled(void);
+static void *bg_new_img(void *data);
+static void *bg_next_frame(void *data);
+static void error_occurred(struct imv_loader *ldr);
+
static void block_usr1_signal(void)
{
sigset_t sigmask;
@@ -61,10 +68,8 @@ void imv_destroy_loader(struct imv_loader *ldr)
}
}
-static void *imv_loader_bg_new_img(void *data);
-static void *imv_loader_bg_next_frame(void *data);
-
-void imv_loader_load_path(struct imv_loader *ldr, const char *path)
+void imv_loader_load(struct imv_loader *ldr, const char *path,
+ const void *buffer, const size_t buffer_size)
{
/* cancel existing thread if already running */
if(ldr->bg_thread) {
@@ -77,7 +82,13 @@ void imv_loader_load_path(struct imv_loader *ldr, const char *path)
free(ldr->path);
}
ldr->path = strdup(path);
- pthread_create(&ldr->bg_thread, NULL, &imv_loader_bg_new_img, ldr);
+ if (strncmp(path, "-", 2) == 0) {
+ ldr->buffer = (BYTE *)buffer;
+ ldr->buffer_size = buffer_size;
+ } else if (ldr->fi_buffer != NULL) {
+ FreeImage_CloseMemory(ldr->fi_buffer);
+ }
+ pthread_create(&ldr->bg_thread, NULL, &bg_new_img, ldr);
pthread_mutex_unlock(&ldr->lock);
}
@@ -120,7 +131,7 @@ void imv_loader_load_next_frame(struct imv_loader *ldr)
}
/* kick off a new thread */
- pthread_create(&ldr->bg_thread, NULL, &imv_loader_bg_next_frame, ldr);
+ pthread_create(&ldr->bg_thread, NULL, &bg_next_frame, ldr);
}
void imv_loader_time_passed(struct imv_loader *ldr, double dt)
@@ -140,33 +151,38 @@ void imv_loader_time_passed(struct imv_loader *ldr, double dt)
}
}
-static void imv_loader_error_occurred(struct imv_loader *ldr)
-{
- pthread_mutex_lock(&ldr->lock);
- if(ldr->out_err) {
- free(ldr->out_err);
- }
- ldr->out_err = strdup(ldr->path);
- pthread_mutex_unlock(&ldr->lock);
-}
-
-static void *imv_loader_bg_new_img(void *data)
+static void *bg_new_img(void *data)
{
/* so we can poll for it */
block_usr1_signal();
struct imv_loader *ldr = data;
+ char path[PATH_MAX] = "-";
pthread_mutex_lock(&ldr->lock);
- char *path = strdup(ldr->path);
+ int from_stdin = !strncmp(path, ldr->path, 2);
+ if(!from_stdin) {
+ (void)snprintf(path, PATH_MAX, "%s", ldr->path);
+ }
pthread_mutex_unlock(&ldr->lock);
- FREE_IMAGE_FORMAT fmt = FreeImage_GetFileType(path, 0);
-
+ FREE_IMAGE_FORMAT fmt;
+ if (from_stdin) {
+ pthread_mutex_lock(&ldr->lock);
+ ldr->fi_buffer = FreeImage_OpenMemory(ldr->buffer, ldr->buffer_size);
+ fmt = FreeImage_GetFileTypeFromMemory(ldr->fi_buffer, 0);
+ pthread_mutex_unlock(&ldr->lock);
+ } else {
+ fmt = FreeImage_GetFileType(path, 0);
+ }
if(fmt == FIF_UNKNOWN) {
- imv_loader_error_occurred(ldr);
- free(path);
- return 0;
+ if (from_stdin) {
+ pthread_mutex_lock(&ldr->lock);
+ FreeImage_CloseMemory(ldr->fi_buffer);
+ pthread_mutex_unlock(&ldr->lock);
+ }
+ error_occurred(ldr);
+ return NULL;
}
int num_frames = 1;
@@ -176,15 +192,21 @@ static void *imv_loader_bg_new_img(void *data)
int raw_frame_time = 100; /* default to 100 */
if(fmt == FIF_GIF) {
- mbmp = FreeImage_OpenMultiBitmap(FIF_GIF, path,
+ if(from_stdin) {
+ pthread_mutex_lock(&ldr->lock);
+ mbmp = FreeImage_LoadMultiBitmapFromMemory(FIF_GIF, ldr->fi_buffer,
+ GIF_LOAD256);
+ pthread_mutex_unlock(&ldr->lock);
+ } else {
+ mbmp = FreeImage_OpenMultiBitmap(FIF_GIF, path,
/* don't create file */ 0,
/* read only */ 1,
/* keep in memory */ 1,
/* flags */ GIF_LOAD256);
- free(path);
+ }
if(!mbmp) {
- imv_loader_error_occurred(ldr);
- return 0;
+ error_occurred(ldr);
+ return NULL;
}
num_frames = FreeImage_GetPageCount(mbmp);
@@ -205,17 +227,27 @@ static void *imv_loader_bg_new_img(void *data)
} else {
/* Future TODO: If we load image line-by-line we could stop loading large
* ones before wasting much more time/memory on them. */
- FIBITMAP *image = FreeImage_Load(fmt, path, 0);
- free(path);
+ FIBITMAP *image;
+ if(from_stdin) {
+ pthread_mutex_lock(&ldr->lock);
+ image = FreeImage_LoadFromMemory(fmt, ldr->fi_buffer, 0);
+ pthread_mutex_unlock(&ldr->lock);
+ } else {
+ image = FreeImage_Load(fmt, path, 0);
+ }
if(!image) {
- imv_loader_error_occurred(ldr);
- return 0;
+ error_occurred(ldr);
+ pthread_mutex_lock(&ldr->lock);
+ FreeImage_CloseMemory(ldr->fi_buffer);
+ ldr->fi_buffer = NULL;
+ pthread_mutex_unlock(&ldr->lock);
+ return NULL;
}
/* Check for cancellation before we convert pixel format */
if(is_thread_cancelled()) {
FreeImage_Unload(image);
- return 0;
+ return NULL;
}
width = FreeImage_GetWidth(bmp);
@@ -236,7 +268,7 @@ static void *imv_loader_bg_new_img(void *data)
FreeImage_Unload(bmp);
}
pthread_mutex_unlock(&ldr->lock);
- return 0;
+ return NULL;
}
if(ldr->mbmp) {
@@ -262,10 +294,10 @@ static void *imv_loader_bg_new_img(void *data)
ldr->frame_time = (double)raw_frame_time * 0.0001;
pthread_mutex_unlock(&ldr->lock);
- return 0;
+ return NULL;
}
-static void *imv_loader_bg_next_frame(void *data)
+static void *bg_next_frame(void *data)
{
struct imv_loader *ldr = data;
@@ -273,7 +305,7 @@ static void *imv_loader_bg_next_frame(void *data)
int num_frames = ldr->num_frames;
if(num_frames < 2) {
pthread_mutex_unlock(&ldr->lock);
- return 0;
+ return NULL;
}
FITAG *tag = NULL;
@@ -371,5 +403,15 @@ static void *imv_loader_bg_next_frame(void *data)
ldr->out_is_new_image = 0;
pthread_mutex_unlock(&ldr->lock);
- return 0;
+ return NULL;
+}
+
+static void error_occurred(struct imv_loader *ldr)
+{
+ pthread_mutex_lock(&ldr->lock);
+ if(ldr->out_err) {
+ free(ldr->out_err);
+ }
+ ldr->out_err = strdup(ldr->path);
+ pthread_mutex_unlock(&ldr->lock);
}