- sync to 1.8.0

master
pierre 2006-04-05 15:40:28 +00:00
parent bdbb50ad58
commit 0c29f6af63
8 changed files with 1903 additions and 247 deletions

View File

@ -13,23 +13,23 @@ AR=ar
#an explicit path for it here, or install manually.
INSTALL=install
#If you don't have FreeType and/or Xpm installed, including the
#If you don't have FreeType, libjpeg and/or Xpm installed, including the
#header files, uncomment this (default).
CFLAGS=-O
#If you do have FreeType and/or Xpm fully installed, uncomment a
#CFLAGS=-O
#If you do have FreeType, libjpeg and/or Xpm fully installed, uncomment a
#variation of this and comment out the line above. See also LIBS below.
#CFLAGS=-O -DHAVE_XPM -DHAVE_LIBTTF
CFLAGS=-O -DHAVE_XPM -DHAVE_JPEG -DHAVE_LIBTTF
#If you don't have FreeType and/or Xpm fully installed, uncomment this
#(default).
LIBS=-lm -lgd -lpng -lz
#LIBS=-lm -lgd -lpng -lz
#If you do have FreeType and/or Xpm fully installed, uncomment a
#If you do have FreeType, JPEG and/or Xpm fully installed, uncomment a
#variation of this and comment out the line above. Note that
#Xpm requires X11. See also CFLAGS above.
#LIBS=-lm -lgd -lpng -lz -lttf -lXpm -lX11
LIBS=-lm -lgd -lpng -lz -ljpeg -lttf -lXpm -lX11
#Typical install locations for freetype, zlib, xpm and libpng header files.
#Typical install locations for freetype, zlib, xpm, libjpeg and libpng header files.
#If yours are somewhere else, change this.
INCLUDEDIRS=-I/usr/local/include -I/usr/include/X11 -I/usr/X11R6/include/X11
@ -121,12 +121,12 @@ gdtestttf: gdtestttf.o libgd.a
$(CC) gdtestttf.o -o gdtestttf $(LIBDIRS) $(LIBS)
libgd.a: gd.o gd_gd.o gd_gd2.o gd_io.o gd_io_dp.o gd_io_file.o gd_ss.o \
gd_io_ss.o gd_png.o gdxpm.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o \
gd_io_ss.o gd_png.o gd_jpeg.o gdxpm.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o \
gdfontg.o gdtables.o gdttf.o gdcache.o gdkanji.o \
gd.h gdfontt.h gdfonts.h gdfontmb.h gdfontl.h gdfontg.h
rm -f libgd.a
$(AR) rc libgd.a gd.o gd_gd.o gd_gd2.o gd_io.o gd_io_dp.o \
gd_io_file.o gd_ss.o gd_io_ss.o gd_png.o gdxpm.o \
gd_io_file.o gd_ss.o gd_io_ss.o gd_png.o gd_jpeg.o gdxpm.o \
gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \
gdtables.o gdttf.o gdcache.o gdkanji.o
-ranlib libgd.a

133
src/gd.c
View File

@ -85,6 +85,137 @@ int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
return ct;
}
/* This code is taken from http://www.acm.org/jgt/papers/SmithLyons96/hwb_rgb.html, an article
* on colour conversion to/from RBG and HWB colour systems.
* It has been modified to return the converted value as a * parameter.
*/
#define RETURN_HWB(h, w, b) {HWB->H = h; HWB->W = w; HWB->B = b; return HWB;}
#define RETURN_RGB(r, g, b) {RGB->R = r; RGB->G = g; RGB->B = b; return RGB;}
#define HWB_UNDEFINED -1
#define SETUP_RGB(s, r, g, b) {s.R = r/255.0; s.G = g/255.0; s.B = b/255.0;}
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c)))
#define MAX(a,b) ((a)<(b)?(b):(a))
#define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c)))
/*
* Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms. Pure
* red always maps to 6 in this implementation. Therefore UNDEFINED can be
* defined as 0 in situations where only unsigned numbers are desired.
*/
typedef struct {float R, G, B;} RGBType;
typedef struct {float H, W, B;} HWBType;
static HWBType* RGB_to_HWB( RGBType RGB, HWBType* HWB) {
/*
* RGB are each on [0, 1]. W and B are returned on [0, 1] and H is
* returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B.
*/
float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f;
int i;
w = MIN3(R, G, B);
v = MAX3(R, G, B);
b = 1 - v;
if (v == w) RETURN_HWB(HWB_UNDEFINED, w, b);
f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
i = (R == w) ? 3 : ((G == w) ? 5 : 1);
RETURN_HWB(i - f /(v - w), w, b);
}
static float HWB_Diff(int r1, int g1, int b1, int r2, int g2, int b2) {
RGBType RGB1, RGB2;
HWBType HWB1, HWB2;
float diff;
SETUP_RGB(RGB1, r1, g1, b1);
SETUP_RGB(RGB2, r2, g2, b2);
RGB_to_HWB(RGB1, &HWB1);
RGB_to_HWB(RGB2, &HWB2);
/*
* I made this bit up; it seems to produce OK results, and it is certainly
* more visually correct than the current RGB metric. (PJW)
*/
if ( (HWB1.H == HWB_UNDEFINED) || (HWB2.H == HWB_UNDEFINED) ) {
diff = 0; /* Undefined hues always match... */
} else {
diff = abs(HWB1.H - HWB2.H);
if (diff > 3) {
diff = 6 - diff; /* Remember, it's a colour circle */
}
}
diff = diff*diff + (HWB1.W - HWB2.W)*(HWB1.W - HWB2.W) + (HWB1.B - HWB2.B)*(HWB1.B - HWB2.B);
return diff;
}
/*
* This is not actually used, but is here for completeness, in case someone wants to
* use the HWB stuff for anything else...
*/
static RGBType* HWB_to_RGB( HWBType HWB, RGBType* RGB ) {
/*
* H is given on [0, 6] or UNDEFINED. W and B are given on [0, 1].
* RGB are each returned on [0, 1].
*/
float h = HWB.H, w = HWB.W, b = HWB.B, v, n, f;
int i;
v = 1 - b;
if (h == HWB_UNDEFINED) RETURN_RGB(v, v, v);
i = floor(h);
f = h - i;
if (i & 1) f = 1 - f; /* if i is odd */
n = w + f * (v - w); /* linear interpolation between w and v */
switch (i) {
case 6:
case 0: RETURN_RGB(v, n, w);
case 1: RETURN_RGB(n, v, w);
case 2: RETURN_RGB(w, v, n);
case 3: RETURN_RGB(w, n, v);
case 4: RETURN_RGB(n, w, v);
case 5: RETURN_RGB(v, w, n);
}
}
int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b)
{
int i;
long rd, gd, bd;
int ct = (-1);
int first = 1;
float mindist = 0;
for (i=0; (i<(im->colorsTotal)); i++) {
float dist;
if (im->open[i]) {
continue;
}
dist = HWB_Diff(im->red[i], im->green[i], im->blue[i], r, g, b);
if (first || (dist < mindist)) {
mindist = dist;
ct = i;
first = 0;
}
}
return ct;
}
int gdImageColorExact(gdImagePtr im, int r, int g, int b)
{
int i;
@ -200,7 +331,7 @@ void gdImagePaletteCopy(gdImagePtr to, gdImagePtr from)
for (y=0 ; y < (to->sy) ; y++) {
p = gdImageGetPixel(to, x, y);
if (xlate[p] == -1) {
xlate[p] = gdImageColorClosest(from, to->red[p], to->green[p], to->blue[p]);
xlate[p] = gdImageColorClosestHWB(from, to->red[p], to->green[p], to->blue[p]);
/*printf("Mapping %d (%d, %d, %d) to %d (%d, %d, %d)\n", */
/* p, to->red[p], to->green[p], to->blue[p], */
/* xlate[p], from->red[xlate[p]], from->green[xlate[p]], from->blue[xlate[p]]); */

View File

@ -156,8 +156,17 @@ void gdImageColorTransparent(gdImagePtr im, int color);
void gdImagePaletteCopy(gdImagePtr dst, gdImagePtr src);
void gdImagePng(gdImagePtr im, FILE *out);
void gdImagePngCtx(gdImagePtr im, gdIOCtx *out);
void gdImageWBMP(gdImagePtr image, int fg, FILE *out);
void gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out);
/* A custom data sink. */
void gdImageJpeg(gdImagePtr im, FILE *out, int quality);
void gdImageJpegCtx(gdImagePtr im, gdIOCtx *out, int quality);
void *gdImageJpegPtr(gdImagePtr im, int *size, int quality);
gdImagePtr gdImageCreateFromJpeg(FILE *infile);
gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile);
/* A custom data sink. For backwards compatibility. Use
gdIOCtx instead. */
/* The sink function must return -1 on error, otherwise the number
of bytes written, which must be equal to len. */
/* context will be passed to your sink function. */

757
src/gd_jpeg.c Normal file
View File

@ -0,0 +1,757 @@
/*
* gd_jpeg.c: Read and write JPEG (JFIF) format image files using the
* gd graphics library (http://www.boutell.com/gd/).
*
* This software is based in part on the work of the Independent JPEG
* Group. For more information on the IJG JPEG software (and JPEG
* documentation, etc.), see ftp://ftp.uu.net/graphics/jpeg/.
*
* NOTE: IJG 12-bit JSAMPLE (BITS_IN_JSAMPLE == 12) mode, although
* theoretically supported in this code, has not really been tested.
* Caveat emptor.
*
* Copyright 2000 Doug Becker, mailto:thebeckers@home.com
*/
#ifdef HAVE_JPEG
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <limits.h>
#include <string.h>
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
#include "gd.h"
static const char * const GD_JPEG_VERSION = "1.0";
typedef struct _jmpbuf_wrapper {
jmp_buf jmpbuf;
} jmpbuf_wrapper;
/* Called by the IJG JPEG library upon encountering a fatal error */
static void
fatal_jpeg_error(j_common_ptr cinfo)
{
jmpbuf_wrapper *jmpbufw;
fprintf(stderr, "gd-jpeg: JPEG library reports unrecoverable error: ");
(*cinfo->err->output_message)(cinfo);
fflush(stderr);
jmpbufw = (jmpbuf_wrapper *)cinfo->client_data;
jpeg_destroy(cinfo);
if (jmpbufw != 0) {
longjmp(jmpbufw->jmpbuf, 1);
fprintf(stderr, "gd-jpeg: EXTREMELY fatal error: longjmp"
" returned control; terminating\n");
} else {
fprintf(stderr, "gd-jpeg: EXTREMELY fatal error: jmpbuf"
" unrecoverable; terminating\n");
}
fflush(stderr);
exit(99);
}
/*
* Write IM to OUTFILE as a JFIF-formatted JPEG image, using quality
* QUALITY. If QUALITY is in the range 0-100, increasing values
* represent higher quality but also larger image size. If QUALITY is
* negative, the IJG JPEG library's default quality is used (which
* should be near optimal for many applications). See the IJG JPEG
* library documentation for more details. */
void gdImageJpeg(gdImagePtr im, FILE *outFile, int quality)
{
gdIOCtx *out = gdNewFileCtx(outFile);
gdImageJpegCtx(im, out, quality);
out->free(out);
}
void* gdImageJpegPtr(gdImagePtr im, int *size, int quality)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
gdImageJpegCtx(im, out, quality);
rv = gdDPExtractData(out, size);
out->free(out);
return rv;
}
void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile);
void
gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int i, j, jidx;
/* volatile so we can free it on return from longjmp */
volatile JSAMPROW row = 0;
JSAMPROW rowptr[1];
jmpbuf_wrapper jmpbufw;
JDIMENSION nlines;
char comment[255];
#ifdef DEBUG
printf("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
printf("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
for (i = 0; i < im->colorsTotal; i++) {
if (!im->open[i])
printf("gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i,
im->red[i], im->green[i], im->blue[i]);
}
#endif /* DEBUG */
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
cinfo.err = jpeg_std_error(&jerr);
cinfo.client_data = &jmpbufw;
if (setjmp(jmpbufw.jmpbuf) != 0) {
/* we're here courtesy of longjmp */
if (row)
free(row);
return;
}
cinfo.err->error_exit = fatal_jpeg_error;
jpeg_create_compress(&cinfo);
cinfo.image_width = im->sx;
cinfo.image_height = im->sy;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
if (quality >= 0)
jpeg_set_quality(&cinfo, quality, TRUE);
/* If user requests interlace, translate that to progressive JPEG */
if (gdImageGetInterlaced(im)) {
#ifdef DEBUG
printf("gd-jpeg: interlace set, outputting progressive"
" JPEG image\n");
#endif
jpeg_simple_progression(&cinfo);
}
jpeg_gdIOCtx_dest(&cinfo, outfile);
row = (JSAMPROW)calloc(1, cinfo.image_width * cinfo.input_components
* sizeof(JSAMPLE));
if (row == 0) {
fprintf(stderr, "gd-jpeg: error: unable to allocate JPEG row "
"structure: calloc returns NULL\n");
jpeg_destroy_compress(&cinfo);
return;
}
rowptr[0] = row;
jpeg_start_compress(&cinfo, TRUE);
sprintf(comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),",
GD_JPEG_VERSION, JPEG_LIB_VERSION);
if (quality >= 0)
sprintf(comment + strlen(comment), " quality = %d\n",
quality);
else
strcat(comment + strlen(comment), " default quality\n");
jpeg_write_marker(&cinfo, JPEG_COM, (JOCTET *)comment,
(unsigned int)strlen(comment));
for (i = 0; i < im->sy; i++) {
for (jidx = 0, j = 0; j < im->sx; j++) {
int idx = im->pixels[i][j];
/*
* NB: Although gd RGB values are ints, their max value is
* 255 (see the documentation for gdImageColorAllocate())
* -- perfect for 8-bit JPEG encoding (which is the norm)
*/
#if BITS_IN_JSAMPLE == 8
row[jidx++] = im->red[idx];
row[jidx++] = im->green[idx];
row[jidx++] = im->blue[idx];
#elif BITS_IN_JSAMPLE == 12
row[jidx++] = im->red[idx] << 4;
row[jidx++] = im->green[idx] << 4;
row[jidx++] = im->blue[idx] << 4;
#else
#error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
#endif
}
nlines = jpeg_write_scanlines(&cinfo, rowptr, 1);
if (nlines != 1)
fprintf(stderr, "gd_jpeg: warning: jpeg_write_scanlines"
" returns %u -- expected 1\n", nlines);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
free(row);
}
gdImagePtr gdImageCreateFromJpeg(FILE *inFile)
{
gdImagePtr im;
gdIOCtx *in = gdNewFileCtx(inFile);
im = gdImageCreateFromJpegCtx(in);
in->free(in);
return im;
}
void
jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
gdIOCtx *infile);
/*
* Create a gd-format image from the JPEG-format INFILE. Returns the
* image, or NULL upon error.
*/
gdImagePtr
gdImageCreateFromJpegCtx(gdIOCtx *infile)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
jmpbuf_wrapper jmpbufw;
/* volatile so we can free them after longjmp */
volatile JSAMPROW row = 0;
volatile gdImagePtr im = 0;
JSAMPROW rowptr[1];
int i, j, retval;
JDIMENSION nrows;
#ifdef DEBUG
printf("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
printf("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
#endif
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
cinfo.err = jpeg_std_error(&jerr);
cinfo.client_data = &jmpbufw;
if (setjmp(jmpbufw.jmpbuf) != 0) {
/* we're here courtesy of longjmp */
if (row)
free(row);
if (im)
gdImageDestroy(im);
return 0;
}
cinfo.err->error_exit = fatal_jpeg_error;
jpeg_create_decompress(&cinfo);
jpeg_gdIOCtx_src(&cinfo, infile);
retval = jpeg_read_header(&cinfo, TRUE);
if (retval != JPEG_HEADER_OK)
fprintf(stderr, "gd-jpeg: warning: jpeg_read_header returns"
" %d, expected %d\n", retval, JPEG_HEADER_OK);
if (cinfo.image_height > INT_MAX)
fprintf(stderr, "gd-jpeg: warning: JPEG image height (%u) is"
" greater than INT_MAX (%d) (and thus greater than"
" gd can handle)", cinfo.image_height,
INT_MAX);
if (cinfo.image_width > INT_MAX)
fprintf(stderr, "gd-jpeg: warning: JPEG image width (%u) is"
" greater than INT_MAX (%d) (and thus greater than"
" gd can handle)\n", cinfo.image_width, INT_MAX);
im = gdImageCreate((int)cinfo.image_width,
(int)cinfo.image_height);
if (im == 0) {
fprintf(stderr, "gd-jpeg error: cannot allocate gdImage"
" struct\n");
goto error;
}
/*
* Have the JPEG library quantize the number of image colors to
* 256 maximum; force into RGB colorspace
*/
cinfo.out_color_space = JCS_RGB;
cinfo.quantize_colors = TRUE;
cinfo.desired_number_of_colors = gdMaxColors;
if (jpeg_start_decompress(&cinfo) != TRUE)
fprintf(stderr, "gd-jpeg: warning: jpeg_start_decompress"
" reports suspended data source\n");
#ifdef DEBUG
printf("gd-jpeg: JPEG image information:");
if (cinfo.saw_JFIF_marker)
printf(" JFIF version %d.%.2d",
(int)cinfo.JFIF_major_version,
(int)cinfo.JFIF_minor_version);
else if (cinfo.saw_Adobe_marker)
printf(" Adobe format");
else
printf(" UNKNOWN format");
printf(" %ux%u (raw) / %ux%u (scaled) %d-bit", cinfo.image_width,
cinfo.image_height, cinfo.output_width,
cinfo.output_height, cinfo.data_precision);
printf(" %s", (cinfo.progressive_mode ? "progressive" :
"baseline"));
printf(" image, %d quantized colors, ",
cinfo.actual_number_of_colors);
switch (cinfo.jpeg_color_space) {
case JCS_GRAYSCALE:
printf("grayscale");
break;
case JCS_RGB:
printf("RGB");
break;
case JCS_YCbCr:
printf("YCbCr (a.k.a. YUV)");
break;
case JCS_CMYK:
printf("CMYK");
break;
case JCS_YCCK:
printf("YCbCrK");
break;
default:
printf("UNKNOWN (value: %d)", (int)cinfo.jpeg_color_space);
break;
}
printf(" colorspace\n");
fflush(stdout);
#endif /* DEBUG */
gdImageInterlace(im, cinfo.progressive_mode != 0);
im->colorsTotal = cinfo.actual_number_of_colors;
if (cinfo.output_components != 1) {
fprintf(stderr, "gd-jpeg: error: JPEG color quantization"
" request resulted in output_components == %d"
" (expected 1)\n", cinfo.output_components);
goto error;
}
for (i = 0; i < im->colorsTotal; i++) {
#if BITS_IN_JSAMPLE == 8
im->red[i] = cinfo.colormap[0][i];
im->green[i] = cinfo.colormap[1][i];
im->blue[i] = cinfo.colormap[2][i];
#elif BITS_IN_JSAMPLE == 12
im->red[i] = (cinfo.colormap[0][i] >> 4) & 0xff;
im->green[i] = (cinfo.colormap[1][i] >> 4) & 0xff;
im->blue[i] = (cinfo.colormap[2][i] >> 4) & 0xff;
#else
#error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
#endif
im->open[i] = 0;
#ifdef DEBUG
printf("gd-jpeg: gd colormap index %d set to (%d, %d, %d)\n", i,
im->red[i], im->green[i], im->blue[i]);
#endif
}
row = calloc(cinfo.output_width, sizeof(JSAMPLE));
if (row == 0) {
fprintf(stderr, "gd-jpeg: error: unable to allocate row for"
" JPEG scanline: calloc returns NULL\n");
goto error;
}
rowptr[0] = row;
for (i = 0; i < cinfo.output_height; i++) {
nrows = jpeg_read_scanlines(&cinfo, rowptr, 1);
if (nrows != 1) {
fprintf(stderr, "gd-jpeg: error: jpeg_read_scanlines"
" returns %u, expected 1\n", nrows);
goto error;
}
for (j = 0; j < cinfo.output_width; j++)
im->pixels[i][j] = row[j];
}
if (jpeg_finish_decompress(&cinfo) != TRUE)
fprintf(stderr, "gd-jpeg: warning: jpeg_finish_decompress"
" reports suspended data source\n");
jpeg_destroy_decompress(&cinfo);
free(row);
return im;
error:
jpeg_destroy_decompress(&cinfo);
if (row)
free(row);
if (im)
gdImageDestroy(im);
return 0;
}
/*
*
* gdIOCtx JPEG data sources and sinks, T. Boutell
* almost a simple global replace from T. Lane's stdio versions.
*
*/
/* Different versions of libjpeg use either 'jboolean' or 'boolean', and
some platforms define 'boolean', and so forth. Deal with this
madness by typedeffing 'safeboolean' to 'boolean' if HAVE_BOOLEAN
is already set, because this is the test that libjpeg uses.
Otherwise, typedef it to int, because that's what libjpeg does
if HAVE_BOOLEAN is not defined. -TBB */
#ifdef HAVE_BOOLEAN
typedef boolean safeboolean;
#else
typedef int safeboolean;
#endif /* HAVE_BOOLEAN */
/* Expanded data source object for gdIOCtx input */
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
gdIOCtx *infile; /* source stream */
JOCTET * buffer; /* start of buffer */
safeboolean start_of_file; /* have we gotten any data yet? */
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
void
init_source (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
/* We reset the empty-input-file flag for each image,
* but we don't clear the input buffer.
* This is correct behavior for reading a series of images from one source.
*/
src->start_of_file = TRUE;
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*
* In typical applications, this should read fresh data into the buffer
* (ignoring the current state of next_input_byte & bytes_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been reloaded. It is not necessary to
* fill the buffer entirely, only to obtain at least one more byte.
*
* There is no such thing as an EOF return. If the end of the file has been
* reached, the routine has a choice of ERREXIT() or inserting fake data into
* the buffer. In most cases, generating a warning message and inserting a
* fake EOI marker is the best course of action --- this will allow the
* decompressor to output however much of the image is there. However,
* the resulting error message is misleading if the real problem is an empty
* input file, so we handle that case specially.
*
* In applications that need to be able to suspend compression due to input
* not being available yet, a FALSE return indicates that no more data can be
* obtained right now, but more may be forthcoming later. In this situation,
* the decompressor will return to its caller (with an indication of the
* number of scanlines it has read, if any). The application should resume
* decompression after it has loaded more data into the input buffer. Note
* that there are substantial restrictions on the use of suspension --- see
* the documentation.
*
* When suspending, the decompressor will back up to a convenient restart point
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point must be rescanned after resumption, so move it to
* the front of the buffer rather than discarding it.
*/
#define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
safeboolean
fill_input_buffer (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
size_t nbytes = 0;
size_t got;
char *s;
memset(src->buffer, 0, INPUT_BUF_SIZE);
while (nbytes < INPUT_BUF_SIZE) {
int got = gdGetBuf(src->buffer + nbytes,
INPUT_BUF_SIZE - nbytes,
src->infile);
if ((got == EOF) || (got == 0)) {
/* EOF or error. If we got any data, don't worry about it.
If we didn't, then this is unexpected. */
if (!nbytes) {
nbytes = -1;
}
break;
}
nbytes += got;
}
if (nbytes <= 0) {
if (src->start_of_file) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
src->buffer[0] = (JOCTET) 0xFF;
src->buffer[1] = (JOCTET) JPEG_EOI;
nbytes = 2;
}
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = nbytes;
src->start_of_file = FALSE;
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* Writers of suspendable-input applications must note that skip_input_data
* is not granted the right to give a suspension return. If the skip extends
* beyond the data currently in the buffer, the buffer can be marked empty so
* that the next read will cause a fill_input_buffer call that can suspend.
* Arranging for additional bytes to be discarded before reloading the input
* buffer is the application writer's problem.
*/
void
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
/* Just a dumb implementation for now. Not clear that being smart is worth
* any trouble anyway --- large skips are infrequent.
*/
if (num_bytes > 0) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* An additional method that can be provided by data source modules is the
* resync_to_restart method for error recovery in the presence of RST markers.
* For the moment, this source module just uses the default resync method
* provided by the JPEG library. That method assumes that no backtracking
* is possible.
*/
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
void
term_source (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
}
/*
* Prepare for input from a gdIOCtx stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing decompression.
*/
void
jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
gdIOCtx *infile)
{
my_src_ptr src;
/* The source object and input buffer are made permanent so that a series
* of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src
* only before the first one. (If we discarded the buffer at the end of
* one image, we'd likely lose the start of the next one.)
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_source_mgr));
src = (my_src_ptr) cinfo->src;
src->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
INPUT_BUF_SIZE * SIZEOF(JOCTET));
}
src = (my_src_ptr) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->infile = infile;
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
}
/* Expanded data destination object for stdio output */
typedef struct {
struct jpeg_destination_mgr pub; /* public fields */
gdIOCtx * outfile; /* target stream */
JOCTET * buffer; /* start of buffer */
} my_destination_mgr;
typedef my_destination_mgr * my_dest_ptr;
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
/*
* Initialize destination --- called by jpeg_start_compress
* before any data is actually written.
*/
void init_destination (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
/* Allocate the output buffer --- it will be released when done with image */
dest->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
/*
* Empty the output buffer --- called whenever buffer fills up.
*
* In typical applications, this should write the entire output buffer
* (ignoring the current state of next_output_byte & free_in_buffer),
* reset the pointer & count to the start of the buffer, and return TRUE
* indicating that the buffer has been dumped.
*
* In applications that need to be able to suspend compression due to output
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
* In this situation, the compressor will return to its caller (possibly with
* an indication that it has not accepted all the supplied scanlines). The
* application should resume compression after it has made more room in the
* output buffer. Note that there are substantial restrictions on the use of
* suspension --- see the documentation.
*
* When suspending, the compressor will back up to a convenient restart point
* (typically the start of the current MCU). next_output_byte & free_in_buffer
* indicate where the restart point will be if the current call returns FALSE.
* Data beyond this point will be regenerated after resumption, so do not
* write it out when emptying the buffer externally.
*/
safeboolean empty_output_buffer (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
if (gdPutBuf(dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) !=
(size_t) OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
return TRUE;
}
/*
* Terminate destination --- called by jpeg_finish_compress
* after all data has been written. Usually needs to flush buffer.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
void term_destination (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
if (datacount > 0) {
if (gdPutBuf(dest->buffer, datacount, dest->outfile) != datacount)
ERREXIT(cinfo, JERR_FILE_WRITE);
}
}
/*
* Prepare for output to a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing compression.
*/
void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile)
{
my_dest_ptr dest;
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_destination_mgr));
}
dest = (my_dest_ptr) cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
dest->outfile = outfile;
}
#endif /* HAVE_JPEG */

292
src/gd_wbmp.c Normal file
View File

@ -0,0 +1,292 @@
/*
Creation of wbmp image files with gd library
gd_wbmp.c
Copyright (C) Maurice Szmurlo --- T-SIT --- January 2000
(Maurice.Szmurlo@info.unicaen.fr)
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation. This software is provided "as is" without express or
implied warranty.
-----------------------------------------------------------------------------------------
Parts od this code are inspired by 'pbmtowbmp.c' and 'wbmptopbm.c' by
Terje Sannum <terje@looplab.com>.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
**
-----------------------------------------------------------------------------------------
Todo:
gdCreateFromWBMP function for reading WBMP files
-----------------------------------------------------------------------------------------
Compilation:
* testing the mbi data structure:
gcc -Wall -W -D__MBI_DEBUG__ gd_wbmp.c -o mbi -L/usr/local/lib -lgd
* testing generation of wbmp images
gcc -Wall -W -D__GD_WBMP_DEBUG__ gd_wbmp.c -o gd_wbmp -L/usr/local/lib -lgd -lpng
* simply making the object file
gcc -c -Wall -W gd_wbmp.c -o gd_wbmp.o
*/
#include <gd.h>
#include <gdfonts.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
/* *************************** Multi Byte Integer Funcionnalities *************************** */
/* **************************************************
An mbi is an array of bytes.
For 32 bit integers, 5 bytes are sufficient.
*/
typedef unsigned char mbi_t[6];
/* **************************************************
initialization of an mbi in order to be used by the int2mbi function
*/
static void mbiInit(mbi_t mbi) {
int i;
mbi[0] = mbi[5] = (unsigned char)0;
for(i=1; i<5; mbi[i++] = 0x80);
}
/* **************************************************
Displays the content of the mbi as a serie of hexa bytes.
For debuging purpose only
*/
#ifdef __MBI_DEBUG__
static void mbiDisplay(mbi_t mbi, FILE *out) {
unsigned int i;
fprintf(out, "MBI:%d [", (unsigned int)mbi[0]);
if(mbi[0] > 0)
fprintf(out, "%X", (unsigned int)mbi[1]);
for(i=2; i<=mbi[0]; i++)
fprintf(out, ":%02X", (unsigned int)mbi[i]);
fprintf(out, "]\n");
}
#endif /* __MBI_DEBUG__ */
/* **************************************************
writes the bytes constituing the mbi on the stream 'out'
*/
static void mbiPrint(mbi_t mbi, gdIOCtx *out) {
unsigned int i;
for(i=1; i<=(unsigned int)mbi[0]; gdPutC(mbi[i++], out));
}
/* **************************************************
Conversion routines:
unsigned int -> multi byte integer
multi byte integer -> unsigned int
*/
static void int2mbi(mbi_t mbi, unsigned int val) {
unsigned int i, j;
mbiInit(mbi);
for(i=5; i>0; i--) {
mbi[i] = mbi[i] | (val & 0x7F);
val = val >> 7;
}
for(j=1; (mbi[j] & 0x7F) == 0 && j<=5; j++);
mbi[0] = (unsigned char)(5-j+1);
for(i=1; i<=mbi[0]; mbi[i++] = mbi[j++]);
}
static unsigned int mbi2int(mbi_t mbi) {
unsigned int res=0, i;
for(i=0; i<(unsigned int)mbi[0]; i++)
res = (res << 7) | (unsigned int) ( mbi[i+1] & 0x7F );
return res;
}
#ifdef __MBI_DEBUG__
int main(void) {
mbi_t mbi;
fprintf(stdout, "testing Multi Byte Integers:\n");
int2mbi(mbi, 0);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
/* 0xA0 and 0x60 are the two examples from the wbmp specs */
int2mbi(mbi, 0xA0);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
int2mbi(mbi, 0x60);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
int2mbi(mbi, 1024+512);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
int2mbi(mbi, 1024+512+1);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
int2mbi(mbi, 775432);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
int2mbi(mbi, 405589432);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
int2mbi(mbi, UINT_MAX);
mbiDisplay(mbi, stdout);
fprintf(stdout, ">> = %u\n", mbi2int(mbi));
fprintf(stdout, "\n");
return 0;
}
#endif
/* *************************** GD interface *************************** */
/*
Write the image as a wbmp file
Parameters are:
image: gd image structure;
fg: the index of the foreground color. any other value will be considered
as background and will not be written
out: the stream where to write
*/
void gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out) {
int x, y;
mbi_t mbi;
/* wbmp images are type 0: B&W; no compression; empty FixHeaderFlield */
gdPutC(0, out); /* header */
gdPutC(0, out); /* FixHeaderFlield */
/* width and height as mbi */
int2mbi(mbi, gdImageSX(image)); /* width */
mbiPrint(mbi, out);
int2mbi(mbi, gdImageSY(image)); /* height */
mbiPrint(mbi, out);
/*
now come the pixels as strings of bits padded with 0's at the end of the
lines, if necessary
*/
for(y=0; y<gdImageSY(image); y++) {
unsigned char nbPixs = 0; /* how many pixels already written */
unsigned char pixels = 0; /* the 8 pixels string */
for(x=0; x<gdImageSX(image); x++) {
if(gdImageGetPixel(image, x, y) == fg) {
pixels = pixels | (1 << (7-nbPixs));
}
nbPixs ++;
if(nbPixs == 8) { /* 8 pixels written -> write to file */
gdPutC(pixels, out);
pixels = 0;
nbPixs = 0;
}
}
/* if there are pixels left to write, write them */
if(nbPixs != 0)
gdPutC(pixels, out);
}
}
/*
Write the image as a wbmp file
Parameters are:
image: gd image structure;
fg: the index of the foreground color. any other value will be considered
as background and will not be written
out: the stream where to write
*/
void gdImageWBMP(gdImagePtr image, int fg, FILE *out)
{
gdIOCtx *out = gdNewFileCtx(outFile);
gdImageWBMPCtx(im, out);
out->free(out);
}
void* gdImageWBMPPtr(gdImagePtr im, int *size)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
gdImageWBMPCtx(im, out);
rv = gdDPExtractData(out, size);
out->free(out);
return rv;
}
#ifdef __GD_WBMP_DEBUG__
int main(int argc, char **argv) {
gdImagePtr image;
int bg, fg;
FILE *out;
if(argc != 2) {
fprintf(stderr, "usage %s <wbmp file>\n", argv[0]);
exit(1);
}
fprintf(stdout, "testing gd generation of WBMP files\n");
fprintf(stdout, "Opening WBMP file '%s'\n", argv[1]);
if(!(out = fopen(argv[1], "w"))) {
fprintf(stderr, "Cannot open out file '%s'\n", argv[1]);
exit(1);
}
fprintf(stdout, "Creating GD image and drawing...y\n");
if(!(image = gdImageCreate(60, 30))) {
fprintf(stderr, "Cannot create image 30x60\n");
exit(1);
}
/* don't really care about rgb values */
bg = gdImageColorAllocate(image, 0, 0, 0);
fg = gdImageColorAllocate(image, 255, 255, 255);
/* draw something : */
gdImageRectangle(image, 1, 1, gdImageSX(image)-2, gdImageSY(image)-2, fg);
/* write something interesting */
gdImageString(image, gdFontSmall, 3, 0, "Hello", fg);
/* write the wbmp file */
fprintf(stdout, "Writing WBMP file '%s':\n", argv[1]);
gdImageWBMP(image, fg, out);
fclose(out);
fprintf(stdout, "Written.\nTry now to load the file '%s' with a WAP browser.\n", argv[1]);
fprintf(stdout, "\n");
return 0;
}
#endif /* __GD_WBMP_DEBUG__ */

View File

@ -246,13 +246,31 @@ int main(int argc, char **argv)
printf("[Merged Image has %d colours]\n",im2->colorsTotal);
CompareImages("Merged (gdtest.png, gdtest_merge.png)", im2, im3);
/*out = fopen("gdtest_merge.png", "wb"); */
/*gdImageLzw(im2, out); */
/*fclose(out); */
gdImageDestroy(im2);
gdImageDestroy(im3);
out = fopen("test/gdtest.jpg", "wb");
if (!out) {
fprintf(stderr, "Can't create file test/gdtest.jpg.\n");
exit(1);
}
gdImageJpeg(im, out, -1);
fclose(out);
in = fopen("test/gdtest.jpg", "rb");
if (!in) {
fprintf(stderr, "Can't open file test/gdtest.jpg.\n");
exit(1);
}
im2 = gdImageCreateFromJpeg(in);
fclose(in);
if (!im2) {
fprintf(stderr, "gdImageCreateFromJpeg failed.\n");
exit(1);
}
gdImageDestroy(im2);
printf("Created test/gdtest.jpg successfully. Compare this image\n"
"to the input image manually. Some difference must be\n"
"expected as JPEG is a lossy file format.\n");
gdImageDestroy(im);
gdImageDestroy(ref);

View File

@ -1,30 +1,35 @@
<HTML>
<HEAD>
<TITLE>gd 1.7.3</TITLE>
<TITLE>gd 1.8</TITLE>
</HEAD>
<BODY>
<!-- BANNER HERE -->
<H1>gd 1.7.3</H1>
<H1>gd 1.8</H1>
<H2>A graphics library for fast image creation</H2>
<H2>Follow this link to the
<A HREF="http://www.boutell.com/gd/">latest version
of this document</A>.</H2>
<blockquote>
<strong>HEY! READ THIS!</strong>
gd 1.7.3 creates PNG images, not GIF images. This is a good thing.
PNG is a more compact format, and full compression is available.
Existing code will need modification to call gdImagePng instead
gd 1.8 creates PNG, JPEG and WBMP images, not GIF images. This is a good
thing. PNG is a more compact format, and full compression is
available. JPEG works well with photographic images, and is still
more compatible with the major Web browsers than even PNG is. WBMP is
intended for wireless devices (not regular web browsers). Existing
code will need modification to call gdImagePng or gdImageJpeg instead
of gdImageGif. <strong>Please do not ask us to send you the old GIF
version of GD.</strong> Unisys holds a patent on the LZW compression
algorithm, which is used in fully compressed GIF images. We are
still investigating the legal issues surrounding various
alternative means of producing a valid GIF file.
algorithm, which is used in fully compressed GIF images. The best
solution is to move to legally unencumbered, well-compressed,
modern image formats such as PNG and JPEG as soon as possible.
<p>
gd 1.7.3 <strong>requires</strong> that the following libraries
gd 1.8 <strong>requires</strong> that the following libraries
also be installed:
<p>
libpng
<p>
jpeg-6b or later
<p>
zlib
<p>
If you want to use the TrueType font support, you must also
@ -46,6 +51,7 @@ information. Thank you!
<H3>Table of Contents</H3>
<UL>
<LI><A HREF="#notice">Credits and license terms</A>
<LI><A HREF="#whatsnew1.8">What's new in version 1.8?</A>
<LI><A HREF="#whatsnew1.7.3">What's new in version 1.7.3?</A>
<LI><A HREF="#whatsnew1.7.2">What's new in version 1.7.2?</A>
<LI><A HREF="#whatsnew1.7.1">What's new in version 1.7.1?</A>
@ -83,19 +89,25 @@ COPYRIGHT STATEMENT FOLLOWS THIS LINE
</pre>
<blockquote>
Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, by Cold Spring
Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000 by Cold Spring
Harbor Laboratory. Funded under Grant P41-RR02188 by the National
Institutes of Health.
<P>
Portions copyright 1996, 1997, 1998, 1999, by Boutell.Com, Inc.
Portions copyright 1996, 1997, 1998, 1999, 2000 by Boutell.Com, Inc.
<p>
Portions relating to GD2 format copyright 1999 Philip Warner.
Portions relating to GD2 format copyright 1999, 2000 Philip Warner.
<p>
Portions relating to PNG copyright 1999, Greg Roelofs.
Portions relating to PNG copyright 1999, 2000 Greg Roelofs.
<p>
Portions relating to libttf copyright 1999, John Ellson (ellson@lucent.com).
Portions relating to libttf copyright 1999, 2000 John Ellson (ellson@lucent.com).
<p>
<strong>Permission has been granted to copy and distribute gd in any
Portions relating to JPEG copyright 2000, Doug Becker and copyright (C)
1994-1998, Thomas G. Lane. This software is based in part on the work
of the Independent JPEG Group.
<p>
Portions relating to WBMP copyright 2000 Maurice Szmurlo.
<p>
<strong>Permission has been granted to copy, distribute and modify gd in any
context without fee, including a commercial application, provided that this notice
is present in user-accessible supporting documentation.</strong>
<p>
@ -111,7 +123,7 @@ including but not limited to implied warranties of merchantability and
fitness for a particular purpose, with respect to this code and accompanying
documentation.
<p>
Although their code does not appear in gd 1.7.3, the authors wish to
Although their code does not appear in gd 1.8, the authors wish to
thank David Koblas, David Rowley, and Hutchison Avenue Software
Corporation for their prior contributions.
</blockquote>
@ -123,8 +135,8 @@ END OF COPYRIGHT STATEMENT
gd is a graphics library. It allows your code to quickly
draw images complete with lines, arcs, text, multiple
colors, cut and paste from other images, and flood fills, and
write out the result as a .PNG file. This is particularly
useful in World Wide Web applications, where .PNG is one
write out the result as a PNG or JPEG file. This is particularly
useful in World Wide Web applications, where PNG and JPEG are two
of the formats accepted for inline images by most browsers.
<P>
gd is not a paint program.
@ -136,8 +148,8 @@ gd does not provide for every possible desirable graphics
operation. It is not necessary or desirable for gd to become
a kitchen-sink graphics package, but version 1.7.3 incorporates
most of the commonly requested features for an 8-bit 2D package.
Support for truecolor images, JPEG and
truecolor PNG is planned for version 2.0.
Support for truecolor images, including truecolor JPEG and PNG,
is planned for version 2.0.
<P>
<A NAME="gdother"><H3>What if I want to use another programming
language?</h3></A>
@ -152,6 +164,9 @@ gd can be used from Tcl with John Ellson's
<a href=http://www.tcltk.com/ftp/ellson/>Gdtclft</a>
dynamically loaded extension package.
(Gdtclft2.0 or later is needed for gd-1.6 and up with PNG output.)
<h4>Pascal</h4>
Pascal enthusiasts should look into Michael Bradbury's
<a href="http://www.elj.com/dev/free-pascal/gdfp/">gdfp</a> package.
<h4>Any Language</h4>
There are, at the moment, at least three simple interpreters that
perform gd operations. You can output the desired commands to a simple
@ -163,6 +178,27 @@ These packages have not been updated to gd 1.6 and up as of this writing.
<li><a href="http://s27w007.pswfs.gov/tgd/">tgd</a>, by Bradley K. Sherman
<li><a href="http://www.unimelb.edu.au/fly/fly.html">fly</a>, by Martin Gleeson
</ul>
<P><A NAME="whatsnew1.8"><H3>What's new in version 1.8?</H3></A>
<ul>
<li>Support for JPEG output, courtesy of Doug Becker
<li>A link to Michael Bradbery's Pascal wrapper
<li>Support for WBMP output, courtesy of Maurice Szmurlo
<li>gdImageColorClosestHWB function based on hue, whiteness, blackness,
superior to the regular gdImageColorClosest function, courtesy
of Philip Warner
<li>License clarification: yes, you can modify gd
</ul>
<h4>Additional JPEG Information</h4>
Support for reading and writing JPEG-format images is courtesy
of Doug Becker and the Independent JPEG Group / Thomas G. Lane. You
can get the latest version of the IJG JPEG software from <A
HREF="ftp://ftp.uu.net/graphics/jpeg/">ftp://ftp.uu.net/graphics/jpeg/</A>
(e.g., the <A
HREF="ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz">jpegsrc.v6b.tar.gz</A>
file). You <strong>must</strong> use
version 6b or later of the IJG JPEG software. You might also consult
the <A HREF="http://www.faqs.org/faqs/jpeg-faq/">JPEG FAQ</A> at
<A HREF="http://www.faqs.org/faqs/jpeg-faq/">http://www.faqs.org/faqs/jpeg-faq/</A>.
<P><A NAME="whatsnew1.7.3"><H3>What's new in version 1.7.3?</H3></A>
Another attempt at Makefile fixes to permit
linking with all libraries required on platforms with order-
@ -295,7 +331,7 @@ Version 1.5 featured the following changes:
<br>gdImageGd2, gdImageCreateFromGd2 - Support for new format
<br>gdImageCopyMerge - Merges two images (useful to highlight part of an image)
<br>gdImageCopyMergeGray - Similar to gdImageCopyMerge, but tries to preserve source image hue.
<br>gdImagePngPtr, gdImageGdPtr, gdImageGd2Ptr - return memort blocks for each type of image.
<br>gdImagePngPtr, gdImageJpegPtr, gdImageWBMPPtr, gdImageGdPtr, gdImageGd2Ptr - return memort blocks for each type of image.
<br>gdImageCreateFromPngCtx, gdImageCreateFromGdCtx, gdImageCreateFromGd2Ctx, gdImageCreateFromGd2PartCtx - Support for new I/O context.
</dl>
@ -403,13 +439,13 @@ newsgroups relevant to your particular system.
<A NAME="getgd"><H3>How do I get gd?</H3></A>
<h4>By HTTP</h4>
<ul>
<li><a href="http://www.boutell.com/gd/http/gd-1.7.3.tar.gz">Gzipped Tar File (Unix)</a>
<li><a href="http://www.boutell.com/gd/http/gd-1.7.3.zip">.ZIP File (Windows)</a>
<li><a href="http://www.boutell.com/gd/http/gd-1.8.tar.gz">Gzipped Tar File (Unix)</a>
<li><a href="http://www.boutell.com/gd/http/gd-1.8.zip">.ZIP File (Windows)</a>
</ul>
<h4>By FTP</h4>
<ul>
<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-1.7.3.tar.gz">Gzipped Tar File (Unix)</a>
<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-1.7.3.zip">.ZIP File (Windows)</a>
<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-1.8.tar.gz">Gzipped Tar File (Unix)</a>
<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-1.8.zip">.ZIP File (Windows)</a>
</ul>
<P>
<A NAME="buildgd"><H3>How do I build gd?</H3></A>
@ -420,10 +456,10 @@ downloaded. If you are not familiar with <code>tar</code> and
consult with an experienced user of your system. Sorry, we cannot
answer questions about basic Internet skills.
<p>
Unpacking the archive will produce a directory called "gd-1.7.3".
Unpacking the archive will produce a directory called "gd-1.8".
<p>
<h4>For Unix</h4>
<code>cd</code> to the 1.7.3 directory. Edit the Makefile with
<code>cd</code> to the 1.8 directory. Edit the Makefile with
your preferred text editor and make any necessary changes to the
settings at the top, especially if you want Xpm or TrueType support.
Next, type "make". If you are the system administrator, and you
@ -432,6 +468,10 @@ also wish to type "make install".
<p>
If you get errors, edit the Makefile again, paying special attention
to the INCLUDEDIRS and LIBDIRS settings.
<p>
IF YOU GET LINKER ERRORS, TRY JUGGLING THE ORDER OF THE -l DIRECTIVES
IN THE MAKEFILE. Some platforms may prefer that the libraries be listed
in the opposite order.
<h4>For Windows, Mac, Et Cetera</h4>
Create a project using your favorite programming environment.
Copy all of the gd files to the project directory. Add <code>gd.c</code>
@ -459,7 +499,7 @@ Look at demoin.png to see the original space shuttle
image which was scaled and copied into the output image.
<P>
<A NAME="basics"><H3>gd basics: using gd in your program</H3></A>
gd lets you create PNG images on the fly. To use gd in your
gd lets you create PNG or JPEG images on the fly. To use gd in your
program, include the file gd.h, and link with the libgd.a
library produced by "make libgd.a", under Unix. Under other
operating systems you will add gd.c to your own project.
@ -487,8 +527,8 @@ it demonstrates additional features!)</strong>
int main() {
/* Declare the image */
<A HREF="#gdImagePtr">gdImagePtr</A> im;
/* Declare an output file */
FILE *out;
/* Declare output files */
FILE *pngout, *jpegout;
/* Declare color indexes */
int black;
int white;
@ -510,13 +550,21 @@ int main() {
/* Open a file for writing. "wb" means "write binary", important
under MSDOS, harmless under Unix. */
out = fopen("test.png", "wb");
pngout = fopen("test.png", "wb");
/* Output the image to the disk file. */
<A HREF="#gdImagePng">gdImagePng</A>(im, out);
/* Do the same for a JPEG-format file. */
jpegout = fopen("test.jpg", "wb");
/* Close the file. */
fclose(out);
/* Output the image to the disk file in PNG format. */
<A HREF="#gdImagePng">gdImagePng</A>(im, pngout);
/* Output the same image in JPEG format, using the default
JPEG quality setting. */
<A HREF="#gdImageJpeg">gdImageJpeg</A>(im, jpegout, -1);
/* Close the files. */
fclose(pngout);
fclose(jpegout);
/* Destroy the image in memory. */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
@ -525,7 +573,7 @@ int main() {
When executed, this program creates an image, allocates
two colors (the first color allocated becomes the background
color), draws a diagonal line (note that 0, 0 is the upper
left corner), writes the image to a PNG file, and
left corner), writes the image to PNG and JPEG files, and
destroys the image.
<P>
The above example program should
@ -686,6 +734,33 @@ im = gdImageCreate(64, 64);
/* ... Use the image ... */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
</PRE>
<DT><A NAME="gdImageCreateFromJpeg">gdImageCreateFromJpeg(FILE *in)</A>
<strong>(FUNCTION)</strong>
<br>
<A NAME="gdImageCreateFromJpegCtx">gdImageCreateFromJpegCtx(FILE *in)</A>
<strong>(FUNCTION)</strong>
<p>
<DD>
gdImageCreateFromJpeg is called to load images from JPEG format files.
Invoke gdImageCreateFromJpeg with an already opened pointer to a file
containing the desired image.
gdImageCreateFromJpeg
returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL
if unable to load the image (most often because the file is corrupt or
does not contain a JPEG image). gdImageCreateFromPng does <em>not</em>
close the file. You can inspect the sx and sy members of the
image to determine its size. The image must eventually be destroyed
using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
<PRE>
<A HREF="#gdImagePtr">gdImagePtr</A> im;
... inside a function ...
FILE *in;
in = fopen("myjpeg.jpg", "rb");
im = gdImageCreateFromJpeg(in);
fclose(in);
/* ... Use the image ... */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
</PRE>
<DT><A NAME="gdImageCreateFromPng">gdImageCreateFromPng(FILE *in)</A>
<strong>(FUNCTION)</strong>
<BR><A NAME="gdImageCreateFromPngCtx">gdImageCreateFromPngCtx(<a href=#gdioctx>gdIOCtx</a> *in)</A>
@ -763,7 +838,7 @@ Invoke gdImageCreateFromGd
with an already opened pointer to a file containing the desired image
in the <A HREF="#gdformat">gd file format</A>, which is specific to
gd and intended for very fast loading. (It is <em>not</em> intended for
compression; for compression, use PNG.)
compression; for compression, use PNG or JPEG.)
gdImageCreateFromGd
returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL
if unable to load the image (most often because the file is corrupt or
@ -889,6 +964,61 @@ im = <A HREF="#gdImageCreate">gdImageCreate</A>(10, 10);
/* Now destroy it */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
</PRE>
<DT><A NAME="gdImageJpeg">
void gdImageJpeg(gdImagePtr im, FILE *out, int quality)</A>
<STRONG>(FUNCTION)</STRONG><BR>
void gdImageJpegCtx(gdImagePtr im, gdIOCtx *out, int quality)</A>
<STRONG>(FUNCTION)</STRONG><BR>
<DD>
gdImageJpeg outputs the specified image to the specified
file in JPEG format. The file must be open for writing. Under MSDOS
and all versions of Windows, it is important to use "wb" as opposed
to simply "w" as the mode when opening the file, and under Unix there
is no penalty for doing so. gdImageJpeg does <em>not</em>
close the file; your code must do so.
<P>
If quality is negative, the default IJG JPEG quality value (which
should yield a good general quality / size tradeoff for most
situations) is used. Otherwise, for practical purposes, quality
should be a value in the range 0-95, higher quality values usually
implying both higher quality and larger image sizes.
<P>
If you have set image interlacing using
<A HREF="#gdImageInterlace">gdImageInterlace</A>, this function will
interpret that to mean you wish to output a progressive JPEG. Some
programs (e.g., Web browsers) can display progressive JPEGs
incrementally; this can be useful when browsing over a relatively slow
communications link, for example. Progressive JPEGs can also be
slightly smaller than sequential (non-progressive) JPEGs.
<PRE>
... inside a function ...
<A HREF="#gdImagePtr">gdImagePtr</A> im;
int black, white;
FILE *out;
/* Create the image */
im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
/* Allocate background */
white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
/* Allocate drawing color */
black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
/* Draw rectangle */
<A HREF="#gdImageRectangle">gdImageRectangle</A>(im, 0, 0, 99, 99, black);
/* Open output file in binary mode */
out = fopen("rect.jpg", "wb");
/* Write JPEG using default quality */
gdImageJpeg(im, out, -1);
/* Close file */
fclose(out);
/* Destroy image */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
</PRE>
<DT><A NAME="gdImageJpegPtr">
void* gdImageJpegPtr(gdImagePtr im, int *size)</A>
<STRONG>(FUNCTION)</STRONG>
<DD>Identical to gdImageJpeg except that it returns a pointer to a memory
area with the JPEG data. This memory must be freed by the caller when it is
no longer needed. The 'size' parameter receives the total size of the block
of memory.
<DT><A NAME="gdImagePng">
void gdImagePng(gdImagePtr im, FILE *out)</A>
<STRONG>(FUNCTION)</STRONG>
@ -927,7 +1057,7 @@ void* gdImagePngPtr(gdImagePtr im, int *size)</A>
<STRONG>(FUNCTION)</STRONG>
<DD>Identical to gdImagePng except that it returns a pointer to a memory
area with the PNG data. This memory must be freed by the caller when it is
no longer needed. The 'size' parameter received the total size of the block
no longer needed. The 'size' parameter receives the total size of the block
of memory.
<DT><A NAME="gdImagePngToSink">gdImagePngToSink(gdImagePtr im, gdSinkPtr out)</A>
@ -966,6 +1096,51 @@ void gdImagePng(gdImagePtr im, FILE *out)
gdImagePngToSink(im, &mySink);
}
</pre>
<DT><A NAME="gdImageWBMP">
void gdImageWBMP(gdImagePtr im, int fg, FILE *out)</A>
<BR><A NAME="gdImageWBMPCtx">gdImageWBMPCtx(<a href=#gdioctx>gdIOCtx</a> *out)</A>
<strong>(FUNCTION)</strong><STRONG>(FUNCTION)</STRONG>
<DD>
gdImageWBMP outputs the specified image to the specified
file in WBMP format. The file must be open for writing. Under MSDOS
and all versions of Windows, it is important to use "wb" as opposed
to simply "w" as the mode when opening the file, and under Unix there
is no penalty for doing so. gdImageWBMP does <em>not</em>
close the file; your code must do so.
<p>
<strong>WBMP file support is black and white only. The color index
specified by the fg argument is the "foreground," and only pixels
of this color will be set in the WBMP file.</strong> All other pixels
will be considered "background."
<PRE>
... inside a function ...
<A HREF="#gdImagePtr">gdImagePtr</A> im;
int black, white;
FILE *out;
/* Create the image */
im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
/* Allocate background */
white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
/* Allocate drawing color */
black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
/* Draw rectangle */
<A HREF="#gdImageRectangle">gdImageRectangle</A>(im, 0, 0, 99, 99, black);
/* Open output file in binary mode */
out = fopen("rect.wbmp", "wb");
/* Write WBMP, with black as foreground */
gdImageWBMP(im, black, out);
/* Close file */
fclose(out);
/* Destroy image */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
</PRE>
<DT><A NAME="gdImageWBMPPtr">
void* gdImageWBMPPtr(gdImagePtr im, int *size)</A>
<STRONG>(FUNCTION)</STRONG>
<DD>Identical to gdImageWBMP except that it returns a pointer to a memory
area with the WBMP data. This memory must be freed by the caller when it is
no longer needed. The 'size' parameter receives the total size of the block
of memory.
<DT><A NAME="gdImageGd">
void gdImageGd(gdImagePtr im, FILE *out)</A>
<STRONG>(FUNCTION)</STRONG>
@ -1010,7 +1185,7 @@ void* gdImageGdPtr(gdImagePtr im, int *size)</A>
<STRONG>(FUNCTION)</STRONG>
<DD>Identical to gdImageGd except that it returns a pointer to a memory
area with the GD data. This memory must be freed by the caller when it is
no longer needed. The 'size' parameter received the total size of the block
no longer needed. The 'size' parameter receives the total size of the block
of memory.
<DT><A NAME="gdImageGd2">
@ -1067,7 +1242,7 @@ void* gdImageGd2Ptr(gdImagePtr im, int chunkSize, int fmt, int *size)</A>
<STRONG>(FUNCTION)</STRONG>
<DD>Identical to gdImageGd2 except that it returns a pointer to a memory
area with the GD2 data. This memory must be freed by the caller when it is
no longer needed. The 'size' parameter received the total size of the block
no longer needed. The 'size' parameter receives the total size of the block
of memory.
</DL>
@ -1975,8 +2150,9 @@ return -1 to indicate failure. (This is not uncommon when
working with existing PNG files that already use 256 colors.)
Note that gdImageColorAllocate
does not check for existing colors that match your request;
see <A HREF="#gdImageColorExact">gdImageColorExact</A>
and <A HREF="#gdImageColorClosest">gdImageColorClosest</A>
see <A HREF="#gdImageColorExact">gdImageColorExact</A>,
<A HREF="#gdImageColorClosest">gdImageColorClosest</A> and
<A HREF="#gdImageColorClosest">gdImageColorClosestHWB</A>
for ways to locate existing colors that approximate the
color desired in situations where a new color is not available.
Also see <A HREF="#gdImageColorResolve">gdImageColorResolve</A>,
@ -2041,7 +2217,50 @@ gdImageDashedLine(im, 0, 0, 99, 99, red);
/* Destroy it */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
</PRE>
<DT><A NAME="gdImageColorExact">
<DT><A NAME="gdImageColorClosestHWB">
int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b)</A>
<STRONG>(FUNCTION)</STRONG>
<DD>
gdImageColorClosestHWB searches the colors which have been
defined thus far in the image specified and returns the
index of the color with hue, whiteness and blackness closest to the
requested color. This scheme is typically superior to the
Euclidian distance scheme used by
<a href="#gdImageColorClosest">gdImageColorClosest</a>.
<P>
If no colors have yet been allocated in the image,
gdImageColorClosestHWB returns -1.
<P>
This function is most useful as a backup method for choosing
a drawing color when an image already contains
<A HREF="#gdMaxColors">gdMaxColors</A> (256) colors and
no more can be allocated. (This is not uncommon when
working with existing PNG files that already use many colors.)
See <A HREF="#gdImageColorExact">gdImageColorExact</A>
for a method of locating exact matches only.
<PRE>
... inside a function ...
<A HREF="#gdImagePtr">gdImagePtr</A> im;
FILE *in;
int red;
/* Let's suppose that photo.png is a scanned photograph with
many colors. */
in = fopen("photo.png", "rb");
im = <A HREF="#gdImageCreateFromPng">gdImageCreateFromPng</A>(in);
fclose(in);
/* Try to allocate red directly */
red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
/* If we fail to allocate red... */
if (red == (-1)) {
/* Find the <em>closest</em> color instead. */
red = gdImageColorClosestHWB(im, 255, 0, 0);
}
/* Draw a dashed line from the upper left corner to the lower right corner */
gdImageDashedLine(im, 0, 0, 99, 99, red);
/* ... Do something with the image, such as saving it to a file... */
/* Destroy it */
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
</PRE><DT><A NAME="gdImageColorExact">
int gdImageColorExact(gdImagePtr im, int r, int g, int b)</A>
<STRONG>(FUNCTION)</STRONG>
<DD>
@ -2145,7 +2364,7 @@ gdImageGetInterlaced is a macro which returns true (1)
if the image is interlaced, false (0) if not.
Use this macro to obtain this information; do not
access the structure directly.
See <A NAME="gdImageInterlace">gdImageInterlace</A> for
See <A HREF="#gdImageInterlace">gdImageInterlace</A> for
a means of interlacing images.
<DT><A NAME="gdImageGetTransparent">
int gdImageGetTransparent(gdImagePtr im)</A>
@ -2199,7 +2418,9 @@ void gdImageColorTransparent(gdImagePtr im, int color)</A>
gdImageColorTransparent sets the transparent color index
for the specified image to the specified index. To indicate
that there should be <em>no</em> transparent color, invoke
gdImageColorTransparent with a color index of -1.
gdImageColorTransparent with a color index of -1. Note that
JPEG images do not support transparency, so this setting has no effect
when writing JPEG images.
<P>
The color index used should be an index
allocated by <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>,
@ -2207,10 +2428,11 @@ whether explicitly invoked by your code or implicitly
invoked by loading an image.
In order to ensure that your image has a reasonable appearance
when viewed by users who do not have transparent background
capabilities, be sure to give reasonable RGB values to the
capabilities (or when you are writing a JPEG-format file, which does
not support transparency), be sure to give reasonable RGB values to the
color you allocate for use as a transparent color,
<em>even though it will be transparent on systems
that support transparency</em>.
that support PNG transparency</em>.
<PRE>
... inside a function ...
<A HREF="#gdImagePtr">gdImagePtr</A> im;
@ -2400,7 +2622,7 @@ gdImageCopyMergeGray(im_out, im_in, 100, 200, 0, 0, 30, 50, 50);
<DT><A NAME="gdImagePaletteCopy">void gdImagePaletteCopy(gdImagePtr dst, gdImagePtr src)
<STRONG> (FUNCTION)</STRONG>
<DD>
Copies a palette from one image to another, doing it's best to match the colors in the target image
Copies a palette from one image to another, attempting to match the colors in the target image
to the colors
in the source palette.
</DL>
@ -2426,20 +2648,27 @@ gdImageInterlace is used to determine whether an image should be stored
in a linear fashion, in which lines will appear on the display from
first to last, or in an interlaced fashion, in which the image
will "fade in" over several passes. By default, images are not
interlaced.
interlaced. (When writing JPEG images, interlacing implies generating
progressive JPEG files, which are represented as a series of scans of
increasing quality. Noninterlaced gd images result in regular
[sequential] JPEG data streams.)
<P>
A nonzero value for the interlace argument turns on interlace;
a zero value turns it off. Note that interlace has no effect
on other functions, and has no meaning unless you save the
image in PNG format; the gd and xbm formats do not support
image in PNG or JPEG format; the gd and xbm formats do not support
interlace.
<P>
When a PNG is loaded with <A HREF="#gdImageCreateFromPng">gdImageCreateFromPng
</A>, interlace will be set according to the setting in the PNG file.
When a PNG is loaded with
<A HREF="#gdImageCreateFromPng">gdImageCreateFromPng</A> or a JPEG is
loaded with
<A HREF="#gdImageCreateFromJpeg">gdImageCreateFromJpeg</A>, interlace
will be set according to the setting in the PNG or JPEG file.
<P>
Note that many PNG viewers and web browsers do <em>not</em> support
interlace. However, the interlaced PNG should still display; it
will simply appear all at once, just as other images do.
Note that many PNG and JPEG viewers and web browsers do <em>not</em>
support interlace or the incremental display of progressive
JPEGs. However, the interlaced PNG or progressive JPEG should still
display; it will simply appear all at once, just as other images do.
<PRE>
gdImagePtr im;
FILE *out;
@ -2449,7 +2678,7 @@ FILE *out;
gdImageInterlace(im, 1);
/* And open an output file */
out = fopen("test.png", "wb");
/* And save the image */
/* And save the image -- could also use <A HREF="#gdImageJpeg">gdImageJpeg</A> */
<A HREF="#gdImagePng">gdImagePng</A>(im, out);
fclose(out);
<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
@ -2539,7 +2768,7 @@ see <A HREF="gdImageColorTransparent">gdImageColorTransparent</A>.
</DL>
<A NAME="gdformat"><H3>About the additional .gd image file format</H3></A>
In addition to reading and writing the PNG format and reading the
In addition to reading and writing the PNG and JPEG formats and reading the
X Bitmap format, gd has the capability to read and write its
own ".gd" format. This format is <em>not</em> intended for
general purpose use and should never be used to distribute
@ -2567,7 +2796,7 @@ images. It is a compressed format allowing pseudo-random access
to large image files. Its purpose is solely to
allow very fast loading of <strong>parts</strong> of images
If you are experiencing
performance problems when loading large, fixed PNG images your
performance problems when loading large, fixed PNG or JPEG images your
program needs to produce its output images, you may wish
to examine the functions <A HREF="#gdImageCreateFromGd2">
gdImageCreateFromGd2</A>, <A HREF="#gdImageCreateFromGd2Part">
@ -2660,6 +2889,7 @@ Be sure to read this manual carefully first.
<A HREF="#gdImageCreateFromGd">gdImageCreateFromGd</A> |
<A HREF="#gdImageCreateFromGd2">gdImageCreateFromGd2</A> |
<A HREF="#gdImageCreateFromGd2Part">gdImageCreateFromGd2Part</A> |
<A HREF="#gdImageCreateFromJpeg">gdImageCreateFromJpeg</A> |
<A HREF="#gdImageCreateFromPng">gdImageCreateFromPng</A> |
<A HREF="#gdImageCreateFromPngSource">gdImageCreateFromPngSource</A> |
<A HREF="#gdImageCreateFromXbm">gdImageCreateFromXbm</A> |
@ -2676,6 +2906,7 @@ Be sure to read this manual carefully first.
<A HREF="#gdImageGetTransparent">gdImageGetTransparent</A> |
<A HREF="#gdImageGreen">gdImageGreen</A> |
<A HREF="#gdImageInterlace">gdImageInterlace</A> |
<A HREF="#gdImageJpeg">gdImageJpeg</A> |
<A HREF="#gdImageLine">gdImageLine</A> |
<A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A> |
<A HREF="#gdImagePaletteCopy">gdImagePaletteCopy</A> |
@ -2683,6 +2914,7 @@ Be sure to read this manual carefully first.
<A HREF="#gdImagePngToSink">gdImagePngToSink</A> |
<A HREF="#gdImagePolygon">gdImagePolygon</A> |
<A HREF="#gdImagePtr">gdImagePtr</A> |
<A HREF="#gdImageWBMP">gdImageWBMP</A> |
<A HREF="#gdImageRectangle">gdImageRectangle</A> |
<A HREF="#gdImageRed">gdImageRed</A> |
<A HREF="#gdImageSetBrush">gdImageSetBrush</A> |
@ -2694,6 +2926,7 @@ Be sure to read this manual carefully first.
<A HREF="#gdImageStringTTF">gdImageStringTTF</A> |
<A HREF="#gdImageStringUp">gdImageStringUp</A> |
<A HREF="#gdImageStringUp">gdImageStringUp16</A> |
<A HREF="#gdImageWBMP">gdImageWBMP</A> |
<A HREF="#gdMaxColors">gdMaxColors</A> |
<A HREF="#gdPoint">gdPoint</A> |
<A HREF="#gdStyled">gdStyled</A> |

View File

@ -1,23 +1,29 @@
gd 1.7.3
gd 1.8
A graphics library for fast image creation
Follow this link to the latest version of this document.
_HEY! READ THIS!_ gd 1.7.3 creates PNG images, not GIF images. This
is a good thing. PNG is a more compact format, and full compression
is available. Existing code will need modification to call
gdImagePng instead of gdImageGif. _Please do not ask us to send you
the old GIF version of GD._ Unisys holds a patent on the LZW
compression algorithm, which is used in fully compressed GIF
images. We are still investigating the legal issues surrounding
various alternative means of producing a valid GIF file.
_HEY! READ THIS!_ gd 1.8 creates PNG, JPEG and WBMP images, not GIF
images. This is a good thing. PNG is a more compact format, and
full compression is available. JPEG works well with photographic
images, and is still more compatible with the major Web browsers
than even PNG is. WBMP is intended for wireless devices (not
regular web browsers). Existing code will need modification to call
gdImagePng or gdImageJpeg instead of gdImageGif. _Please do not ask
us to send you the old GIF version of GD._ Unisys holds a patent on
the LZW compression algorithm, which is used in fully compressed
GIF images. The best solution is to move to legally unencumbered,
well-compressed, modern image formats such as PNG and JPEG as soon
as possible.
gd 1.7.3 _requires_ that the following libraries also be installed:
gd 1.8 _requires_ that the following libraries also be installed:
libpng
jpeg-6b or later
zlib
If you want to use the TrueType font support, you must also install
@ -36,6 +42,7 @@ Follow this link to the latest version of this document.
Table of Contents
* Credits and license terms
* What's new in version 1.8?
* What's new in version 1.7.3?
* What's new in version 1.7.2?
* What's new in version 1.7.1?
@ -69,22 +76,29 @@ Follow this link to the latest version of this document.
COPYRIGHT STATEMENT FOLLOWS THIS LINE
Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, by Cold
Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000 by Cold
Spring Harbor Laboratory. Funded under Grant P41-RR02188 by the
National Institutes of Health.
Portions copyright 1996, 1997, 1998, 1999, by Boutell.Com, Inc.
Portions copyright 1996, 1997, 1998, 1999, 2000 by Boutell.Com,
Inc.
Portions relating to GD2 format copyright 1999 Philip Warner.
Portions relating to GD2 format copyright 1999, 2000 Philip Warner.
Portions relating to PNG copyright 1999, Greg Roelofs.
Portions relating to PNG copyright 1999, 2000 Greg Roelofs.
Portions relating to libttf copyright 1999, John Ellson
Portions relating to libttf copyright 1999, 2000 John Ellson
(ellson@lucent.com).
_Permission has been granted to copy and distribute gd in any
context without fee, including a commercial application, provided
that this notice is present in user-accessible supporting
Portions relating to JPEG copyright 2000, Doug Becker and copyright
(C) 1994-1998, Thomas G. Lane. This software is based in part on
the work of the Independent JPEG Group.
Portions relating to WBMP copyright 2000 Maurice Szmurlo.
_Permission has been granted to copy, distribute and modify gd in
any context without fee, including a commercial application,
provided that this notice is present in user-accessible supporting
documentation._
This does not affect your ownership of the derived work itself, and
@ -99,8 +113,8 @@ COPYRIGHT STATEMENT FOLLOWS THIS LINE
particular purpose, with respect to this code and accompanying
documentation.
Although their code does not appear in gd 1.7.3, the authors wish
to thank David Koblas, David Rowley, and Hutchison Avenue Software
Although their code does not appear in gd 1.8, the authors wish to
thank David Koblas, David Rowley, and Hutchison Avenue Software
Corporation for their prior contributions.
END OF COPYRIGHT STATEMENT
@ -109,10 +123,10 @@ END OF COPYRIGHT STATEMENT
gd is a graphics library. It allows your code to quickly draw images
complete with lines, arcs, text, multiple colors, cut and paste from
other images, and flood fills, and write out the result as a .PNG
file. This is particularly useful in World Wide Web applications,
where .PNG is one of the formats accepted for inline images by most
browsers.
other images, and flood fills, and write out the result as a PNG or
JPEG file. This is particularly useful in World Wide Web applications,
where PNG and JPEG are two of the formats accepted for inline images
by most browsers.
gd is not a paint program. If you are looking for a paint program, you
are looking in the wrong place. If you are not a programmer, you are
@ -122,7 +136,7 @@ END OF COPYRIGHT STATEMENT
It is not necessary or desirable for gd to become a kitchen-sink
graphics package, but version 1.7.3 incorporates most of the commonly
requested features for an 8-bit 2D package. Support for truecolor
images, JPEG and truecolor PNG is planned for version 2.0.
images, including truecolor JPEG and PNG, is planned for version 2.0.
What if I want to use another programming language?
@ -138,6 +152,10 @@ END OF COPYRIGHT STATEMENT
extension package. (Gdtclft2.0 or later is needed for gd-1.6 and up
with PNG output.)
Pascal
Pascal enthusiasts should look into Michael Bradbury's gdfp package.
Any Language
There are, at the moment, at least three simple interpreters that
@ -150,6 +168,25 @@ END OF COPYRIGHT STATEMENT
* tgd, by Bradley K. Sherman
* fly, by Martin Gleeson
What's new in version 1.8?
* Support for JPEG output, courtesy of Doug Becker
* A link to Michael Bradbery's Pascal wrapper
* Support for WBMP output, courtesy of Maurice Szmurlo
* gdImageColorClosestHWB function based on hue, whiteness,
blackness, superior to the regular gdImageColorClosest function,
courtesy of Philip Warner
* License clarification: yes, you can modify gd
Additional JPEG Information
Support for reading and writing JPEG-format images is courtesy of Doug
Becker and the Independent JPEG Group / Thomas G. Lane. You can get
the latest version of the IJG JPEG software from
ftp://ftp.uu.net/graphics/jpeg/ (e.g., the jpegsrc.v6b.tar.gz file).
You _must_ use version 6b or later of the IJG JPEG software. You might
also consult the JPEG FAQ at http://www.faqs.org/faqs/jpeg-faq/.
What's new in version 1.7.3?
Another attempt at Makefile fixes to permit linking with all libraries
@ -295,8 +332,8 @@ END OF COPYRIGHT STATEMENT
of an image)
gdImageCopyMergeGray - Similar to gdImageCopyMerge, but tries
to preserve source image hue.
gdImagePngPtr, gdImageGdPtr, gdImageGd2Ptr - return memort
blocks for each type of image.
gdImagePngPtr, gdImageJpegPtr, gdImageWBMPPtr, gdImageGdPtr,
gdImageGd2Ptr - return memort blocks for each type of image.
gdImageCreateFromPngCtx, gdImageCreateFromGdCtx,
gdImageCreateFromGd2Ctx, gdImageCreateFromGd2PartCtx - Support
for new I/O context.
@ -420,11 +457,11 @@ END OF COPYRIGHT STATEMENT
(Windows), please consult with an experienced user of your system.
Sorry, we cannot answer questions about basic Internet skills.
Unpacking the archive will produce a directory called "gd-1.7.3".
Unpacking the archive will produce a directory called "gd-1.8".
For Unix
cd to the 1.7.3 directory. Edit the Makefile with your preferred text
cd to the 1.8 directory. Edit the Makefile with your preferred text
editor and make any necessary changes to the settings at the top,
especially if you want Xpm or TrueType support. Next, type "make". If
you are the system administrator, and you wish to make the gd library
@ -433,6 +470,10 @@ END OF COPYRIGHT STATEMENT
If you get errors, edit the Makefile again, paying special attention
to the INCLUDEDIRS and LIBDIRS settings.
IF YOU GET LINKER ERRORS, TRY JUGGLING THE ORDER OF THE -l DIRECTIVES
IN THE MAKEFILE. Some platforms may prefer that the libraries be
listed in the opposite order.
For Windows, Mac, Et Cetera
Create a project using your favorite programming environment. Copy all
@ -460,10 +501,10 @@ END OF COPYRIGHT STATEMENT
gd basics: using gd in your program
gd lets you create PNG images on the fly. To use gd in your program,
include the file gd.h, and link with the libgd.a library produced by
"make libgd.a", under Unix. Under other operating systems you will add
gd.c to your own project.
gd lets you create PNG or JPEG images on the fly. To use gd in your
program, include the file gd.h, and link with the libgd.a library
produced by "make libgd.a", under Unix. Under other operating systems
you will add gd.c to your own project.
If you want to use the provided fonts, include gdfontt.h, gdfonts.h,
gdfontmb.h, gdfontl.h and/or gdfontg.h. For more impressive results,
@ -486,8 +527,8 @@ END OF COPYRIGHT STATEMENT
int main() {
/* Declare the image */
gdImagePtr im;
/* Declare an output file */
FILE *out;
/* Declare output files */
FILE *pngout, *jpegout;
/* Declare color indexes */
int black;
int white;
@ -509,13 +550,21 @@ int main() {
/* Open a file for writing. "wb" means "write binary", important
under MSDOS, harmless under Unix. */
out = fopen("test.png", "wb");
pngout = fopen("test.png", "wb");
/* Output the image to the disk file. */
gdImagePng(im, out);
/* Do the same for a JPEG-format file. */
jpegout = fopen("test.jpg", "wb");
/* Close the file. */
fclose(out);
/* Output the image to the disk file in PNG format. */
gdImagePng(im, pngout);
/* Output the same image in JPEG format, using the default
JPEG quality setting. */
gdImageJpeg(im, jpegout, -1);
/* Close the files. */
fclose(pngout);
fclose(jpegout);
/* Destroy the image in memory. */
gdImageDestroy(im);
@ -524,7 +573,7 @@ int main() {
When executed, this program creates an image, allocates two colors
(the first color allocated becomes the background color), draws a
diagonal line (note that 0, 0 is the upper left corner), writes the
image to a PNG file, and destroys the image.
image to PNG and JPEG files, and destroys the image.
The above example program should give you an idea of how the package
works. gd provides many additional functions, which are listed in the
@ -671,6 +720,30 @@ typedef struct {
gdImagePtr im;
im = gdImageCreate(64, 64);
/* ... Use the image ... */
gdImageDestroy(im);
gdImageCreateFromJpeg(FILE *in) _(FUNCTION)_
gdImageCreateFromJpegCtx(FILE *in) _(FUNCTION)_
gdImageCreateFromJpeg is called to load images from JPEG format
files. Invoke gdImageCreateFromJpeg with an already opened
pointer to a file containing the desired image.
gdImageCreateFromJpeg returns a gdImagePtr to the new image, or
NULL if unable to load the image (most often because the file
is corrupt or does not contain a JPEG image).
gdImageCreateFromPng does _not_ close the file. You can inspect
the sx and sy members of the image to determine its size. The
image must eventually be destroyed using gdImageDestroy().
gdImagePtr im;
... inside a function ...
FILE *in;
in = fopen("myjpeg.jpg", "rb");
im = gdImageCreateFromJpeg(in);
fclose(in);
/* ... Use the image ... */
gdImageDestroy(im);
gdImageCreateFromPng(FILE *in) _(FUNCTION)_
@ -742,13 +815,13 @@ static int freadWrapper(void *context, char *buf, int len)
pointer to a file containing the desired image in the gd file
format, which is specific to gd and intended for very fast
loading. (It is _not_ intended for compression; for
compression, use PNG.) gdImageCreateFromGd returns a gdImagePtr
to the new image, or NULL if unable to load the image (most
often because the file is corrupt or does not contain a gd
format image). gdImageCreateFromGd does _not_ close the file.
You can inspect the sx and sy members of the image to determine
its size. The image must eventually be destroyed using
gdImageDestroy().
compression, use PNG or JPEG.) gdImageCreateFromGd returns a
gdImagePtr to the new image, or NULL if unable to load the
image (most often because the file is corrupt or does not
contain a gd format image). gdImageCreateFromGd does _not_
close the file. You can inspect the sx and sy members of the
image to determine its size. The image must eventually be
destroyed using gdImageDestroy().
... inside a function ...
@ -858,14 +931,65 @@ im = gdImageCreate(10, 10);
/* Now destroy it */
gdImageDestroy(im);
void gdImagePng(gdImagePtr im, FILE *out) _(FUNCTION)_
gdImagePng outputs the specified image to the specified file in
PNG format. The file must be open for writing. Under MSDOS and
all versions of Windows, it is important to use "wb" as opposed
to simply "w" as the mode when opening the file, and under Unix
there is no penalty for doing so. gdImagePng does _not_ close
the file; your code must do so.
void gdImageJpeg(gdImagePtr im, FILE *out, int quality) _(FUNCTION)_
void gdImageJpegCtx(gdImagePtr im, gdIOCtx *out, int quality)
_(FUNCTION)_
gdImageJpeg outputs the specified image to the specified file in JPEG
format. The file must be open for writing. Under MSDOS and all
versions of Windows, it is important to use "wb" as opposed to simply
"w" as the mode when opening the file, and under Unix there is no
penalty for doing so. gdImageJpeg does _not_ close the file; your code
must do so.
If quality is negative, the default IJG JPEG quality value (which
should yield a good general quality / size tradeoff for most
situations) is used. Otherwise, for practical purposes, quality should
be a value in the range 0-95, higher quality values usually implying
both higher quality and larger image sizes.
If you have set image interlacing using gdImageInterlace, this
function will interpret that to mean you wish to output a progressive
JPEG. Some programs (e.g., Web browsers) can display progressive JPEGs
incrementally; this can be useful when browsing over a relatively slow
communications link, for example. Progressive JPEGs can also be
slightly smaller than sequential (non-progressive) JPEGs.
... inside a function ...
gdImagePtr im;
int black, white;
FILE *out;
/* Create the image */
im = gdImageCreate(100, 100);
/* Allocate background */
white = gdImageColorAllocate(im, 255, 255, 255);
/* Allocate drawing color */
black = gdImageColorAllocate(im, 0, 0, 0);
/* Draw rectangle */
gdImageRectangle(im, 0, 0, 99, 99, black);
/* Open output file in binary mode */
out = fopen("rect.jpg", "wb");
/* Write JPEG using default quality */
gdImageJpeg(im, out, -1);
/* Close file */
fclose(out);
/* Destroy image */
gdImageDestroy(im);
void* gdImageJpegPtr(gdImagePtr im, int *size) _(FUNCTION)_
Identical to gdImageJpeg except that it returns a pointer to a memory
area with the JPEG data. This memory must be freed by the caller when
it is no longer needed. The 'size' parameter receives the total size
of the block of memory.
void gdImagePng(gdImagePtr im, FILE *out) _(FUNCTION)_
gdImagePng outputs the specified image to the specified file in PNG
format. The file must be open for writing. Under MSDOS and all
versions of Windows, it is important to use "wb" as opposed to simply
"w" as the mode when opening the file, and under Unix there is no
penalty for doing so. gdImagePng does _not_ close the file; your code
must do so.
... inside a function ...
gdImagePtr im;
@ -889,29 +1013,27 @@ fclose(out);
gdImageDestroy(im);
void* gdImagePngPtr(gdImagePtr im, int *size) _(FUNCTION)_
Identical to gdImagePng except that it returns a pointer to a
memory area with the PNG data. This memory must be freed by the
caller when it is no longer needed. The 'size' parameter
received the total size of the block of memory.
Identical to gdImagePng except that it returns a pointer to a memory
area with the PNG data. This memory must be freed by the caller when
it is no longer needed. The 'size' parameter receives the total size
of the block of memory.
gdImagePngToSink(gdImagePtr im, gdSinkPtr out) _(FUNCTION)_
gdImagePngToSink is called to write a PNG to a data "sink"
(destination) other than a file. Usage is very similar to the
gdImagePng function, except that the programmer provides a
custom data sink.
The programmer must write an output function which accepts a
context pointer, a buffer, and a number of bytes to be written
as arguments. This function must write the number of bytes
requested and return that number, unless an error has occurred,
in which case the function should return -1. The programmer
then creates a gdSink structure and sets the sink pointer to
the output function and the context pointer to any value which
is useful to the programmer.
The example below implements gdImagePng by creating a custom
data source and invoking gdImagePngFromSink.
gdImagePngToSink is called to write a PNG to a data "sink"
(destination) other than a file. Usage is very similar to the
gdImagePng function, except that the programmer provides a custom data
sink.
The programmer must write an output function which accepts a context
pointer, a buffer, and a number of bytes to be written as arguments.
This function must write the number of bytes requested and return that
number, unless an error has occurred, in which case the function
should return -1. The programmer then creates a gdSink structure and
sets the sink pointer to the output function and the context pointer
to any value which is useful to the programmer.
The example below implements gdImagePng by creating a custom data
source and invoking gdImagePngFromSink.
static int stdioSink(void *context, char *buffer, int len)
{
@ -926,19 +1048,58 @@ void gdImagePng(gdImagePtr im, FILE *out)
gdImagePngToSink(im, &mySink);
}
void gdImageWBMP(gdImagePtr im, int fg, FILE *out)
gdImageWBMPCtx(gdIOCtx *out) _(FUNCTION)__(FUNCTION)_
gdImageWBMP outputs the specified image to the specified file in WBMP
format. The file must be open for writing. Under MSDOS and all
versions of Windows, it is important to use "wb" as opposed to simply
"w" as the mode when opening the file, and under Unix there is no
penalty for doing so. gdImageWBMP does _not_ close the file; your code
must do so.
_WBMP file support is black and white only. The color index specified
by the fg argument is the "foreground," and only pixels of this color
will be set in the WBMP file._ All other pixels will be considered
"background."
... inside a function ...
gdImagePtr im;
int black, white;
FILE *out;
/* Create the image */
im = gdImageCreate(100, 100);
/* Allocate background */
white = gdImageColorAllocate(im, 255, 255, 255);
/* Allocate drawing color */
black = gdImageColorAllocate(im, 0, 0, 0);
/* Draw rectangle */
gdImageRectangle(im, 0, 0, 99, 99, black);
/* Open output file in binary mode */
out = fopen("rect.wbmp", "wb");
/* Write WBMP, with black as foreground */
gdImageWBMP(im, black, out);
/* Close file */
fclose(out);
/* Destroy image */
gdImageDestroy(im);
void* gdImageWBMPPtr(gdImagePtr im, int *size) _(FUNCTION)_
Identical to gdImageWBMP except that it returns a pointer to a memory
area with the WBMP data. This memory must be freed by the caller when
it is no longer needed. The 'size' parameter receives the total size
of the block of memory.
void gdImageGd(gdImagePtr im, FILE *out) _(FUNCTION)_
gdImageGd outputs the specified image to the specified file in
the gd image format. The file must be open for writing. Under
MSDOS and all versions of Windows, it is important to use "wb"
as opposed to simply "w" as the mode when opening the file, and
under Unix there is no penalty for doing so. gdImagePng does
_not_ close the file; your code must do so.
The gd image format is intended for fast reads and writes of
images your program will need frequently to build other images.
It is _not_ a compressed format, and is not intended for
general use.
gdImageGd outputs the specified image to the specified file in the gd
image format. The file must be open for writing. Under MSDOS and all
versions of Windows, it is important to use "wb" as opposed to simply
"w" as the mode when opening the file, and under Unix there is no
penalty for doing so. gdImagePng does _not_ close the file; your code
must do so.
The gd image format is intended for fast reads and writes of images
your program will need frequently to build other images. It is _not_ a
compressed format, and is not intended for general use.
... inside a function ...
gdImagePtr im;
@ -962,34 +1123,31 @@ fclose(out);
gdImageDestroy(im);
void* gdImageGdPtr(gdImagePtr im, int *size) _(FUNCTION)_
Identical to gdImageGd except that it returns a pointer to a
memory area with the GD data. This memory must be freed by the
caller when it is no longer needed. The 'size' parameter
received the total size of the block of memory.
Identical to gdImageGd except that it returns a pointer to a memory
area with the GD data. This memory must be freed by the caller when it
is no longer needed. The 'size' parameter receives the total size of
the block of memory.
void gdImageGd2(gdImagePtr im, FILE *out, int chunkSize, int fmt)
_(FUNCTION)_
gdImageGd2 outputs the specified image to the specified file in
the gd2 image format. The file must be open for writing. Under
MSDOS and all versions of Windows, it is important to use "wb"
as opposed to simply "w" as the mode when opening the file, and
under Unix there is no penalty for doing so. gdImageGd2 does
_not_ close the file; your code must do so.
The gd2 image format is intended for fast reads and writes of
parts of images. It is a compressed format, and well suited to
retrieving smll sections of much larger images. The third and
fourth parameters are the 'chunk size' and format
resposectively.
The file is stored as a series of compressed subimages, and the
_Chunk Size_ determines the sub-image size - a value of zero
causes the GD library to use the default.
It is also possible to store GD2 files in an uncompressed
format, in which case the fourth parameter should be
GD2_FMT_RAW.
_(FUNCTION)_
gdImageGd2 outputs the specified image to the specified file in the
gd2 image format. The file must be open for writing. Under MSDOS and
all versions of Windows, it is important to use "wb" as opposed to
simply "w" as the mode when opening the file, and under Unix there is
no penalty for doing so. gdImageGd2 does _not_ close the file; your
code must do so.
The gd2 image format is intended for fast reads and writes of parts of
images. It is a compressed format, and well suited to retrieving smll
sections of much larger images. The third and fourth parameters are
the 'chunk size' and format resposectively.
The file is stored as a series of compressed subimages, and the _Chunk
Size_ determines the sub-image size - a value of zero causes the GD
library to use the default.
It is also possible to store GD2 files in an uncompressed format, in
which case the fourth parameter should be GD2_FMT_RAW.
... inside a function ...
gdImagePtr im;
@ -1013,12 +1171,12 @@ fclose(out);
gdImageDestroy(im);
void* gdImageGd2Ptr(gdImagePtr im, int chunkSize, int fmt, int *size)
_(FUNCTION)_
Identical to gdImageGd2 except that it returns a pointer to a
memory area with the GD2 data. This memory must be freed by the
caller when it is no longer needed. The 'size' parameter
received the total size of the block of memory.
_(FUNCTION)_
Identical to gdImageGd2 except that it returns a pointer to a memory
area with the GD2 data. This memory must be freed by the caller when
it is no longer needed. The 'size' parameter receives the total size
of the block of memory.
Drawing Functions
void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
@ -1865,10 +2023,11 @@ gdImageDestroy(im);
working with existing PNG files that already use 256
colors.) Note that gdImageColorAllocate does not check
for existing colors that match your request; see
gdImageColorExact and gdImageColorClosest for ways to
locate existing colors that approximate the color desired
in situations where a new color is not available. Also
see gdImageColorResolve, new in gd-1.6.2.
gdImageColorExact, gdImageColorClosest and
gdImageColorClosestHWB for ways to locate existing colors
that approximate the color desired in situations where a
new color is not available. Also see gdImageColorResolve,
new in gd-1.6.2.
... inside a function ...
@ -1927,6 +2086,49 @@ if (red == (-1)) {
gdImageDashedLine(im, 0, 0, 99, 99, red);
/* ... Do something with the image, such as saving it to a file... */
/* Destroy it */
gdImageDestroy(im);
int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b)
_(FUNCTION)_
gdImageColorClosestHWB searches the colors which have
been defined thus far in the image specified and returns
the index of the color with hue, whiteness and blackness
closest to the requested color. This scheme is typically
superior to the Euclidian distance scheme used by
gdImageColorClosest.
If no colors have yet been allocated in the image,
gdImageColorClosestHWB returns -1.
This function is most useful as a backup method for
choosing a drawing color when an image already contains
gdMaxColors (256) colors and no more can be allocated.
(This is not uncommon when working with existing PNG
files that already use many colors.) See
gdImageColorExact for a method of locating exact matches
only.
... inside a function ...
gdImagePtr im;
FILE *in;
int red;
/* Let's suppose that photo.png is a scanned photograph with
many colors. */
in = fopen("photo.png", "rb");
im = gdImageCreateFromPng(in);
fclose(in);
/* Try to allocate red directly */
red = gdImageColorAllocate(im, 255, 0, 0);
/* If we fail to allocate red... */
if (red == (-1)) {
/* Find the _closest_ color instead. */
red = gdImageColorClosestHWB(im, 255, 0, 0);
}
/* Draw a dashed line from the upper left corner to the lower right corner */
gdImageDashedLine(im, 0, 0, 99, 99, red);
/* ... Do something with the image, such as saving it to a file... */
/* Destroy it */
gdImageDestroy(im);
int gdImageColorExact(gdImagePtr im, int r, int g, int b)
@ -2070,16 +2272,20 @@ gdImageDestroy(im);
for the specified image to the specified index. To
indicate that there should be _no_ transparent color,
invoke gdImageColorTransparent with a color index of -1.
Note that JPEG images do not support transparency, so
this setting has no effect when writing JPEG images.
The color index used should be an index allocated by
gdImageColorAllocate, whether explicitly invoked by your
code or implicitly invoked by loading an image. In order
to ensure that your image has a reasonable appearance
when viewed by users who do not have transparent
background capabilities, be sure to give reasonable RGB
values to the color you allocate for use as a transparent
color, _even though it will be transparent on systems
that support transparency_.
background capabilities (or when you are writing a
JPEG-format file, which does not support transparency),
be sure to give reasonable RGB values to the color you
allocate for use as a transparent color, _even though it
will be transparent on systems that support PNG
transparency_.
... inside a function ...
@ -2267,9 +2473,9 @@ gdImageCopyMergeGray(im_out, im_in, 100, 200, 0, 0, 30, 50, 50);
void gdImagePaletteCopy(gdImagePtr dst, gdImagePtr src)
_(FUNCTION)_
Copies a palette from one image to another, doing it's
best to match the colors in the target image to the
colors in the source palette.
Copies a palette from one image to another, attempting to
match the colors in the target image to the colors in the
source palette.
Miscellaneous Functions
@ -2296,22 +2502,31 @@ cmpMask = gdImageCompare(im1, im2);
which lines will appear on the display from first
to last, or in an interlaced fashion, in which the
image will "fade in" over several passes. By
default, images are not interlaced.
default, images are not interlaced. (When writing
JPEG images, interlacing implies generating
progressive JPEG files, which are represented as a
series of scans of increasing quality.
Noninterlaced gd images result in regular
[sequential] JPEG data streams.)
A nonzero value for the interlace argument turns on
interlace; a zero value turns it off. Note that
interlace has no effect on other functions, and has
no meaning unless you save the image in PNG format;
the gd and xbm formats do not support interlace.
no meaning unless you save the image in PNG or JPEG
format; the gd and xbm formats do not support
interlace.
When a PNG is loaded with gdImageCreateFromPng ,
When a PNG is loaded with gdImageCreateFromPng or a
JPEG is loaded with gdImageCreateFromJpeg,
interlace will be set according to the setting in
the PNG file.
the PNG or JPEG file.
Note that many PNG viewers and web browsers do _not_
support interlace. However, the interlaced PNG
should still display; it will simply appear all at
once, just as other images do.
Note that many PNG and JPEG viewers and web
browsers do _not_ support interlace or the
incremental display of progressive JPEGs. However,
the interlaced PNG or progressive JPEG should still
display; it will simply appear all at once, just as
other images do.
gdImagePtr im;
@ -2322,7 +2537,7 @@ FILE *out;
gdImageInterlace(im, 1);
/* And open an output file */
out = fopen("test.png", "wb");
/* And save the image */
/* And save the image -- could also use gdImageJpeg */
gdImagePng(im, out);
fclose(out);
gdImageDestroy(im);
@ -2410,21 +2625,21 @@ gdImageDestroy(im);
About the additional .gd image file format
In addition to reading and writing the PNG
format and reading the X Bitmap format, gd
has the capability to read and write its own
".gd" format. This format is _not_ intended
for general purpose use and should never be
used to distribute images. It is not a
compressed format. Its purpose is solely to
allow very fast loading of images your
program needs often in order to build other
images for output. If you are experiencing
performance problems when loading large,
fixed PNG images your program needs to
produce its output images, you may wish to
examine the functions gdImageCreateFromGd and
gdImageGd, which read and write .gd format
images.
and JPEG formats and reading the X Bitmap
format, gd has the capability to read and
write its own ".gd" format. This format is
_not_ intended for general purpose use and
should never be used to distribute images. It
is not a compressed format. Its purpose is
solely to allow very fast loading of images
your program needs often in order to build
other images for output. If you are
experiencing performance problems when
loading large, fixed PNG images your program
needs to produce its output images, you may
wish to examine the functions
gdImageCreateFromGd and gdImageGd, which read
and write .gd format images.
The program "pngtogd.c" is provided as a
simple way of converting .png files to .gd
@ -2445,9 +2660,9 @@ gdImageDestroy(im);
image files. Its purpose is solely to allow
very fast loading of _parts_ of images If you
are experiencing performance problems when
loading large, fixed PNG images your program
needs to produce its output images, you may
wish to examine the functions
loading large, fixed PNG or JPEG images your
program needs to produce its output images,
you may wish to examine the functions
gdImageCreateFromGd2,
gdImageCreateFromGd2Part and gdImageGd2,
which read and write .gd2 format images.
@ -2539,24 +2754,25 @@ typedef struct gdIOCtx {
gdImageCopyResized | gdImageCreate |
gdImageCreateFromGd | gdImageCreateFromGd2 |
gdImageCreateFromGd2Part |
gdImageCreateFromPng |
gdImageCreateFromPngSource |
gdImageCreateFromJpeg | gdImageCreateFromPng
| gdImageCreateFromPngSource |
gdImageCreateFromXbm | gdImageCreateFromXpm |
gdImageDashedLine | gdImageDestroy |
gdImageFill | gdImageFillToBorder |
gdImageFilledRectangle | gdImageGd |
gdImageGd2 | gdImageGetInterlaced |
gdImageGetPixel | gdImageGetTransparent |
gdImageGreen | gdImageInterlace | gdImageLine
| gdImageFilledPolygon | gdImagePaletteCopy |
gdImagePng | gdImagePngToSink |
gdImagePolygon | gdImagePtr |
gdImageRectangle | gdImageRed |
gdImageSetBrush | gdImageSetPixel |
gdImageSetStyle | gdImageSetTile |
gdImageString | gdImageString16 |
gdImageStringTTF | gdImageStringUp |
gdImageStringUp16 | gdMaxColors | gdPoint |
gdImageGreen | gdImageInterlace | gdImageJpeg
| gdImageLine | gdImageFilledPolygon |
gdImagePaletteCopy | gdImagePng |
gdImagePngToSink | gdImagePolygon |
gdImagePtr | gdImageWBMP | gdImageRectangle |
gdImageRed | gdImageSetBrush |
gdImageSetPixel | gdImageSetStyle |
gdImageSetTile | gdImageString |
gdImageString16 | gdImageStringTTF |
gdImageStringUp | gdImageStringUp16 |
gdImageWBMP | gdMaxColors | gdPoint |
gdStyled | gdStyledBrushed | gdTiled |
gdTransparent