root/ext/gd/libgd/gd_webp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gdWebpGetVersionString
  2. gdImageCreateFromWebp
  3. gdImageCreateFromWebpPtr
  4. gdImageCreateFromWebpCtx
  5. gdImageWebpEx
  6. gdImageWebp
  7. gdImageWebpPtr
  8. gdImageWebpPtrEx
  9. mapQualityToVP8QP
  10. gdImageWebpCtx

   1 #include <stdio.h>
   2 #include <math.h>
   3 #include <string.h>
   4 #include <stdlib.h>
   5 #include "gd.h"
   6 
   7 
   8 #ifdef HAVE_LIBVPX
   9 #include "webpimg.h"
  10 #include "gdhelpers.h"
  11 
  12 extern void gd_YUV420toRGBA(uint8* Y,
  13                   uint8* U,
  14                   uint8* V,
  15                   gdImagePtr im);
  16 
  17 extern void gd_RGBAToYUV420(gdImagePtr im2,
  18                   uint8* Y,
  19                   uint8* U,
  20                   uint8* V);
  21 
  22 const char * gdWebpGetVersionString()
  23 {
  24         return "not defined";
  25 }
  26 
  27 gdImagePtr gdImageCreateFromWebp (FILE * inFile)
  28 {
  29         gdImagePtr im;
  30         gdIOCtx *in = gdNewFileCtx(inFile);
  31         im = gdImageCreateFromWebpCtx(in);
  32         in->gd_free(in);
  33 
  34         return im;
  35 }
  36 
  37 gdImagePtr gdImageCreateFromWebpPtr (int size, void *data)
  38 {
  39         int    width, height, ret;
  40         unsigned char   *Y = NULL;
  41         unsigned char   *U = NULL;
  42         unsigned char   *V = NULL;
  43         gdImagePtr im;
  44 
  45         ret = WebPDecode(data, size, &Y, &U, &V, &width, &height);
  46         if (ret != webp_success) {
  47                 if (Y) free(Y);
  48                 if (U) free(U);
  49                 if (V) free(V);
  50                 php_gd_error("WebP decode: fail to decode input data");
  51                 return NULL;
  52         }
  53         im = gdImageCreateTrueColor(width, height);
  54         if (!im) {
  55                 return NULL;
  56         }
  57         gd_YUV420toRGBA(Y, U, V, im);
  58         return im;
  59 }
  60 
  61 #define GD_WEBP_ALLOC_STEP (4*1024)
  62 
  63 gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
  64 {
  65         int    width, height, ret;
  66         unsigned char   *filedata = NULL;
  67         unsigned char   *read, *temp;
  68         unsigned char   *Y = NULL;
  69         unsigned char   *U = NULL;
  70         unsigned char   *V = NULL;
  71         size_t size = 0, n;
  72         gdImagePtr im;
  73 
  74         do {
  75                 temp = gdRealloc(filedata, size+GD_WEBP_ALLOC_STEP);
  76                 if (temp) {
  77                         filedata = temp;
  78                         read = temp + size;
  79                 } else {
  80                         if (filedata) {
  81                                 gdFree(filedata);
  82                         }
  83                         php_gd_error("WebP decode: realloc failed");
  84                         return NULL;
  85                 }
  86 
  87                 n = gdGetBuf(read, GD_WEBP_ALLOC_STEP, infile);
  88                 /* differs from upstream where gdGetBuf return 0 instead of EOF */
  89                 if (n>0 && n!=EOF) {
  90                         size += n;
  91                 }
  92         } while (n>0 && n!=EOF);
  93 
  94         ret = WebPDecode(filedata, size, &Y, &U, &V, &width, &height);
  95         gdFree(filedata);
  96         if (ret != webp_success) {
  97                 if (Y) free(Y);
  98                 if (U) free(U);
  99                 if (V) free(V);
 100                 php_gd_error("WebP decode: fail to decode input data");
 101                 return NULL;
 102         }
 103         im = gdImageCreateTrueColor(width, height);
 104         gd_YUV420toRGBA(Y, U, V, im);
 105         return im;
 106 }
 107 
 108 void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization)
 109 {
 110         gdIOCtx *out = gdNewFileCtx(outFile);
 111         gdImageWebpCtx(im, out, quantization);
 112         out->gd_free(out);
 113 }
 114 
 115 void gdImageWebp (gdImagePtr im, FILE * outFile)
 116 {
 117         gdIOCtx *out = gdNewFileCtx(outFile);
 118         gdImageWebpCtx(im, out, -1);
 119         out->gd_free(out);
 120 }
 121 
 122 void * gdImageWebpPtr (gdImagePtr im, int *size)
 123 {
 124         void *rv;
 125         gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
 126         gdImageWebpCtx(im, out, -1);
 127         rv = gdDPExtractData(out, size);
 128         out->gd_free(out);
 129 
 130         return rv;
 131 }
 132 
 133 void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization)
 134 {
 135         void *rv;
 136         gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
 137         gdImageWebpCtx(im, out, quantization);
 138         rv = gdDPExtractData(out, size);
 139         out->gd_free(out);
 140         return rv;
 141 }
 142 
 143 /*
 144  * Maps normalized QP (quality) to VP8 QP
 145  */
 146 int mapQualityToVP8QP(int quality) {
 147 #define MIN_QUALITY 0
 148 #define MAX_QUALITY 100
 149 #define MIN_VP8QP 1
 150 #define MAX_VP8QP 63
 151         const float scale = MAX_VP8QP - MIN_VP8QP;
 152         const float vp8qp =
 153         scale * (MAX_QUALITY - quality) / (MAX_QUALITY - MIN_QUALITY) + MIN_VP8QP;
 154         if (quality < MIN_QUALITY || quality > MAX_QUALITY) {
 155                 php_gd_error("Wrong quality value %d.", quality);
 156                 return -1;
 157         }
 158 
 159         return (int)(vp8qp + 0.5);
 160 }
 161 
 162 /* This routine is based in part on code from Dale Lutz (Safe Software Inc.)
 163  *  and in part on demo code from Chapter 15 of "PNG: The Definitive Guide"
 164  *  (http://www.cdrom.com/pub/png/pngbook.html).
 165  */
 166 void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
 167 {
 168         int width = im->sx;
 169         int height = im->sy;
 170         int colors = im->colorsTotal;
 171         int *open = im->open;
 172 
 173         int  yuv_width, yuv_height, yuv_nbytes, ret;
 174         int vp8_quality;
 175         unsigned char *Y = NULL,
 176                                   *U = NULL,
 177                                   *V = NULL;
 178         unsigned char *filedata = NULL;
 179 
 180         /* Conversion to Y,U,V buffer */
 181     yuv_width = (width + 1) >> 1;
 182     yuv_height = (height + 1) >> 1;
 183     yuv_nbytes = width * height + 2 * yuv_width * yuv_height;
 184 
 185     if ((Y = (unsigned char *)gdCalloc(yuv_nbytes, sizeof(unsigned char))) == NULL) {
 186         php_gd_error("gd-webp error: cannot allocate Y buffer");
 187         return;
 188     }
 189         vp8_quality = mapQualityToVP8QP(quantization);
 190 
 191     U = Y + width * height;
 192     V = U + yuv_width * yuv_height;
 193     gd_RGBAToYUV420(im, Y, U, V);
 194 
 195         /* Encode Y,U,V and write data to file */
 196     ret = WebPEncode(Y, U, V, width, height, width, yuv_width, yuv_height, yuv_width,
 197                      vp8_quality, &filedata, &yuv_nbytes, NULL);
 198         gdFree(Y);
 199 
 200     if (ret != webp_success) {
 201         if (filedata) {
 202                 free(filedata);
 203                 }
 204                 php_gd_error("gd-webp error: WebP Encoder failed");
 205                 return;
 206     }
 207 
 208     gdPutBuf (filedata, yuv_nbytes, outfile);
 209     free(filedata);
 210 }
 211 
 212 #endif /* HAVE_LIBVPX */

/* [<][>][^][v][top][bottom][index][help] */