"Fossies" - the Fresh Open Source Software Archive

Member "libgd-2.3.3/src/gd_webp.c" (11 Sep 2021, 9348 Bytes) of package /linux/www/libgd-2.3.3.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.

    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     ssize_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     if (quality >= gdWebpLossless) {
  221         out_size = WebPEncodeLosslessRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, &out);
  222     } else {
  223         out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quality, &out);
  224     }
  225     if (out_size == 0) {
  226         gd_error("gd-webp encoding failed");
  227         ret = 1;
  228         goto freeargb;
  229     }
  230 
  231     int res = gdPutBuf(out, out_size, outfile);
  232     free(out);
  233     if (res != out_size) {
  234         gd_error("gd-webp write error\n");
  235         ret = 1;
  236     }
  237 
  238 freeargb:
  239     gdFree(argb);
  240 
  241     return ret;
  242 }
  243 
  244 
  245 /*
  246   Function: gdImageWebpCtx
  247 
  248     Write the image as WebP data via a <gdIOCtx>. See <gdImageWebpEx>
  249     for more details.
  250 
  251   Parameters:
  252 
  253     im      - The image to write.
  254     outfile - The output sink.
  255     quality - Image quality.
  256 
  257   Returns:
  258 
  259     Nothing.
  260 */
  261 BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
  262 {
  263     _gdImageWebpCtx(im, outfile, quality);
  264 }
  265 
  266 /*
  267   Function: gdImageWebpEx
  268 
  269     <gdImageWebpEx> outputs the specified image to the specified file in
  270     WebP format. The file must be open for writing. Under MSDOS and
  271     all versions of Windows, it is important to use "wb" as opposed to
  272     simply "w" as the mode when opening the file, and under Unix there
  273     is no penalty for doing so. <gdImageWebpEx> does not close the file;
  274     your code must do so.
  275 
  276     If _quality_ is -1, a reasonable quality value (which should yield a
  277     good general quality / size tradeoff for most situations) is used. Otherwise
  278     _quality_ should be a value in the range 0-100, higher quality values
  279     usually implying both higher quality and larger image sizes.
  280 
  281     If _quality_ is greater than or equal to <gdWebpLossless> then the image
  282     will be written in the lossless WebP format.
  283 
  284   Variants:
  285 
  286     <gdImageWebpCtx> stores the image using a <gdIOCtx> struct.
  287 
  288     <gdImageWebpPtrEx> stores the image to RAM.
  289 
  290   Parameters:
  291 
  292     im      - The image to save.
  293     outFile - The FILE pointer to write to.
  294     quality - Compression quality (0-100).
  295 
  296   Returns:
  297 
  298     Nothing.
  299 */
  300 BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
  301 {
  302     gdIOCtx *out = gdNewFileCtx(outFile);
  303     if (out == NULL) {
  304         return;
  305     }
  306     _gdImageWebpCtx(im, out, quality);
  307     out->gd_free(out);
  308 }
  309 
  310 /*
  311   Function: gdImageWebp
  312 
  313     Variant of <gdImageWebpEx> which uses the default quality (-1).
  314 
  315   Parameters:
  316 
  317     im      - The image to save
  318     outFile - The FILE pointer to write to.
  319 
  320   Returns:
  321 
  322     Nothing.
  323 */
  324 BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile)
  325 {
  326     gdIOCtx *out = gdNewFileCtx(outFile);
  327     if (out == NULL) {
  328         return;
  329     }
  330     _gdImageWebpCtx(im, out, -1);
  331     out->gd_free(out);
  332 }
  333 
  334 /*
  335   Function: gdImageWebpPtr
  336 
  337     See <gdImageWebpEx>.
  338 */
  339 BGD_DECLARE(void *) gdImageWebpPtr (gdImagePtr im, int *size)
  340 {
  341     void *rv;
  342     gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  343     if (out == NULL) {
  344         return NULL;
  345     }
  346     if (_gdImageWebpCtx(im, out, -1)) {
  347         rv = NULL;
  348     } else {
  349         rv = gdDPExtractData(out, size);
  350     }
  351     out->gd_free(out);
  352 
  353     return rv;
  354 }
  355 
  356 /*
  357   Function: gdImageWebpPtrEx
  358 
  359     See <gdImageWebpEx>.
  360 */
  361 BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
  362 {
  363     void *rv;
  364 
  365     gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  366     if (out == NULL) {
  367         return NULL;
  368     }
  369     if (_gdImageWebpCtx(im, out, quality)) {
  370         rv = NULL;
  371     } else {
  372         rv = gdDPExtractData(out, size);
  373     }
  374     out->gd_free(out);
  375     return rv;
  376 }
  377 
  378 #else /* !HAVE_LIBWEBP */
  379 
  380 static void _noWebpError(void)
  381 {
  382     gd_error("WEBP image support has been disabled\n");
  383 }
  384 
  385 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile)
  386 {
  387     ARG_NOT_USED(inFile);
  388     _noWebpError();
  389     return NULL;
  390 }
  391 
  392 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpPtr (int size, void *data)
  393 {
  394     ARG_NOT_USED(size);
  395     ARG_NOT_USED(data);
  396     _noWebpError();
  397     return NULL;
  398 }
  399 
  400 BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile)
  401 {
  402     ARG_NOT_USED(infile);
  403     _noWebpError();
  404     return NULL;
  405 }
  406 
  407 BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
  408 {
  409     ARG_NOT_USED(im);
  410     ARG_NOT_USED(outfile);
  411     ARG_NOT_USED(quality);
  412     _noWebpError();
  413 }
  414 
  415 BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quality)
  416 {
  417     ARG_NOT_USED(im);
  418     ARG_NOT_USED(outFile);
  419     ARG_NOT_USED(quality);
  420     _noWebpError();
  421 }
  422 
  423 BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile)
  424 {
  425     ARG_NOT_USED(im);
  426     ARG_NOT_USED(outFile);
  427     _noWebpError();
  428 }
  429 
  430 BGD_DECLARE(void *) gdImageWebpPtr (gdImagePtr im, int *size)
  431 {
  432     ARG_NOT_USED(im);
  433     ARG_NOT_USED(size);
  434     _noWebpError();
  435     return NULL;
  436 }
  437 
  438 BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quality)
  439 {
  440     ARG_NOT_USED(im);
  441     ARG_NOT_USED(size);
  442     ARG_NOT_USED(quality);
  443     _noWebpError();
  444     return NULL;
  445 }
  446 
  447 #endif /* HAVE_LIBWEBP */