123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
- #include <stdlib.h>
- #include "gd.h"
- #include "gdhelpers.h"
- #ifdef HAVE_LIBWEBP
- #include "webp/decode.h"
- #include "webp/encode.h"
- #define GD_WEBP_ALLOC_STEP (4*1024)
- gdImagePtr gdImageCreateFromWebp (FILE * inFile)
- {
- gdImagePtr im;
- gdIOCtx *in = gdNewFileCtx(inFile);
- if (!in)
- return 0;
- im = gdImageCreateFromWebpCtx(in);
- in->gd_free(in);
- return im;
- }
- gdImagePtr gdImageCreateFromWebpPtr (int size, void *data)
- {
- gdImagePtr im;
- gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
- if (!in)
- return 0;
- im = gdImageCreateFromWebpCtx(in);
- in->gd_free(in);
- return im;
- }
- gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
- {
- int width, height;
- uint8_t *filedata = NULL;
- uint8_t *argb = NULL;
- size_t size = 0, n;
- gdImagePtr im;
- int x, y;
- uint8_t *p;
- do {
- unsigned char *read, *temp;
- temp = gdRealloc(filedata, size+GD_WEBP_ALLOC_STEP);
- if (temp) {
- filedata = temp;
- read = temp + size;
- } else {
- if (filedata) {
- gdFree(filedata);
- }
- zend_error(E_ERROR, "WebP decode: realloc failed");
- return NULL;
- }
- n = gdGetBuf(read, GD_WEBP_ALLOC_STEP, infile);
- if (n>0 && n!=EOF) {
- size += n;
- }
- } while (n>0 && n!=EOF);
- if (WebPGetInfo(filedata,size, &width, &height) == 0) {
- zend_error(E_ERROR, "gd-webp cannot get webp info");
- gdFree(filedata);
- return NULL;
- }
- im = gdImageCreateTrueColor(width, height);
- if (!im) {
- gdFree(filedata);
- return NULL;
- }
- argb = WebPDecodeARGB(filedata, size, &width, &height);
- if (!argb) {
- zend_error(E_ERROR, "gd-webp cannot allocate temporary buffer");
- gdFree(filedata);
- gdImageDestroy(im);
- return NULL;
- }
- for (y = 0, p = argb; y < height; y++) {
- for (x = 0; x < width; x++) {
- register uint8_t a = gdAlphaMax - (*(p++) >> 1);
- register uint8_t r = *(p++);
- register uint8_t g = *(p++);
- register uint8_t b = *(p++);
- im->tpixels[y][x] = gdTrueColorAlpha(r, g, b, a);
- }
- }
- gdFree(filedata);
- /* do not use gdFree here, in case gdFree/alloc is mapped to something else than libc */
- free(argb);
- im->saveAlphaFlag = 1;
- return im;
- }
- void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
- {
- uint8_t *argb;
- int x, y;
- uint8_t *p;
- uint8_t *out;
- size_t out_size;
- if (im == NULL) {
- return;
- }
- if (!gdImageTrueColor(im)) {
- zend_error(E_ERROR, "Paletter image not supported by webp");
- return;
- }
- if (quality == -1) {
- quality = 80;
- }
- if (overflow2(gdImageSX(im), 4)) {
- return;
- }
- if (overflow2(gdImageSX(im) * 4, gdImageSY(im))) {
- return;
- }
- argb = (uint8_t *)gdMalloc(gdImageSX(im) * 4 * gdImageSY(im));
- if (!argb) {
- return;
- }
- p = argb;
- for (y = 0; y < gdImageSY(im); y++) {
- for (x = 0; x < gdImageSX(im); x++) {
- register int c;
- register char a;
- c = im->tpixels[y][x];
- a = gdTrueColorGetAlpha(c);
- if (a == 127) {
- a = 0;
- } else {
- a = 255 - ((a << 1) + (a >> 6));
- }
- *(p++) = gdTrueColorGetRed(c);
- *(p++) = gdTrueColorGetGreen(c);
- *(p++) = gdTrueColorGetBlue(c);
- *(p++) = a;
- }
- }
-
- if (quality >= gdWebpLossless) {
- out_size = WebPEncodeLosslessRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, &out);
- } else {
- out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quality, &out);
- }
- if (out_size == 0) {
- zend_error(E_ERROR, "gd-webp encoding failed");
- goto freeargb;
- }
- gdPutBuf(out, out_size, outfile);
- free(out);
- freeargb:
- gdFree(argb);
- }
- void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
- {
- gdIOCtx *out = gdNewFileCtx(outFile);
- gdImageWebpCtx(im, out, quality);
- out->gd_free(out);
- }
- void gdImageWebp (gdImagePtr im, FILE * outFile)
- {
- gdIOCtx *out = gdNewFileCtx(outFile);
- gdImageWebpCtx(im, out, -1);
- out->gd_free(out);
- }
- void * gdImageWebpPtr (gdImagePtr im, int *size)
- {
- void *rv;
- gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
- gdImageWebpCtx(im, out, -1);
- rv = gdDPExtractData(out, size);
- out->gd_free(out);
- return rv;
- }
- void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
- {
- void *rv;
- gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
- gdImageWebpCtx(im, out, quality);
- rv = gdDPExtractData(out, size);
- out->gd_free(out);
- return rv;
- }
- #endif /* HAVE_LIBWEBP */
|