#ifdef HAVE_WEBP
#include "webp/encode.h"
+static const char* const kErrorMessages[] = {
+ "OK",
+ "OUT_OF_MEMORY: Out of memory allocating objects",
+ "BITSTREAM_OUT_OF_MEMORY: Out of memory re-allocating byte buffer",
+ "NULL_PARAMETER: NULL parameter passed to function",
+ "INVALID_CONFIGURATION: configuration is invalid",
+ "BAD_DIMENSION: Bad picture dimension. Maximum width and height "
+ "allowed is 16383 pixels.",
+ "PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k.\n"
+ "To reduce the size of this partition, try using less segments "
+ "with the -segments option, and eventually reduce the number of "
+ "header bits using -partition_limit. More details are available "
+ "in the manual (`man cwebp`)",
+ "PARTITION_OVERFLOW: Partition is too big to fit 16M",
+ "BAD_WRITE: Picture writer returned an I/O error",
+ "FILE_TOO_BIG: File would be too big to fit in 4G",
+ "USER_ABORT: encoding abort requested by user"
+};
+
typedef enum {
FORMAT_WEBP,
} format_type;
if (!WebPEncode(&config, &picture)) {
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
-// fprintf(stderr, "Error code: %d (%s)\n",
-// pic.error_code, kErrorMessages[picture.error_code]);
+ fprintf(stderr, "Error code: %d (%s)\n",
+ picture.error_code, kErrorMessages[picture.error_code]);
goto Error;
}
#ifdef HAVE_WEBP
#ifdef HAVE_PANGOCAIRO
#include <cairo.h>
-#include <webp/encode.h>
+#include <webp/decode.h>
#ifdef WIN32 //*dependencies
#pragma comment( lib, "gvc.lib" )
#pragma comment( lib, "webp.lib" )
#endif
+static const char* const kStatusMessages[] = {
+ "OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
+ "UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
+};
+
typedef enum {
FORMAT_WEBP_CAIRO,
} format_type;
-static cairo_status_t
-reader (void *closure, unsigned char *data, unsigned int length)
+static void webp_freeimage(usershape_t *us)
{
- if (length == fread(data, 1, length, (FILE *)closure)
- || feof((FILE *)closure))
- return CAIRO_STATUS_SUCCESS;
- return CAIRO_STATUS_READ_ERROR;
+ cairo_surface_destroy((cairo_surface_t*)(us->data));
}
-static void webp_freeimage(usershape_t *us)
+static cairo_surface_t* webp_really_loadimage(const char *in_file, FILE* const in)
{
- cairo_surface_destroy((cairo_surface_t*)(us->data));
+ WebPDecoderConfig config;
+ WebPDecBuffer* const output_buffer = &config.output;
+ WebPBitstreamFeatures* const bitstream = &config.input;
+ VP8StatusCode status = VP8_STATUS_OK;
+ cairo_surface_t *surface = NULL; /* source surface */
+ int ok;
+ uint32_t data_size = 0;
+ void* data = NULL;
+
+ if (!WebPInitDecoderConfig(&config)) {
+ fprintf(stderr, "Error: WebP library version mismatch!\n");
+ return NULL;
+ }
+
+ fseek(in, 0, SEEK_END);
+ data_size = ftell(in);
+ fseek(in, 0, SEEK_SET);
+ data = malloc(data_size);
+ ok = (fread(data, data_size, 1, in) == 1);
+ if (!ok) {
+ fprintf(stderr, "Error: WebP could not read %d bytes of data from %s\n",
+ data_size, in_file);
+ free(data);
+ return NULL;
+ }
+
+ status = WebPGetFeatures((const uint8_t*)data, data_size, bitstream);
+ if (status != VP8_STATUS_OK) {
+ goto end;
+ }
+
+ output_buffer->colorspace = MODE_RGBA;
+ status = WebPDecode((const uint8_t*)data, data_size, &config);
+
+end:
+ free(data);
+ ok = (status == VP8_STATUS_OK);
+ if (!ok) {
+ fprintf(stderr, "Error: WebP decoding of %s failed.\n", in_file);
+ fprintf(stderr, "Status: %d (%s)\n", status, kStatusMessages[status]);
+ return NULL;
+ }
+
+ // FIXME - convert data to cairo surface ...
+
+#if 1
+ fprintf(stderr, "Info: WebP file %s can be decoded (dimensions: %d x %d)%s.\n",
+ in_file, output_buffer->width, output_buffer->height,
+ bitstream->has_alpha ? " (with alpha)" : "");
+#endif
+
+ return surface;
}
static cairo_surface_t* webp_loadimage(GVJ_t * job, usershape_t *us)
return NULL;
switch (us->type) {
case FT_WEBP:
-#if 0 // FIXME
- surface = cairo_image_surface_create_from_png_stream(reader, us->f);
- cairo_surface_reference(surface);
-#endif
+ if ((surface = webp_really_loadimage(us->name, us->f)))
+ cairo_surface_reference(surface);
break;
default:
surface = NULL;