Blame src/gd_gd.c

Packit Service df60bb
/**
Packit Service df60bb
 * File: GD IO
Packit Service df60bb
 *
Packit Service df60bb
 * Read and write GD images.
Packit Service df60bb
 *
Packit Service df60bb
 * The GD image format is a proprietary image format of libgd. *It has to be*
Packit Service df60bb
 * *regarded as being obsolete, and should only be used for development and*
Packit Service df60bb
 * *testing purposes.*
Packit Service df60bb
 *
Packit Service df60bb
 * Structure of a GD image file:
Packit Service df60bb
 *  - file header
Packit Service df60bb
 *  - color header (either truecolor or palette)
Packit Service df60bb
 *  - image data
Packit Service df60bb
 *
Packit Service df60bb
 * All numbers are stored in big-endian format.
Packit Service df60bb
 *
Packit Service df60bb
 * File header structure:
Packit Service df60bb
 *  signature     - 1 word ("\xFF\xFE" for truecolor, "\xFF\xFF" for palette)
Packit Service df60bb
 *  width         - 1 word
Packit Service df60bb
 *  height        - 1 word
Packit Service df60bb
 *
Packit Service df60bb
 * Truecolor image color header:
Packit Service df60bb
 *  truecolor   - 1 byte (always "\001")
Packit Service df60bb
 *  transparent - 1 dword (ARGB color)
Packit Service df60bb
 *
Packit Service df60bb
 * Palette image color header:
Packit Service df60bb
 *  truecolor   - 1 byte (always "\0")
Packit Service df60bb
 *  count       - 1 word (the number of used palette colors)
Packit Service df60bb
 *  transparent - 1 dword (ARGB color)
Packit Service df60bb
 *  palette     - 256 dwords (RGBA colors)
Packit Service df60bb
 *
Packit Service df60bb
 * Image data:
Packit Service df60bb
 *  Sequential pixel data; row-major from top to bottom, left to right:
Packit Service df60bb
 *   - 1 byte per pixel for palette images
Packit Service df60bb
 *   - 1 dword (ARGB) per pixel for truecolor images
Packit Service df60bb
 */
Packit Service df60bb
Packit Service df60bb
#ifdef HAVE_CONFIG_H
Packit Service df60bb
#include "config.h"
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#include <stdio.h>
Packit Service df60bb
#include <math.h>
Packit Service df60bb
#include <string.h>
Packit Service df60bb
#include <stdlib.h>
Packit Service df60bb
#include "gd.h"
Packit Service df60bb
Packit Service df60bb
#define TRUE 1
Packit Service df60bb
#define FALSE 0
Packit Service df60bb
Packit Service df60bb
/* Use this for commenting out debug-print statements. */
Packit Service df60bb
/* Just use the first '#define' to allow all the prints... */
Packit Service df60bb
/*#define GD2_DBG(s) (s) */
Packit Service df60bb
#define GD2_DBG(s)
Packit Service df60bb
Packit Service df60bb
/* */
Packit Service df60bb
/* Shared code to read color tables from gd file. */
Packit Service df60bb
/* */
Packit Service df60bb
int
Packit Service df60bb
_gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag)
Packit Service df60bb
{
Packit Service df60bb
	int i;
Packit Service df60bb
	if (gd2xFlag) {
Packit Service df60bb
		int trueColorFlag;
Packit Service df60bb
		if (!gdGetByte (&trueColorFlag, in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
		/* 2.0.12: detect bad truecolor .gd files created by pre-2.0.12.
Packit Service df60bb
		   Beginning in 2.0.12 truecolor is indicated by the initial 2-byte
Packit Service df60bb
		   signature. */
Packit Service df60bb
		if (trueColorFlag != im->trueColor) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
		/* This should have been a word all along */
Packit Service df60bb
		if (!im->trueColor) {
Packit Service df60bb
			if (!gdGetWord (&im->colorsTotal, in)) {
Packit Service df60bb
				goto fail1;
Packit Service df60bb
			}
Packit Service df60bb
			if (im->colorsTotal > gdMaxColors) {
Packit Service df60bb
				goto fail1;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
		/* Int to accommodate truecolor single-color transparency */
Packit Service df60bb
		if (!gdGetInt (&im->transparent, in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
	} else {
Packit Service df60bb
		if (!gdGetByte (&im->colorsTotal, in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
		if (!gdGetWord (&im->transparent, in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
		if (im->transparent == 257) {
Packit Service df60bb
			im->transparent = (-1);
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
	GD2_DBG (printf
Packit Service df60bb
	         ("Palette had %d colours (T=%d)\n", im->colorsTotal,
Packit Service df60bb
	          im->transparent));
Packit Service df60bb
	if (im->trueColor) {
Packit Service df60bb
		return TRUE;
Packit Service df60bb
	}
Packit Service df60bb
	for (i = 0; (i < gdMaxColors); i++) {
Packit Service df60bb
		if (!gdGetByte (&im->red[i], in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
		if (!gdGetByte (&im->green[i], in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
		if (!gdGetByte (&im->blue[i], in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
		if (gd2xFlag) {
Packit Service df60bb
			if (!gdGetByte (&im->alpha[i], in)) {
Packit Service df60bb
				goto fail1;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	for (i = 0; (i < im->colorsTotal); i++) {
Packit Service df60bb
		im->open[i] = 0;
Packit Service df60bb
	};
Packit Service df60bb
Packit Service df60bb
	return TRUE;
Packit Service df60bb
fail1:
Packit Service df60bb
	return FALSE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/* */
Packit Service df60bb
/* Use the common basic header info to make the image object. */
Packit Service df60bb
/* */
Packit Service df60bb
static gdImagePtr
Packit Service df60bb
_gdCreateFromFile (gdIOCtx * in, int *sx, int *sy)
Packit Service df60bb
{
Packit Service df60bb
	gdImagePtr im;
Packit Service df60bb
	int gd2xFlag = 0;
Packit Service df60bb
	int trueColorFlag = 0;
Packit Service df60bb
	if (!gdGetWord (sx, in)) {
Packit Service df60bb
		goto fail1;
Packit Service df60bb
	}
Packit Service df60bb
	if ((*sx == 65535) || (*sx == 65534)) {
Packit Service df60bb
		/* This is a gd 2.0 .gd file */
Packit Service df60bb
		gd2xFlag = 1;
Packit Service df60bb
		/* 2.0.12: 65534 signals a truecolor .gd file.
Packit Service df60bb
		   There is a slight redundancy here but we can
Packit Service df60bb
		   live with it. */
Packit Service df60bb
		if (*sx == 65534) {
Packit Service df60bb
			trueColorFlag = 1;
Packit Service df60bb
		}
Packit Service df60bb
		if (!gdGetWord (sx, in)) {
Packit Service df60bb
			goto fail1;
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
	if (!gdGetWord (sy, in)) {
Packit Service df60bb
		goto fail1;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	GD2_DBG (printf ("Image is %dx%d\n", *sx, *sy));
Packit Service df60bb
	if (trueColorFlag) {
Packit Service df60bb
		im = gdImageCreateTrueColor (*sx, *sy);
Packit Service df60bb
	} else {
Packit Service df60bb
		im = gdImageCreate (*sx, *sy);
Packit Service df60bb
	}
Packit Service df60bb
	if (!im) {
Packit Service df60bb
		goto fail1;
Packit Service df60bb
	}
Packit Service df60bb
	if (!_gdGetColors (in, im, gd2xFlag)) {
Packit Service df60bb
		goto fail2;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return im;
Packit Service df60bb
fail2:
Packit Service df60bb
	gdImageDestroy (im);
Packit Service df60bb
fail1:
Packit Service df60bb
	return 0;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
  Function: gdImageCreateFromGd
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGd> is called to load images from gd format
Packit Service df60bb
    files. Invoke <gdImageCreateFromGd> with an already opened pointer
Packit Service df60bb
    to a file containing the desired image in the gd file format,
Packit Service df60bb
    which is specific to gd and intended for very fast loading. (It is
Packit Service df60bb
    not intended for compression; for compression, use PNG or JPEG.)
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGd> returns a <gdImagePtr> to the new image, or
Packit Service df60bb
    NULL if unable to load the image (most often because the file is
Packit Service df60bb
    corrupt or does not contain a gd format
Packit Service df60bb
    image). <gdImageCreateFromGd> does not close the file. You can
Packit Service df60bb
    inspect the sx and sy members of the image to determine its
Packit Service df60bb
    size. The image must eventually be destroyed using
Packit Service df60bb
    <gdImageDestroy>.
Packit Service df60bb
Packit Service df60bb
  Variants:
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGdPtr> creates an image from GD data (i.e. the
Packit Service df60bb
    contents of a GD file) already in memory.
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGdCtx> reads in an image using the functions in
Packit Service df60bb
    a <gdIOCtx> struct.
Packit Service df60bb
Packit Service df60bb
  Parameters:
Packit Service df60bb
Packit Service df60bb
    infile - The input FILE pointer
Packit Service df60bb
Packit Service df60bb
  Returns:
Packit Service df60bb
Packit Service df60bb
    A pointer to the new image or NULL if an error occurred.
Packit Service df60bb
Packit Service df60bb
  Example:
Packit Service df60bb
Packit Service df60bb
    > gdImagePtr im;
Packit Service df60bb
    > FILE *in;
Packit Service df60bb
    > in = fopen("mygd.gd", "rb");
Packit Service df60bb
    > im = gdImageCreateFromGd(in);
Packit Service df60bb
    > fclose(in);
Packit Service df60bb
    > // ... Use the image ... 
Packit Service df60bb
    > gdImageDestroy(im);
Packit Service df60bb
*/
Packit Service df60bb
BGD_DECLARE(gdImagePtr) gdImageCreateFromGd (FILE * inFile)
Packit Service df60bb
{
Packit Service df60bb
	gdImagePtr im;
Packit Service df60bb
	gdIOCtx *in;
Packit Service df60bb
Packit Service df60bb
	in = gdNewFileCtx (inFile);
Packit Service df60bb
	if (in == NULL) return NULL;
Packit Service df60bb
	im = gdImageCreateFromGdCtx (in);
Packit Service df60bb
Packit Service df60bb
	in->gd_free (in);
Packit Service df60bb
Packit Service df60bb
	return im;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
  Function: gdImageCreateFromGdPtr
Packit Service df60bb
Packit Service df60bb
  Parameters:
Packit Service df60bb
Packit Service df60bb
    size - size of GD data in bytes.
Packit Service df60bb
    data - GD data (i.e. contents of a GIF file).
Packit Service df60bb
Packit Service df60bb
  Reads in GD data from memory. See <gdImageCreateFromGd>.
Packit Service df60bb
*/
Packit Service df60bb
BGD_DECLARE(gdImagePtr) gdImageCreateFromGdPtr (int size, void *data)
Packit Service df60bb
{
Packit Service df60bb
	gdImagePtr im;
Packit Service df60bb
	gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
Packit Service df60bb
	if(!in)
Packit Service df60bb
		return 0;
Packit Service df60bb
	im = gdImageCreateFromGdCtx (in);
Packit Service df60bb
	in->gd_free (in);
Packit Service df60bb
	return im;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
  Function: gdImageCreateFromGdCtx
Packit Service df60bb
Packit Service df60bb
  Reads in a GD image via a <gdIOCtx> struct.  See
Packit Service df60bb
  <gdImageCreateFromGd>.
Packit Service df60bb
*/
Packit Service df60bb
BGD_DECLARE(gdImagePtr) gdImageCreateFromGdCtx (gdIOCtxPtr in)
Packit Service df60bb
{
Packit Service df60bb
	int sx, sy;
Packit Service df60bb
	int x, y;
Packit Service df60bb
	gdImagePtr im;
Packit Service df60bb
Packit Service df60bb
	/* Read the header */
Packit Service df60bb
	im = _gdCreateFromFile (in, &sx, &sy;;
Packit Service df60bb
Packit Service df60bb
	if (im == NULL) {
Packit Service df60bb
		goto fail1;
Packit Service df60bb
	};
Packit Service df60bb
Packit Service df60bb
	/* Then the data... */
Packit Service df60bb
	/* 2.0.12: support truecolor properly in .gd as well as in .gd2.
Packit Service df60bb
	   Problem reported by Andreas Pfaller. */
Packit Service df60bb
	if (im->trueColor) {
Packit Service df60bb
		for (y = 0; (y < sy); y++) {
Packit Service df60bb
			for (x = 0; (x < sx); x++) {
Packit Service df60bb
				int pix;
Packit Service df60bb
				if (!gdGetInt (&pix, in)) {
Packit Service df60bb
					goto fail2;
Packit Service df60bb
				}
Packit Service df60bb
				im->tpixels[y][x] = pix;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	} else {
Packit Service df60bb
		for (y = 0; (y < sy); y++) {
Packit Service df60bb
			for (x = 0; (x < sx); x++) {
Packit Service df60bb
				int ch;
Packit Service df60bb
				ch = gdGetC (in);
Packit Service df60bb
				if (ch == EOF) {
Packit Service df60bb
					goto fail2;
Packit Service df60bb
				}
Packit Service df60bb
				/* ROW-MAJOR IN GD 1.3 */
Packit Service df60bb
				im->pixels[y][x] = ch;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
	return im;
Packit Service df60bb
Packit Service df60bb
fail2:
Packit Service df60bb
	gdImageDestroy (im);
Packit Service df60bb
fail1:
Packit Service df60bb
	return 0;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
void
Packit Service df60bb
_gdPutColors (gdImagePtr im, gdIOCtx * out)
Packit Service df60bb
{
Packit Service df60bb
	int i;
Packit Service df60bb
Packit Service df60bb
	gdPutC (im->trueColor, out);
Packit Service df60bb
	if (!im->trueColor) {
Packit Service df60bb
		gdPutWord (im->colorsTotal, out);
Packit Service df60bb
	}
Packit Service df60bb
	gdPutInt (im->transparent, out);
Packit Service df60bb
	if (!im->trueColor) {
Packit Service df60bb
		for (i = 0; (i < gdMaxColors); i++) {
Packit Service df60bb
			gdPutC ((unsigned char) im->red[i], out);
Packit Service df60bb
			gdPutC ((unsigned char) im->green[i], out);
Packit Service df60bb
			gdPutC ((unsigned char) im->blue[i], out);
Packit Service df60bb
			gdPutC ((unsigned char) im->alpha[i], out);
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static void
Packit Service df60bb
_gdPutHeader (gdImagePtr im, gdIOCtx * out)
Packit Service df60bb
{
Packit Service df60bb
	/* 65535 indicates this is a gd 2.x .gd file.
Packit Service df60bb
	   2.0.12: 65534 indicates truecolor. */
Packit Service df60bb
	if (im->trueColor) {
Packit Service df60bb
		gdPutWord (65534, out);
Packit Service df60bb
	} else {
Packit Service df60bb
		gdPutWord (65535, out);
Packit Service df60bb
	}
Packit Service df60bb
	gdPutWord (im->sx, out);
Packit Service df60bb
	gdPutWord (im->sy, out);
Packit Service df60bb
Packit Service df60bb
	_gdPutColors (im, out);
Packit Service df60bb
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static void
Packit Service df60bb
_gdImageGd (gdImagePtr im, gdIOCtx * out)
Packit Service df60bb
{
Packit Service df60bb
	int x, y;
Packit Service df60bb
Packit Service df60bb
	_gdPutHeader (im, out);
Packit Service df60bb
Packit Service df60bb
	for (y = 0; (y < im->sy); y++) {
Packit Service df60bb
		for (x = 0; (x < im->sx); x++) {
Packit Service df60bb
			/* ROW-MAJOR IN GD 1.3 */
Packit Service df60bb
			if (im->trueColor) {
Packit Service df60bb
				gdPutInt (im->tpixels[y][x], out);
Packit Service df60bb
			} else {
Packit Service df60bb
				gdPutC ((unsigned char) im->pixels[y][x], out);
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
	Function: gdImageGd
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(void) gdImageGd (gdImagePtr im, FILE * outFile)
Packit Service df60bb
{
Packit Service df60bb
	gdIOCtx *out = gdNewFileCtx (outFile);
Packit Service df60bb
	if (out == NULL) return;
Packit Service df60bb
	_gdImageGd (im, out);
Packit Service df60bb
	out->gd_free (out);
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
	Function: gdImageGdPtr
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(void *) gdImageGdPtr (gdImagePtr im, int *size)
Packit Service df60bb
{
Packit Service df60bb
	void *rv;
Packit Service df60bb
	gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
Packit Service df60bb
	if (out == NULL) return NULL;
Packit Service df60bb
	_gdImageGd (im, out);
Packit Service df60bb
	rv = gdDPExtractData (out, size);
Packit Service df60bb
	out->gd_free (out);
Packit Service df60bb
	return rv;
Packit Service df60bb
}