"Fossies" - the Fresh Open Source Software Archive

Member "libgd-2.3.2/src/gd_webp.c" (4 Mar 2021, 8624 Bytes) of package /linux/www/libgd-2.3.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gd_webp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.1_vs_2.3.2.

    1 /**
    2  * File: WebP IO
    3  *
    4  * Read and write WebP images.
    5  */
    6 
    7 #ifdef HAVE_CONFIG_H
    8 #include "config.h"
    9 #endif /* HAVE_CONFIG_H */
   10 
   11 
   12 #include <stdio.h>
   13 #include <math.h>
   14 #include <string.h>
   15 #include <stdlib.h>
   16 #include "gd.h"
   17 #include "gd_errors.h"
   18 #include "gdhelpers.h"
   19 
   20 #ifdef HAVE_LIBWEBP
   21 #include "webp/decode.h"
   22 #include "webp/encode.h"
   23 
   24 #define GD_WEBP_ALLOC_STEP (4*1024)
   25 
   26 /*
   27   Function: gdImageCreateFromWebp
   28 
   29     <gdImageCreateFromWebp> is called to load truecolor images from
   30     WebP format files. Invoke <gdImageCreateFromWebp> with an
   31     already opened pointer to a file containing the desired
   32     image. <gdImageCreateFromWebp> returns a <gdImagePtr> to the new
   33     truecolor image, or NULL if unable to load the image (most often
   34     because the file is corrupt or does not contain a WebP
   35     image). <gdImageCreateFromWebp> does not close the file.
   36 
   37     You can inspect the sx and sy members of the image to determine
   38     its size. The image must eventually be destroyed using
   39     <gdImageDestroy>.
   40 
   41     *The returned image is always a truecolor image.*
   42 
   43   Variants:
   44 
   45     <gdImageCreateFromWebpPtr> creates an image from WebP data
   46     already in memory.
   47 
   48     <gdImageCreateFromWebpCtx> reads its data via the function
   49     pointers in a <gdIOCtx> structure.
   50 
   51   Parameters:
   52 
   53     infile - The input FILE pointer.
   54 
   55   Returns:
   56 
   57     A pointer to the new *truecolor* image.  This will need to be
   58     destroyed with <gdImageDestroy> once it is no longer needed.
   59 
   60     On error, returns NULL.
   61 */
   62 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile)
   63 {
   64     gdImagePtr im;
   65     gdIOCtx *in = gdNewFileCtx(inFile);
   66     if (!in) {
   67         return 0;
   68     }
   69     im = gdImageCreateFromWebpCtx(in);
   70     in->gd_free(in);
   71 
   72     return im;
   73 }
   74 
   75 
   76 /*
   77   Function: gdImageCreateFromWebpPtr
   78 
   79     See <gdImageCreateFromWebp>.
   80 
   81   Parameters:
   82 
   83     size            - size of WebP data in bytes.
   84     data            - pointer to WebP data.
   85 */
   86 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpPtr (int size, void *data)
   87 {
   88     gdImagePtr im;
   89     gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
   90     if (!in)
   91         return 0;
   92     im = gdImageCreateFromWebpCtx(in);
   93     in->gd_free(in);
   94     return im;
   95 }
   96 
   97 /*
   98   Function: gdImageCreateFromWebpCtx
   99 
  100     See <gdImageCreateFromWebp>.
  101 */
  102 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile)
  103 {
  104     int    width, height;
  105     uint8_t   *filedata = NULL;
  106     uint8_t    *argb = NULL;
  107     unsigned char   *read, *temp;
  108     size_t size = 0, n;
  109     gdImagePtr im;
  110     int x, y;
  111     uint8_t *p;
  112 
  113     do {
  114         temp = gdRealloc(filedata, size+GD_WEBP_ALLOC_STEP);
  115         if (temp) {
  116             filedata = temp;
  117             read = temp + size;
  118         } else {
  119             if (filedata) {
  120                 gdFree(filedata);
  121             }
  122             gd_error("WebP decode: realloc failed");
  123             return NULL;
  124         }
  125 
  126         n = gdGetBuf(read, GD_WEBP_ALLOC_STEP, infile);
  127         if (n>0 && n!=EOF) {
  128             size += n;
  129         }
  130     } while (n>0 && n!=EOF);
  131 
  132     if (WebPGetInfo(filedata,size, &width, &height) == 0) {
  133         gd_error("gd-webp cannot get webp info");
  134         gdFree(temp);
  135         return NULL;
  136     }
  137 
  138     im = gdImageCreateTrueColor(width, height);
  139     if (!im) {
  140         gdFree(temp);
  141         return NULL;
  142     }
  143     argb = WebPDecodeARGB(filedata, size, &width, &height);
  144     if (!argb) {
  145         gd_error("gd-webp cannot allocate temporary buffer");
  146         gdFree(temp);
  147         gdImageDestroy(im);
  148         return NULL;
  149     }
  150     for (y = 0, p = argb;  y < height; y++) {
  151         for (x = 0; x < width; x++) {
  152             register uint8_t a = gdAlphaMax - (*(p++) >> 1);
  153             register uint8_t r = *(p++);
  154             register uint8_t g = *(p++);
  155             register uint8_t b = *(p++);
  156             im->tpixels[y][x] = gdTrueColorAlpha(r, g, b, a);
  157         }
  158     }
  159     /* do not use gdFree here, in case gdFree/alloc is mapped to something else than libc */
  160     free(argb);
  161     gdFree(temp);
  162     im->saveAlphaFlag = 1;
  163     return im;
  164 }
  165 
  166 
  167 /* returns 0 on success, 1 on failure */
  168 static int _gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
  169 {
  170     uint8_t *argb;
  171     int x, y;
  172     uint8_t *p;
  173     uint8_t *out;
  174     size_t out_size;
  175     int ret = 0;
  176 
  177     if (im == NULL) {
  178         return 1;
  179     }
  180 
  181     if (!gdImageTrueColor(im)) {
  182         gd_error("Palette image not supported by webp");
  183         return 1;
  184     }
  185 
  186     if (quality == -1) {
  187         quality = 80;
  188     }
  189 
  190     if (overflow2(gdImageSX(im), 4)) {
  191         return 1;
  192     }
  193 
  194     if (overflow2(gdImageSX(im) * 4, gdImageSY(im))) {
  195         return 1;
  196     }
  197 
  198     argb = (uint8_t *)gdMalloc(gdImageSX(im) * 4 * gdImageSY(im));
  199     if (!argb) {
  200         return 1;
  201     }
  202     p = argb;
  203     for (y = 0; y < gdImageSY(im); y++) {
  204         for (x = 0; x < gdImageSX(im); x++) {
  205             register int c;
  206             register char a;
  207             c = im->tpixels[y][x];
  208             a = gdTrueColorGetAlpha(c);
  209             if (a == 127) {
  210                 a = 0;
  211             } else {
  212                 a = 255 - ((a << 1) + (a >> 6));
  213             }
  214             *(p++) = gdTrueColorGetRed(c);
  215             *(p++) = gdTrueColorGetGreen(c);
  216             *(p++) = gdTrueColorGetBlue(c);
  217             *(p++) = a;
  218         }
  219     }
  220     out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quality, &out);
  221     if (out_size == 0) {
  222         gd_error("gd-webp encoding failed");
  223         ret = 1;
  224         goto freeargb;
  225     }
  226     gdPutBuf(out, out_size, outfile);
  227     free(out);
  228 
  229 freeargb:
  230     gdFree(argb);
  231 
  232     return ret;
  233 }
  234 
  235 
  236 /*
  237   Function: gdImageWebpCtx
  238 
  239     Write the image as WebP data via a <gdIOCtx>. See <gdImageWebpEx>
  240     for more details.
  241 
  242   Parameters:
  243 
  244     im      - The image to write.
  245     outfile - The output sink.
  246     quality - Image quality.
  247 
  248   Returns:
  249 
  250     Nothing.
  251 */
  252 BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
  253 {
  254     _gdImageWebpCtx(im, outfile, quality);
  255 }
  256 
  257 /*
  258   Function: gdImageWebpEx
  259 
  260     <gdImageWebpEx> outputs the specified image to the specified file in
  261     WebP format. The file must be open for writing. Under MSDOS and
  262     all versions of Windows, it is important to use "wb" as opposed to
  263     simply "w" as the mode when opening the file, and under Unix there
  264     is no penalty for doing so. <gdImageWebpEx> does not close the file;
  265     your code must do so.
  266 
  267     If _quality_ is -1, a reasonable quality value (which should yield a
  268     good general quality / size tradeoff for most situations) is used. Otherwise
  269     _quality_ should be a value in the range 0-100, higher quality values
  270     usually implying both higher quality and larger image sizes.
  271 
  272   Variants:
  273 
  274     <gdImageWebpCtx> stores the image using a <gdIOCtx> struct.
  275 
  276     <gdImageWebpPtrEx> stores the image to RAM.
  277 
  278   Parameters:
  279 
  280     im      - The image to save.
  281     outFile - The FILE pointer to write to.
  282     quality - Compression quality (0-100).
  283 
  284   Returns:
  285 
  286     Nothing.
  287 */
  288 BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
  289 {
  290     gdIOCtx *out = gdNewFileCtx(outFile);
  291     if (out == NULL) {
  292         return;
  293     }
  294     _gdImageWebpCtx(im, out, quality);
  295     out->gd_free(out);
  296 }
  297 
  298 /*
  299   Function: gdImageWebp
  300 
  301     Variant of <gdImageWebpEx> which uses the default quality (-1).
  302 
  303   Parameters:
  304 
  305     im      - The image to save
  306     outFile - The FILE pointer to write to.
  307 
  308   Returns:
  309 
  310     Nothing.
  311 */
  312 BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile)
  313 {
  314     gdIOCtx *out = gdNewFileCtx(outFile);
  315     if (out == NULL) {
  316         return;
  317     }
  318     _gdImageWebpCtx(im, out, -1);
  319     out->gd_free(out);
  320 }
  321 
  322 /*
  323   Function: gdImageWebpPtr
  324 
  325     See <gdImageWebpEx>.
  326 */
  327 BGD_DECLARE(void *) gdImageWebpPtr (gdImagePtr im, int *size)
  328 {
  329     void *rv;
  330     gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  331     if (out == NULL) {
  332         return NULL;
  333     }
  334     if (_gdImageWebpCtx(im, out, -1)) {
  335         rv = NULL;
  336     } else {
  337         rv = gdDPExtractData(out, size);
  338     }
  339     out->gd_free(out);
  340 
  341     return rv;
  342 }
  343 
  344 /*
  345   Function: gdImageWebpPtrEx
  346 
  347     See <gdImageWebpEx>.
  348 */
  349 BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
  350 {
  351     void *rv;
  352     gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  353     if (out == NULL) {
  354         return NULL;
  355     }
  356     if (_gdImageWebpCtx(im, out, quality)) {
  357         rv = NULL;
  358     } else {
  359         rv = gdDPExtractData(out, size);
  360     }
  361     out->gd_free(out);
  362     return rv;
  363 }
  364 
  365 #else /* !HAVE_LIBWEBP */
  366 
  367 static void _noWebpError(void)
  368 {
  369     gd_error("WEBP image support has been disabled\n");
  370 }
  371 
  372 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile)
  373 {
  374     _noWebpError();
  375     return NULL;
  376 }
  377 
  378 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpPtr (int size, void *data)
  379 {
  380     _noWebpError();
  381     return NULL;
  382 }
  383 
  384 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile)
  385 {
  386     _noWebpError();
  387     return NULL;
  388 }
  389 
  390 BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
  391 {
  392     _noWebpError();
  393 }
  394 
  395 BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
  396 {
  397     _noWebpError();
  398 }
  399 
  400 BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile)
  401 {
  402     _noWebpError();
  403 }
  404 
  405 BGD_DECLARE(void *) gdImageWebpPtr (gdImagePtr im, int *size)
  406 {
  407     _noWebpError();
  408     return NULL;
  409 }
  410 
  411 BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
  412 {
  413     _noWebpError();
  414     return NULL;
  415 }
  416 
  417 #endif /* HAVE_LIBWEBP */