implement __mg_check_webp, __mg_init_webp and __mg_cleanup_webp

This commit is contained in:
Vincent Wei
2021-10-19 18:46:53 +08:00
parent 5e43b76753
commit b59ed4b7d1
+115 -2
View File
@@ -59,26 +59,139 @@
#ifdef _MGIMAGE_WEBP
#include "gdi.h"
#include "constants.h"
#include <webp/decode.h>
#define RIFF_HEADER_SIZE 12
#define HEADER_CHUNK_SIZE 64
#define READ_BUFF_SIZE 1024
struct webp_decode_info {
WebPDecoderConfig config;
size_t sz_data;
char buf[READ_BUFF_SIZE];
};
void* __mg_init_webp(MG_RWops *fp, MYBITMAP *mybmp, RGB *pal)
{
int n;
size_t pitch;
struct webp_decode_info *info = NULL;
if ((info = malloc(sizeof(struct webp_decode_info))) == NULL) {
_ERR_PRINTF ("__mg_init_webp: failed to allocate memory\n");
return NULL;
}
if (!WebPInitDecoderConfig(&info->config)) {
_ERR_PRINTF ("__mg_init_webp: WebPInitDecoderConfig failed\n");
goto error;
}
info->sz_data = 0;
do {
VP8StatusCode sc;
if (info->sz_data + HEADER_CHUNK_SIZE > READ_BUFF_SIZE) {
_ERR_PRINTF ("__mg_init_webp: two small buffer\n");
goto error;
}
n = MGUI_RWread(fp, info->buf + info->sz_data, 1, HEADER_CHUNK_SIZE);
if (n > 0) {
info->sz_data += n;
}
else
goto error;
sc = WebPGetFeatures(info->buf, info->sz_data, &info->config.input);
if (sc == VP8_STATUS_OK) {
break;
}
else if (sc == VP8_STATUS_NOT_ENOUGH_DATA) {
continue;
}
else {
_ERR_PRINTF ("__mg_init_webp: WebPGetFeatures failed: %d\n", sc);
goto error;
}
} while (1);
if (info->config.input.has_animation) {
_ERR_PRINTF ("__mg_init_webp: animation not supported\n");
goto error;
}
mybmp->w = info->config.input.width;
mybmp->h = info->config.input.height;
mybmp->frames = 1;
if (info->config.input.has_alpha) {
info->config.output.colorspace = MODE_RGBA;
mybmp->depth = 32;
mybmp->flags |= MYBMP_FLOW_DOWN | MYBMP_ALPHA | MYBMP_TYPE_RGBA;
mybmp->flags |= MYBMP_RGBSIZE_4;
pitch = (size_t)info->config.input.width * 4;
}
else {
info->config.output.colorspace = MODE_RGB;
mybmp->depth = 24;
mybmp->flags |= MYBMP_FLOW_DOWN | MYBMP_ALPHA | MYBMP_TYPE_RGBA;
mybmp->flags |= MYBMP_RGBSIZE_4;
pitch = (size_t)info->config.input.width * 3;
}
pitch = ROUND_TO_MULTIPLE(pitch, 8);
// Have config.output point to an external buffer:
info->config.output.u.RGBA.rgba = (uint8_t*)malloc(pitch);
info->config.output.u.RGBA.stride = pitch;
info->config.output.u.RGBA.size = pitch;
info->config.output.is_external_memory = 1;
if (info->config.output.u.RGBA.rgba == NULL) {
_ERR_PRINTF ("__mg_init_webp: failed to allocate memory\n");
goto error;
}
return info;
error:
if (info)
free(info);
return NULL;
}
void __mg_cleanup_webp(void *init_info)
{
struct webp_decode_info *info = init_info;
if (info) {
free(info->config.output.u.RGBA.rgba);
free(info);
}
}
int __mg_load_webp (MG_RWops *fp, void *init_info, MYBITMAP *my_bmp,
int __mg_load_webp(MG_RWops *fp, void *init_info, MYBITMAP *my_bmp,
CB_ONE_SCANLINE cb, void *context)
{
return ERR_BMP_OK;
}
BOOL __mg_check_webp (MG_RWops* fp)
BOOL __mg_check_webp(MG_RWops* fp)
{
unsigned char header[RIFF_HEADER_SIZE];
MGUI_RWread(fp, header, RIFF_HEADER_SIZE, 1);
if (!WebPGetInfo(header, RIFF_HEADER_SIZE, NULL, NULL)) {
}
return WebPGetInfo(header, RIFF_HEADER_SIZE, NULL, NULL);
}
#endif /* _MGIMAGE_WEBP */