mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-05 08:48:00 +02:00
Add support for webp image format
This commit is contained in:
parent
902865c757
commit
3d5437c48d
2 changed files with 109 additions and 10 deletions
|
|
@ -21,6 +21,8 @@
|
|||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -32,6 +34,10 @@
|
|||
#include <jpeglib.h>
|
||||
#include <png.h>
|
||||
|
||||
#ifdef HAVE_WEBP
|
||||
#include <webp/decode.h>
|
||||
#endif
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
void
|
||||
|
|
@ -514,14 +520,98 @@ load_png(FILE *fp)
|
|||
width, height, stride);
|
||||
}
|
||||
|
||||
#ifdef HAVE_WEBP
|
||||
|
||||
static cairo_surface_t *
|
||||
load_webp(FILE *fp)
|
||||
{
|
||||
WebPDecoderConfig config;
|
||||
uint8_t buffer[16 * 1024];
|
||||
int len;
|
||||
VP8StatusCode status;
|
||||
WebPIDecoder *idec;
|
||||
|
||||
if (!WebPInitDecoderConfig(&config)) {
|
||||
fprintf(stderr, "Library version mismatch!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* webp decoding api doesn't seem to specify a min size that's
|
||||
usable for GetFeatures, but 256 works... */
|
||||
len = fread(buffer, 1, 256, fp);
|
||||
status = WebPGetFeatures(buffer, len, &config.input);
|
||||
if (status != VP8_STATUS_OK) {
|
||||
fprintf(stderr, "failed to parse webp header\n");
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
config.output.colorspace = MODE_BGRA;
|
||||
config.output.u.RGBA.stride =
|
||||
cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
|
||||
config.input.width);
|
||||
config.output.u.RGBA.size =
|
||||
config.output.u.RGBA.stride * config.input.height;
|
||||
config.output.u.RGBA.rgba =
|
||||
malloc(config.output.u.RGBA.stride * config.input.height);
|
||||
config.output.is_external_memory = 1;
|
||||
if (!config.output.u.RGBA.rgba) {
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rewind(fp);
|
||||
idec = WebPINewDecoder(&config.output);
|
||||
if (!idec) {
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (!feof(fp)) {
|
||||
len = fread(buffer, 1, sizeof buffer, fp);
|
||||
status = WebPIAppend(idec, buffer, len);
|
||||
if (status != VP8_STATUS_OK) {
|
||||
fprintf(stderr, "webp decode status %d\n", status);
|
||||
WebPIDelete(idec);
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
WebPIDelete(idec);
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
|
||||
return cairo_image_surface_create_for_data (config.output.u.RGBA.rgba,
|
||||
CAIRO_FORMAT_RGB24,
|
||||
config.input.width,
|
||||
config.input.height,
|
||||
config.output.u.RGBA.stride);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct image_loader {
|
||||
char header[4];
|
||||
int header_size;
|
||||
cairo_surface_t *(*load)(FILE *fp);
|
||||
};
|
||||
|
||||
static const struct image_loader loaders[] = {
|
||||
{ { 0x89, 'P', 'N', 'G' }, 4, load_png },
|
||||
{ { 0xff, 0xd8 }, 2, load_jpeg },
|
||||
#ifdef HAVE_WEBP
|
||||
{ { 'R', 'I', 'F', 'F' }, 4, load_webp }
|
||||
#endif
|
||||
};
|
||||
|
||||
cairo_surface_t *
|
||||
load_image(const char *filename)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
static const unsigned char png_header[] = { 0x89, 'P', 'N', 'G' };
|
||||
static const unsigned char jpeg_header[] = { 0xff, 0xd8 };
|
||||
unsigned char header[4];
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == NULL)
|
||||
|
|
@ -529,18 +619,22 @@ load_image(const char *filename)
|
|||
|
||||
fread(header, sizeof header, 1, fp);
|
||||
rewind(fp);
|
||||
if (memcmp(header, png_header, sizeof png_header) == 0)
|
||||
surface = load_png(fp);
|
||||
else if (memcmp(header, jpeg_header, sizeof jpeg_header) == 0)
|
||||
surface = load_jpeg(fp);
|
||||
else {
|
||||
for (i = 0; i < ARRAY_LENGTH(loaders); i++) {
|
||||
if (memcmp(header, loaders[i].header,
|
||||
loaders[i].header_size) == 0) {
|
||||
surface = loaders[i].load(fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (i == ARRAY_LENGTH(loaders)) {
|
||||
fprintf(stderr, "unrecognized file header for %s: "
|
||||
"0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
filename, header[0], header[1], header[2], header[3]);
|
||||
surface = NULL;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,11 +123,16 @@ if test x$enable_clients == xyes; then
|
|||
[have_poppler=yes], [have_poppler=no])
|
||||
PKG_CHECK_MODULES(CAIRO_EGL, [cairo-egl >= 1.11.3 $cairo_modules],
|
||||
[have_cairo_egl=yes], [have_cairo_egl=no])
|
||||
|
||||
AS_IF([test "x$have_cairo_egl" = "xyes"],
|
||||
[AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])],
|
||||
[AC_MSG_WARN([Cairo-EGL not found - clients will use cairo image])])
|
||||
|
||||
PKG_CHECK_MODULES(WEBP, [libwebp], [have_webp=yes], [have_webp=no])
|
||||
AS_IF([test "x$have_webp" = "xyes"],
|
||||
[AC_DEFINE([HAVE_WEBP], [1], [Have webp])])
|
||||
CLIENT_LIBS="$CLIENT_LIBS $WEBP_LIBS"
|
||||
CLIENT_CFLAGS="$CLIENT_CFLAGS $WEBP_CFLAGS"
|
||||
|
||||
AC_CHECK_LIB([jpeg], [jpeg_CreateDecompress], have_jpeglib=yes)
|
||||
if test x$have_jpeglib == xyes; then
|
||||
CLIENT_LIBS="$CLIENT_LIBS -ljpeg"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue