"Fossies" - the Fresh Open Source Software Archive

Member "libgd-2.3.3/src/gd_gd.c" (11 Sep 2021, 9950 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. For more information about "gd_gd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.2_vs_2.3.3.

    1 /**
    2  * File: GD IO
    3  *
    4  * Read and write GD images.
    5  *
    6  * The GD image format is a proprietary image format of libgd. *It has to be*
    7  * *regarded as being obsolete, and should only be used for development and*
    8  * *testing purposes.*
    9  *
   10  * Structure of a GD image file:
   11  *  - file header
   12  *  - color header (either truecolor or palette)
   13  *  - image data
   14  *
   15  * All numbers are stored in big-endian format. Note that all GD output is done
   16  * in the GD 2.x format (not to be confused with the GD2 format), but input may
   17  * also be in the GD 1.x format.
   18  *
   19  * GD 1.x file header structure:
   20  *  width  - 1 word
   21  *  height - 1 word
   22  *
   23  * GD 1.x color header (palette only):
   24  *  count       - 1 byte (the number of used palette colors)
   25  *  transparent - 1 word (257 signals no transparency)
   26  *  palette     - 256×3 bytes (RGB triplets)
   27  *
   28  * GD 2.x file header structure:
   29  *  signature     - 1 word ("\xFF\xFE" for truecolor, "\xFF\xFF" for palette)
   30  *  width         - 1 word
   31  *  height        - 1 word
   32  *
   33  * GD 2.x truecolor image color header:
   34  *  truecolor   - 1 byte (always "\001")
   35  *  transparent - 1 dword (ARGB color); "\377\377\377\377" means that no
   36  *                transparent color is set
   37  *
   38  * GD 2.x palette image color header:
   39  *  truecolor   - 1 byte (always "\0")
   40  *  count       - 1 word (the number of used palette colors)
   41  *  transparent - 1 dword (palette index); "\377\377\377\377" means that no
   42  *                transparent color is set
   43  *  palette     - 256 dwords (RGBA colors)
   44  *
   45  * Image data:
   46  *  Sequential pixel data; row-major from top to bottom, left to right:
   47  *   - 1 byte per pixel for palette images
   48  *   - 1 dword (ARGB) per pixel for truecolor images
   49  */
   50 
   51 #ifdef HAVE_CONFIG_H
   52 #include "config.h"
   53 #endif
   54 
   55 #include <stdio.h>
   56 #include <math.h>
   57 #include <string.h>
   58 #include <stdlib.h>
   59 #include "gd.h"
   60 #include "gd_errors.h"
   61 
   62 /* 2.3: gd is no longer mandatory */
   63 #if ENABLE_GD_FORMATS
   64 
   65 #define TRUE 1
   66 #define FALSE 0
   67 
   68 /* Use this for commenting out debug-print statements. */
   69 /* Just use the first '#define' to allow all the prints... */
   70 /*#define GD2_DBG(s) (s) */
   71 #define GD2_DBG(s)
   72 
   73 /* */
   74 /* Shared code to read color tables from gd file. */
   75 /* */
   76 int
   77 _gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag)
   78 {
   79     int i;
   80     if (gd2xFlag) {
   81         int trueColorFlag;
   82         if (!gdGetByte (&trueColorFlag, in)) {
   83             goto fail1;
   84         }
   85         /* 2.0.12: detect bad truecolor .gd files created by pre-2.0.12.
   86            Beginning in 2.0.12 truecolor is indicated by the initial 2-byte
   87            signature. */
   88         if (trueColorFlag != im->trueColor) {
   89             goto fail1;
   90         }
   91         /* This should have been a word all along */
   92         if (!im->trueColor) {
   93             if (!gdGetWord (&im->colorsTotal, in)) {
   94                 goto fail1;
   95             }
   96             if (im->colorsTotal > gdMaxColors) {
   97                 goto fail1;
   98             }
   99         }
  100         /* Int to accommodate truecolor single-color transparency */
  101         if (!gdGetInt (&im->transparent, in)) {
  102             goto fail1;
  103         }
  104     } else {
  105         if (!gdGetByte (&im->colorsTotal, in)) {
  106             goto fail1;
  107         }
  108         if (!gdGetWord (&im->transparent, in)) {
  109             goto fail1;
  110         }
  111     }
  112     /* Make sure transparent index is within bounds of the palette. */
  113     if (!(im->trueColor) && (im->transparent >= im->colorsTotal || im->transparent < 0)) {
  114         im->transparent = (-1);
  115     }
  116     GD2_DBG (printf
  117              ("Palette had %d colours (T=%d)\n", im->colorsTotal,
  118               im->transparent));
  119     if (im->trueColor) {
  120         return TRUE;
  121     }
  122     for (i = 0; (i < gdMaxColors); i++) {
  123         if (!gdGetByte (&im->red[i], in)) {
  124             goto fail1;
  125         }
  126         if (!gdGetByte (&im->green[i], in)) {
  127             goto fail1;
  128         }
  129         if (!gdGetByte (&im->blue[i], in)) {
  130             goto fail1;
  131         }
  132         if (gd2xFlag) {
  133             if (!gdGetByte (&im->alpha[i], in)) {
  134                 goto fail1;
  135             }
  136         }
  137     }
  138 
  139     for (i = 0; (i < im->colorsTotal); i++) {
  140         im->open[i] = 0;
  141     };
  142 
  143     return TRUE;
  144 fail1:
  145     return FALSE;
  146 }
  147 
  148 /* */
  149 /* Use the common basic header info to make the image object. */
  150 /* */
  151 static gdImagePtr
  152 _gdCreateFromFile (gdIOCtx * in, int *sx, int *sy)
  153 {
  154     gdImagePtr im;
  155     int gd2xFlag = 0;
  156     int trueColorFlag = 0;
  157     if (!gdGetWord (sx, in)) {
  158         goto fail1;
  159     }
  160     if ((*sx == 65535) || (*sx == 65534)) {
  161         /* This is a gd 2.0 .gd file */
  162         gd2xFlag = 1;
  163         /* 2.0.12: 65534 signals a truecolor .gd file.
  164            There is a slight redundancy here but we can
  165            live with it. */
  166         if (*sx == 65534) {
  167             trueColorFlag = 1;
  168         }
  169         if (!gdGetWord (sx, in)) {
  170             goto fail1;
  171         }
  172     }
  173     if (!gdGetWord (sy, in)) {
  174         goto fail1;
  175     }
  176 
  177     GD2_DBG (printf ("Image is %dx%d\n", *sx, *sy));
  178     if (trueColorFlag) {
  179         im = gdImageCreateTrueColor (*sx, *sy);
  180     } else {
  181         im = gdImageCreate (*sx, *sy);
  182     }
  183     if (!im) {
  184         goto fail1;
  185     }
  186     if (!_gdGetColors (in, im, gd2xFlag)) {
  187         goto fail2;
  188     }
  189 
  190     return im;
  191 fail2:
  192     gdImageDestroy (im);
  193 fail1:
  194     return 0;
  195 }
  196 
  197 /*
  198   Function: gdImageCreateFromGd
  199 
  200     <gdImageCreateFromGd> is called to load images from gd format
  201     files. Invoke <gdImageCreateFromGd> with an already opened pointer
  202     to a file containing the desired image in the gd file format,
  203     which is specific to gd and intended for very fast loading. (It is
  204     not intended for compression; for compression, use PNG or JPEG.)
  205 
  206     <gdImageCreateFromGd> returns a <gdImagePtr> to the new image, or
  207     NULL if unable to load the image (most often because the file is
  208     corrupt or does not contain a gd format
  209     image). <gdImageCreateFromGd> does not close the file. You can
  210     inspect the sx and sy members of the image to determine its
  211     size. The image must eventually be destroyed using
  212     <gdImageDestroy>.
  213 
  214   Variants:
  215 
  216     <gdImageCreateFromGdPtr> creates an image from GD data (i.e. the
  217     contents of a GD file) already in memory.
  218 
  219     <gdImageCreateFromGdCtx> reads in an image using the functions in
  220     a <gdIOCtx> struct.
  221 
  222   Parameters:
  223 
  224     infile - The input FILE pointer
  225 
  226   Returns:
  227 
  228     A pointer to the new image or NULL if an error occurred.
  229 
  230   Example:
  231 
  232     > gdImagePtr im;
  233     > FILE *in;
  234     > in = fopen("mygd.gd", "rb");
  235     > im = gdImageCreateFromGd(in);
  236     > fclose(in);
  237     > // ... Use the image ...
  238     > gdImageDestroy(im);
  239 */
  240 BGD_DECLARE(gdImagePtr) gdImageCreateFromGd (FILE * inFile)
  241 {
  242     gdImagePtr im;
  243     gdIOCtx *in;
  244 
  245     in = gdNewFileCtx (inFile);
  246     if (in == NULL) return NULL;
  247     im = gdImageCreateFromGdCtx (in);
  248 
  249     in->gd_free (in);
  250 
  251     return im;
  252 }
  253 
  254 /*
  255   Function: gdImageCreateFromGdPtr
  256 
  257   Parameters:
  258 
  259     size - size of GD data in bytes.
  260     data - GD data (i.e. contents of a GIF file).
  261 
  262   Reads in GD data from memory. See <gdImageCreateFromGd>.
  263 */
  264 BGD_DECLARE(gdImagePtr) gdImageCreateFromGdPtr (int size, void *data)
  265 {
  266     gdImagePtr im;
  267     gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
  268     if(!in)
  269         return 0;
  270     im = gdImageCreateFromGdCtx (in);
  271     in->gd_free (in);
  272     return im;
  273 }
  274 
  275 /*
  276   Function: gdImageCreateFromGdCtx
  277 
  278   Reads in a GD image via a <gdIOCtx> struct.  See
  279   <gdImageCreateFromGd>.
  280 */
  281 BGD_DECLARE(gdImagePtr) gdImageCreateFromGdCtx (gdIOCtxPtr in)
  282 {
  283     int sx, sy;
  284     int x, y;
  285     gdImagePtr im;
  286 
  287     /* Read the header */
  288     im = _gdCreateFromFile (in, &sx, &sy);
  289 
  290     if (im == NULL) {
  291         goto fail1;
  292     };
  293 
  294     /* Then the data... */
  295     /* 2.0.12: support truecolor properly in .gd as well as in .gd2.
  296        Problem reported by Andreas Pfaller. */
  297     if (im->trueColor) {
  298         for (y = 0; (y < sy); y++) {
  299             for (x = 0; (x < sx); x++) {
  300                 int pix;
  301                 if (!gdGetInt (&pix, in)) {
  302                     goto fail2;
  303                 }
  304                 im->tpixels[y][x] = pix;
  305             }
  306         }
  307     } else {
  308         for (y = 0; (y < sy); y++) {
  309             for (x = 0; (x < sx); x++) {
  310                 int ch;
  311                 ch = gdGetC (in);
  312                 if (ch == EOF) {
  313                     goto fail2;
  314                 }
  315                 /* ROW-MAJOR IN GD 1.3 */
  316                 im->pixels[y][x] = ch;
  317             }
  318         }
  319     }
  320     return im;
  321 
  322 fail2:
  323     gdImageDestroy (im);
  324 fail1:
  325     return 0;
  326 }
  327 
  328 void
  329 _gdPutColors (gdImagePtr im, gdIOCtx * out)
  330 {
  331     int i;
  332 
  333     gdPutC (im->trueColor, out);
  334     if (!im->trueColor) {
  335         gdPutWord (im->colorsTotal, out);
  336     }
  337     gdPutInt (im->transparent, out);
  338     if (!im->trueColor) {
  339         for (i = 0; (i < gdMaxColors); i++) {
  340             gdPutC ((unsigned char) im->red[i], out);
  341             gdPutC ((unsigned char) im->green[i], out);
  342             gdPutC ((unsigned char) im->blue[i], out);
  343             gdPutC ((unsigned char) im->alpha[i], out);
  344         }
  345     }
  346 }
  347 
  348 static void
  349 _gdPutHeader (gdImagePtr im, gdIOCtx * out)
  350 {
  351     /* 65535 indicates this is a gd 2.x .gd file.
  352        2.0.12: 65534 indicates truecolor. */
  353     if (im->trueColor) {
  354         gdPutWord (65534, out);
  355     } else {
  356         gdPutWord (65535, out);
  357     }
  358     gdPutWord (im->sx, out);
  359     gdPutWord (im->sy, out);
  360 
  361     _gdPutColors (im, out);
  362 
  363 }
  364 
  365 static void
  366 _gdImageGd (gdImagePtr im, gdIOCtx * out)
  367 {
  368     int x, y;
  369 
  370     _gdPutHeader (im, out);
  371 
  372     for (y = 0; (y < im->sy); y++) {
  373         for (x = 0; (x < im->sx); x++) {
  374             /* ROW-MAJOR IN GD 1.3 */
  375             if (im->trueColor) {
  376                 gdPutInt (im->tpixels[y][x], out);
  377             } else {
  378                 gdPutC ((unsigned char) im->pixels[y][x], out);
  379             }
  380         }
  381     }
  382 }
  383 
  384 /*
  385     Function: gdImageGd
  386  */
  387 BGD_DECLARE(void) gdImageGd (gdImagePtr im, FILE * outFile)
  388 {
  389     gdIOCtx *out = gdNewFileCtx (outFile);
  390     if (out == NULL) return;
  391     _gdImageGd (im, out);
  392     out->gd_free (out);
  393 }
  394 
  395 /*
  396     Function: gdImageGdPtr
  397  */
  398 BGD_DECLARE(void *) gdImageGdPtr (gdImagePtr im, int *size)
  399 {
  400     void *rv;
  401     gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
  402     if (out == NULL) return NULL;
  403     _gdImageGd (im, out);
  404     rv = gdDPExtractData (out, size);
  405     out->gd_free (out);
  406     return rv;
  407 }
  408 
  409 #else /* no HAVE_LIBZ or !ENABLE_GD_FORMATS */
  410 
  411 static void _noGdError (void)
  412 {
  413     gd_error("GD image support has been disabled\n");
  414 }
  415 
  416 BGD_DECLARE(gdImagePtr) gdImageCreateFromGd (FILE * inFile)
  417 {
  418     ARG_NOT_USED(inFile);
  419     _noGdError();
  420     return NULL;
  421 }
  422 
  423 BGD_DECLARE(gdImagePtr) gdImageCreateFromGdPtr (int size, void *data)
  424 {
  425     ARG_NOT_USED(size);
  426     ARG_NOT_USED(data);
  427     _noGdError();
  428     return NULL;
  429 }
  430 
  431 BGD_DECLARE(gdImagePtr) gdImageCreateFromGdCtx (gdIOCtxPtr in)
  432 {
  433     ARG_NOT_USED(in);
  434     _noGdError();
  435     return NULL;
  436 }
  437 
  438 BGD_DECLARE(void) gdImageGd (gdImagePtr im, FILE * outFile)
  439 {
  440     ARG_NOT_USED(im);
  441     ARG_NOT_USED(outFile);
  442     _noGdError();
  443 }
  444 
  445 BGD_DECLARE(void *) gdImageGdPtr (gdImagePtr im, int *size)
  446 {
  447     ARG_NOT_USED(im);
  448     ARG_NOT_USED(size);
  449     _noGdError();
  450     return NULL;
  451 }
  452 
  453 #endif /* ENABLE_GD_FORMATS */