library, so we can have several or none of them at some time.
* sdl.c imlib.c: allow to save images that weren't created using the
current codec.
git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2629 92316355-f0b4-4df1-b90c-862c8a59935f
remotes/tiles
| @@ -38,32 +38,23 @@ pipi_image_t *pipi_load(const char *name) | |||||
| #endif | #endif | ||||
| } | } | ||||
| pipi_image_t *pipi_new(int width, int height) | |||||
| { | |||||
| #if USE_SDL | |||||
| return pipi_new_sdl(width, height); | |||||
| #elif USE_IMLIB2 | |||||
| return pipi_new_imlib2(width, height); | |||||
| #elif USE_OPENCV | |||||
| return pipi_new_opencv(width, height); | |||||
| #endif | |||||
| } | |||||
| void pipi_free(pipi_image_t *img) | void pipi_free(pipi_image_t *img) | ||||
| { | { | ||||
| unsigned int i; | |||||
| int i; | |||||
| for(i = 0; i < PIPI_PIXELS_MAX; i++) | for(i = 0; i < PIPI_PIXELS_MAX; i++) | ||||
| if(i != img->codec_format && img->p[i].pixels) | if(i != img->codec_format && img->p[i].pixels) | ||||
| free(img->p[i].pixels); | free(img->p[i].pixels); | ||||
| #if USE_SDL | #if USE_SDL | ||||
| return pipi_free_sdl(img); | |||||
| pipi_free_sdl(img); | |||||
| #elif USE_IMLIB2 | #elif USE_IMLIB2 | ||||
| return pipi_free_imlib2(img); | |||||
| pipi_free_imlib2(img); | |||||
| #elif USE_OPENCV | #elif USE_OPENCV | ||||
| return pipi_free_opencv(img); | |||||
| pipi_free_opencv(img); | |||||
| #endif | #endif | ||||
| free(img); | |||||
| } | } | ||||
| void pipi_save(pipi_image_t *img, const char *name) | void pipi_save(pipi_image_t *img, const char *name) | ||||
| @@ -36,44 +36,13 @@ pipi_image_t *pipi_load_imlib2(const char *name) | |||||
| if(!priv) | if(!priv) | ||||
| return NULL; | return NULL; | ||||
| img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); | |||||
| memset(img, 0, sizeof(pipi_image_t)); | |||||
| imlib_context_set_image(priv); | imlib_context_set_image(priv); | ||||
| img->w = imlib_image_get_width(); | |||||
| img->h = imlib_image_get_height(); | |||||
| img = pipi_new(imlib_image_get_width(), imlib_image_get_height()); | |||||
| img->p[PIPI_PIXELS_RGBA32].pixels = imlib_image_get_data(); | img->p[PIPI_PIXELS_RGBA32].pixels = imlib_image_get_data(); | ||||
| img->p[PIPI_PIXELS_RGBA32].w = imlib_image_get_width(); | |||||
| img->p[PIPI_PIXELS_RGBA32].h = imlib_image_get_height(); | |||||
| img->p[PIPI_PIXELS_RGBA32].pitch = 4 * imlib_image_get_width(); | |||||
| img->last_modified = PIPI_PIXELS_RGBA32; | |||||
| img->codec_priv = (void *)priv; | |||||
| img->codec_format = PIPI_PIXELS_RGBA32; | |||||
| return img; | |||||
| } | |||||
| pipi_image_t *pipi_new_imlib2(int width, int height) | |||||
| { | |||||
| pipi_image_t *img; | |||||
| Imlib_Image priv = imlib_create_image(width, height); | |||||
| if(!priv) | |||||
| return NULL; | |||||
| img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); | |||||
| memset(img, 0, sizeof(pipi_image_t)); | |||||
| imlib_context_set_image(priv); | |||||
| img->w = imlib_image_get_width(); | |||||
| img->h = imlib_image_get_height(); | |||||
| img->p[PIPI_PIXELS_RGBA32].pixels = imlib_image_get_data(); | |||||
| img->p[PIPI_PIXELS_RGBA32].w = imlib_image_get_width(); | |||||
| img->p[PIPI_PIXELS_RGBA32].h = imlib_image_get_height(); | |||||
| img->p[PIPI_PIXELS_RGBA32].pitch = 4 * imlib_image_get_width(); | |||||
| img->p[PIPI_PIXELS_RGBA32].w = img->w; | |||||
| img->p[PIPI_PIXELS_RGBA32].h = img->h; | |||||
| img->p[PIPI_PIXELS_RGBA32].pitch = 4 * img->w; | |||||
| img->last_modified = PIPI_PIXELS_RGBA32; | img->last_modified = PIPI_PIXELS_RGBA32; | ||||
| img->codec_priv = (void *)priv; | img->codec_priv = (void *)priv; | ||||
| @@ -86,12 +55,35 @@ void pipi_free_imlib2(pipi_image_t *img) | |||||
| { | { | ||||
| imlib_context_set_image(img->codec_priv); | imlib_context_set_image(img->codec_priv); | ||||
| imlib_free_image(); | imlib_free_image(); | ||||
| free(img); | |||||
| } | } | ||||
| void pipi_save_imlib2(pipi_image_t *img, const char *name) | void pipi_save_imlib2(pipi_image_t *img, const char *name) | ||||
| { | { | ||||
| if(!img->codec_priv) | |||||
| { | |||||
| Imlib_Image priv = imlib_create_image(img->w, img->h); | |||||
| void *data; | |||||
| imlib_context_set_image(priv); | |||||
| data = imlib_image_get_data(); | |||||
| /* FIXME: check pitch differences here */ | |||||
| if(img->last_modified == PIPI_PIXELS_RGBA32) | |||||
| { | |||||
| memcpy(data, img->p[PIPI_PIXELS_RGBA32].pixels, | |||||
| 4 * img->w * img->h); | |||||
| free(img->p[PIPI_PIXELS_RGBA32].pixels); | |||||
| } | |||||
| img->p[PIPI_PIXELS_RGBA32].pixels = data; | |||||
| img->p[PIPI_PIXELS_RGBA32].w = imlib_image_get_width(); | |||||
| img->p[PIPI_PIXELS_RGBA32].h = imlib_image_get_height(); | |||||
| img->p[PIPI_PIXELS_RGBA32].pitch = 4 * imlib_image_get_width(); | |||||
| img->codec_priv = (void *)priv; | |||||
| img->codec_format = PIPI_PIXELS_RGBA32; | |||||
| } | |||||
| pipi_getpixels(img, img->codec_format); | pipi_getpixels(img, img->codec_format); | ||||
| imlib_context_set_image(img->codec_priv); | imlib_context_set_image(img->codec_priv); | ||||
| imlib_save_image(name); | imlib_save_image(name); | ||||
| @@ -29,6 +29,8 @@ | |||||
| #include "pipi.h" | #include "pipi.h" | ||||
| #include "pipi_internals.h" | #include "pipi_internals.h" | ||||
| /* FIXME: this whole file is broken until we support BGR24 images */ | |||||
| pipi_image_t *pipi_load_opencv(const char *name) | pipi_image_t *pipi_load_opencv(const char *name) | ||||
| { | { | ||||
| pipi_image_t *img; | pipi_image_t *img; | ||||
| @@ -58,7 +60,7 @@ pipi_image_t *pipi_load_opencv(const char *name) | |||||
| pipi_image_t *pipi_new_opencv(int width, int height) | pipi_image_t *pipi_new_opencv(int width, int height) | ||||
| { | { | ||||
| pipi_image_t *img; | pipi_image_t *img; | ||||
| IplImage *priv = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); | |||||
| IplImage *priv = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 4); | |||||
| if(!priv) | if(!priv) | ||||
| return NULL; | return NULL; | ||||
| @@ -28,6 +28,8 @@ | |||||
| #include "pipi.h" | #include "pipi.h" | ||||
| #include "pipi_internals.h" | #include "pipi_internals.h" | ||||
| static SDL_Surface *create_32bpp_surface(int w, int h); | |||||
| pipi_image_t *pipi_load_sdl(const char *name) | pipi_image_t *pipi_load_sdl(const char *name) | ||||
| { | { | ||||
| pipi_image_t *img; | pipi_image_t *img; | ||||
| @@ -38,17 +40,13 @@ pipi_image_t *pipi_load_sdl(const char *name) | |||||
| if(priv->format->BytesPerPixel != 4) | if(priv->format->BytesPerPixel != 4) | ||||
| { | { | ||||
| img = pipi_new(priv->w, priv->h); | |||||
| SDL_BlitSurface(priv, NULL, img->codec_priv, NULL); | |||||
| SDL_Surface *tmp = create_32bpp_surface(priv->w, priv->h); | |||||
| SDL_BlitSurface(priv, NULL, tmp, NULL); | |||||
| SDL_FreeSurface(priv); | SDL_FreeSurface(priv); | ||||
| return img; | |||||
| priv = tmp; | |||||
| } | } | ||||
| img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); | |||||
| memset(img, 0, sizeof(pipi_image_t)); | |||||
| img->w = priv->w; | |||||
| img->h = priv->h; | |||||
| img = pipi_new(priv->w, priv->h); | |||||
| img->p[PIPI_PIXELS_RGBA32].pixels = priv->pixels; | img->p[PIPI_PIXELS_RGBA32].pixels = priv->pixels; | ||||
| img->p[PIPI_PIXELS_RGBA32].w = priv->w; | img->p[PIPI_PIXELS_RGBA32].w = priv->w; | ||||
| @@ -62,10 +60,44 @@ pipi_image_t *pipi_load_sdl(const char *name) | |||||
| return img; | return img; | ||||
| } | } | ||||
| pipi_image_t *pipi_new_sdl(int width, int height) | |||||
| void pipi_free_sdl(pipi_image_t *img) | |||||
| { | |||||
| SDL_FreeSurface(img->codec_priv); | |||||
| } | |||||
| void pipi_save_sdl(pipi_image_t *img, const char *name) | |||||
| { | |||||
| if(!img->codec_priv) | |||||
| { | |||||
| SDL_Surface *priv = create_32bpp_surface(img->w, img->h); | |||||
| /* FIXME: check pitch differences here */ | |||||
| if(img->last_modified == PIPI_PIXELS_RGBA32) | |||||
| { | |||||
| memcpy(priv->pixels, img->p[PIPI_PIXELS_RGBA32].pixels, | |||||
| priv->pitch * priv->h); | |||||
| free(img->p[PIPI_PIXELS_RGBA32].pixels); | |||||
| } | |||||
| img->p[PIPI_PIXELS_RGBA32].pixels = priv->pixels; | |||||
| img->p[PIPI_PIXELS_RGBA32].w = priv->w; | |||||
| img->p[PIPI_PIXELS_RGBA32].h = priv->h; | |||||
| img->p[PIPI_PIXELS_RGBA32].pitch = priv->pitch; | |||||
| img->codec_priv = (void *)priv; | |||||
| img->codec_format = PIPI_PIXELS_RGBA32; | |||||
| } | |||||
| pipi_getpixels(img, img->codec_format); | |||||
| SDL_SaveBMP(img->codec_priv, name); | |||||
| } | |||||
| /* | |||||
| * The following functions are local. | |||||
| */ | |||||
| static SDL_Surface *create_32bpp_surface(int w, int h) | |||||
| { | { | ||||
| pipi_image_t *img; | |||||
| SDL_Surface *priv; | |||||
| Uint32 rmask, gmask, bmask, amask; | Uint32 rmask, gmask, bmask, amask; | ||||
| #if SDL_BYTEORDER == SDL_BIG_ENDIAN | #if SDL_BYTEORDER == SDL_BIG_ENDIAN | ||||
| rmask = 0xff000000; | rmask = 0xff000000; | ||||
| @@ -78,40 +110,8 @@ pipi_image_t *pipi_new_sdl(int width, int height) | |||||
| bmask = 0x00ff0000; | bmask = 0x00ff0000; | ||||
| amask = 0x00000000; | amask = 0x00000000; | ||||
| #endif | #endif | ||||
| priv = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, | |||||
| rmask, gmask, bmask, amask); | |||||
| if(!priv) | |||||
| return NULL; | |||||
| img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); | |||||
| memset(img, 0, sizeof(pipi_image_t)); | |||||
| img->w = priv->w; | |||||
| img->h = priv->h; | |||||
| img->p[PIPI_PIXELS_RGBA32].pixels = priv->pixels; | |||||
| img->p[PIPI_PIXELS_RGBA32].w = priv->w; | |||||
| img->p[PIPI_PIXELS_RGBA32].h = priv->h; | |||||
| img->p[PIPI_PIXELS_RGBA32].pitch = priv->pitch; | |||||
| img->last_modified = PIPI_PIXELS_RGBA32; | |||||
| img->codec_priv = (void *)priv; | |||||
| img->codec_format = PIPI_PIXELS_RGBA32; | |||||
| return img; | |||||
| } | |||||
| void pipi_free_sdl(pipi_image_t *img) | |||||
| { | |||||
| SDL_FreeSurface(img->codec_priv); | |||||
| free(img); | |||||
| } | |||||
| void pipi_save_sdl(pipi_image_t *img, const char *name) | |||||
| { | |||||
| pipi_getpixels(img, img->codec_format); | |||||
| SDL_SaveBMP(img->codec_priv, name); | |||||
| return SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, | |||||
| rmask, gmask, bmask, amask); | |||||
| } | } | ||||
| @@ -38,3 +38,17 @@ void _pipi_init(void) | |||||
| } | } | ||||
| */ | */ | ||||
| pipi_image_t *pipi_new(int w, int h) | |||||
| { | |||||
| pipi_image_t *img; | |||||
| img = malloc(sizeof(pipi_image_t)); | |||||
| memset(img, 0, sizeof(pipi_image_t)); | |||||
| img->w = w; | |||||
| img->h = h; | |||||
| img->last_modified = PIPI_PIXELS_UNINITIALISED; | |||||
| return img; | |||||
| } | |||||
| @@ -29,6 +29,8 @@ extern "C" | |||||
| * just been loaded, but RGBA_F is a lot better for complex operations. */ | * just been loaded, but RGBA_F is a lot better for complex operations. */ | ||||
| typedef enum | typedef enum | ||||
| { | { | ||||
| PIPI_PIXELS_UNINITIALISED = -1, | |||||
| PIPI_PIXELS_RGBA32 = 0, | PIPI_PIXELS_RGBA32 = 0, | ||||
| PIPI_PIXELS_RGBA_F = 1, | PIPI_PIXELS_RGBA_F = 1, | ||||