1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
/*************************************************************************
* Copyright (c) 2011 AT&T Intellectual Property
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Details at https://graphviz.org
*************************************************************************/
#include "config.h"
#include <gvc/gvplugin_device.h>
#include <gvc/gvio.h>
#include <util/gv_math.h>
#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"
};
enum {
FORMAT_WEBP,
};
static int writer(const uint8_t* data, size_t data_size, const WebPPicture* const pic) {
return gvwrite(pic->custom_ptr, (const char *)data, data_size) == data_size ? 1 : 0;
}
static void webp_format(GVJ_t * job)
{
WebPPicture picture;
WebPPreset preset;
WebPConfig config;
if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) {
fprintf(stderr, "Error! Version mismatch!\n");
goto Error;
}
// if either dimension exceeds the WebP API, map this to one of its errors
if (INT_MAX / BYTES_PER_PIXEL < job->width || job->height > INT_MAX) {
int error = VP8_ENC_ERROR_BAD_DIMENSION;
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
fprintf(stderr, "Error code: %d (%s)\n", error, kErrorMessages[error]);
goto Error;
}
picture.width = (int)job->width;
picture.height = (int)job->height;
const int stride = BYTES_PER_PIXEL * (int)job->width;
picture.writer = writer;
picture.custom_ptr = job;
preset = WEBP_PRESET_DRAWING;
if (!WebPConfigPreset(&config, preset, config.quality)) {
fprintf(stderr, "Error! Could initialize configuration with preset.\n");
goto Error;
}
if (!WebPValidateConfig(&config)) {
fprintf(stderr, "Error! Invalid configuration.\n");
goto Error;
}
if (!WebPPictureAlloc(&picture)) {
fprintf(stderr, "Error! Cannot allocate memory\n");
return;
}
if (!WebPPictureImportBGRA(&picture, job->imagedata, stride)) {
fprintf(stderr, "Error! Cannot import picture\n");
goto Error;
}
if (!WebPEncode(&config, &picture)) {
fprintf(stderr, "Error! Cannot encode picture as WebP\n");
fprintf(stderr, "Error code: %d (%s)\n",
picture.error_code, kErrorMessages[picture.error_code]);
goto Error;
}
Error:
WebPPictureFree(&picture);
}
static gvdevice_engine_t webp_engine = {
NULL, /* webp_initialize */
webp_format,
NULL, /* webp_finalize */
};
static gvdevice_features_t device_features_webp = {
GVDEVICE_BINARY_FORMAT
| GVDEVICE_NO_WRITER
| GVDEVICE_DOES_TRUECOLOR,/* flags */
{0.,0.}, /* default margin - points */
{0.,0.}, /* default page width, height - points */
{96.,96.}, /* 96 dpi */
};
#endif
gvplugin_installed_t gvdevice_webp_types[] = {
#ifdef HAVE_WEBP
{FORMAT_WEBP, "webp:cairo", 1, &webp_engine, &device_features_webp},
#endif
{0, NULL, 0, NULL, NULL}
};
|