efl/src/modules/evas/loaders/webp/evas_image_load_webp.c

157 lines
3.1 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <webp/decode.h>
#ifdef HAVE_EVIL
# include <Evil.h>
#endif
#include "evas_common.h"
#include "evas_private.h"
static Eina_Bool
evas_image_load_file_check(Eina_File *f, void *map,
unsigned int *w, unsigned int *h, Eina_Bool *alpha,
int *error)
{
WebPDecoderConfig config;
if (eina_file_size_get(f) < 30) return EINA_FALSE;
if (!WebPInitDecoderConfig(&config))
{
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
return EINA_FALSE;
}
if (WebPGetFeatures(map, 30, &config.input) != VP8_STATUS_OK)
{
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
return EINA_FALSE;
}
*w = config.input.width;
*h = config.input.height;
*alpha = config.input.has_alpha;
return EINA_TRUE;
}
static void *
evas_image_load_file_open_webp(Eina_File *f, const char *key EINA_UNUSED,
Evas_Image_Load_Opts *opts EINA_UNUSED,
Evas_Image_Animated *animated EINA_UNUSED,
int *error EINA_UNUSED)
{
return f;
}
static void
evas_image_load_file_close_webp(void *loader_data EINA_UNUSED)
{
}
static Eina_Bool
evas_image_load_file_head_webp(void *loader_data,
Evas_Image_Property *prop,
int *error)
{
Eina_File *f = loader_data;
Eina_Bool r;
void *data;
*error = EVAS_LOAD_ERROR_NONE;
data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
r = evas_image_load_file_check(f, data,
&prop->w, &prop->h, &prop->alpha,
error);
if (data) eina_file_map_free(f, data);
return r;
}
static Eina_Bool
evas_image_load_file_data_webp(void *loader_data,
Evas_Image_Property *prop,
void *pixels,
int *error)
{
Eina_File *f = loader_data;
void *data = NULL;
void *decoded = NULL;
void *surface = NULL;
int width, height;
data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
surface = pixels;
decoded = WebPDecodeBGRA(data, eina_file_size_get(f), &width, &height);
if (!decoded)
{
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
goto free_data;
}
*error = EVAS_LOAD_ERROR_NONE;
if ((int) prop->w != width ||
(int) prop->h != height)
goto free_data;
// XXX: this copy of the surface is inefficient
memcpy(surface, decoded, width * height * 4);
prop->premul = EINA_TRUE;
free_data:
if (data) eina_file_map_free(f, data);
free(decoded);
return EINA_TRUE;
}
static Evas_Image_Load_Func evas_image_load_webp_func =
{
EINA_TRUE,
evas_image_load_file_open_webp,
evas_image_load_file_close_webp,
evas_image_load_file_head_webp,
evas_image_load_file_data_webp,
NULL,
EINA_FALSE
};
static int
module_open(Evas_Module *em)
{
if (!em) return 0;
em->functions = (void *)(&evas_image_load_webp_func);
return 1;
}
static void
module_close(Evas_Module *em EINA_UNUSED)
{
}
static Evas_Module_Api evas_modapi =
{
EVAS_MODULE_API_VERSION,
"webp",
"none",
{
module_open,
module_close
}
};
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, webp);
#ifndef EVAS_STATIC_BUILD_WEBP
EVAS_EINA_MODULE_DEFINE(image_loader, webp);
#endif