- sync to 2.0.23

master
pierre 2006-04-05 15:51:53 +00:00
parent 480330b083
commit 0a3439a3e7
18 changed files with 1213 additions and 1027 deletions

View File

@ -7,56 +7,60 @@
int
main (int argc, char *argv[])
{
/* 2.0.22: can't depend on PNG either */
/* 2.0.22: can't depend on PNG either */
#ifndef HAVE_LIBPNG
fprintf(stderr, "Requires PNG support, gd was compiled without it\n");
exit(0);
fprintf (stderr, "Requires PNG support, gd was compiled without it\n");
exit (0);
#else
FILE *in = 0;
FILE *out;
gdImagePtr im;
int radius;
/* Create an image of text on a circle, with an
alpha channel so that we can copy it onto a
background */
/* TBB: 2.0.18: shouldn't depend on JPEG */
FILE *in = 0;
FILE *out;
gdImagePtr im;
int radius;
/* Create an image of text on a circle, with an
alpha channel so that we can copy it onto a
background */
/* TBB: 2.0.18: shouldn't depend on JPEG */
#ifdef HAVE_LIBJPEG
in = fopen("eleanor.jpg", "rb");
if (!in) {
im = gdImageCreateTrueColor(300, 300);
} else {
im = gdImageCreateFromJpeg(in);
fclose(in);
}
in = fopen ("eleanor.jpg", "rb");
if (!in)
{
im = gdImageCreateTrueColor (300, 300);
}
else
{
im = gdImageCreateFromJpeg (in);
fclose (in);
}
#else
im = gdImageCreateTrueColor(300, 300);
#endif /* HAVE_LIBJPEG */
if (gdImageSX(im) < gdImageSY(im)) {
radius = gdImageSX(im) / 2;
} else {
radius = gdImageSY(im) / 2;
}
gdImageStringFTCircle(
im,
gdImageSX(im) / 2,
gdImageSY(im) / 2,
radius,
radius / 2,
0.8,
"arial",
24,
"top text",
"bottom text",
gdTrueColorAlpha(192, 100, 255, 32));
out = fopen("gdfx.png", "wb");
if (!out) {
fprintf(stderr, "Can't create gdfx.png\n");
return 1;
}
gdImagePng(im, out);
fclose(out);
gdImageDestroy(im);
im = gdImageCreateTrueColor (300, 300);
#endif /* HAVE_LIBJPEG */
if (gdImageSX (im) < gdImageSY (im))
{
radius = gdImageSX (im) / 2;
}
else
{
radius = gdImageSY (im) / 2;
}
gdImageStringFTCircle (im,
gdImageSX (im) / 2,
gdImageSY (im) / 2,
radius,
radius / 2,
0.8,
"arial",
24,
"top text",
"bottom text", gdTrueColorAlpha (192, 100, 255, 32));
out = fopen ("gdfx.png", "wb");
if (!out)
{
fprintf (stderr, "Can't create gdfx.png\n");
return 1;
}
gdImagePng (im, out);
fclose (out);
gdImageDestroy (im);
#endif /* HAVE_LIBPNG */
return 0;
return 0;
}

26
src/configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.57 for GD 2.0.22.
# Generated by GNU Autoconf 2.57 for GD 2.0.23.
#
# Report bugs to <gd@boutell.com>.
#
@ -427,8 +427,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='GD'
PACKAGE_TARNAME='gd'
PACKAGE_VERSION='2.0.22'
PACKAGE_STRING='GD 2.0.22'
PACKAGE_VERSION='2.0.23'
PACKAGE_STRING='GD 2.0.23'
PACKAGE_BUGREPORT='gd@boutell.com'
ac_unique_file="gd.c"
@ -938,7 +938,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures GD 2.0.22 to adapt to many kinds of systems.
\`configure' configures GD 2.0.23 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1008,7 +1008,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of GD 2.0.22:";;
short | recursive ) echo "Configuration of GD 2.0.23:";;
esac
cat <<\_ACEOF
@ -1111,7 +1111,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
GD configure 2.0.22
GD configure 2.0.23
generated by GNU Autoconf 2.57
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
@ -1126,7 +1126,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by GD $as_me 2.0.22, which was
It was created by GD $as_me 2.0.23, which was
generated by GNU Autoconf 2.57. Invocation command line was
$ $0 $@
@ -1491,7 +1491,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
GDLIB_MAJOR=2
GDLIB_MINOR=0
GDLIB_REVISION=22
GDLIB_REVISION=23
GDLIBNAME=gd
@ -1738,7 +1738,7 @@ fi
# Define the identity of the package.
PACKAGE=gd
VERSION=2.0.22
VERSION=2.0.23
cat >>confdefs.h <<_ACEOF
@ -10371,8 +10371,8 @@ echo "$as_me: WARNING: libpng is required - see http://www.libpng.org/pub/png/"
fi
#TBB: png12's png_create_read_struct is just as good
if test "$ac_cv_lib_png12_png_create_read_struct" == yes; then
#2.0.23: should be = not ==
if test "$ac_cv_lib_png12_png_create_read_struct" = yes; then
ac_cv_lib_png_png_create_read_struct=yes
fi
@ -11683,7 +11683,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
This file was extended by GD $as_me 2.0.22, which was
This file was extended by GD $as_me 2.0.23, which was
generated by GNU Autoconf 2.57. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -11746,7 +11746,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
GD config.status 2.0.22
GD config.status 2.0.23
configured by $0, generated by GNU Autoconf 2.57,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -5,13 +5,13 @@
AC_PREREQ(2.54)
#HEY! Change BOTH the vesion number and the GDLIB_REVISION setting!
AC_INIT([GD], [2.0.22], [gd@boutell.com])
AC_INIT([GD], [2.0.23], [gd@boutell.com])
AC_CONFIG_SRCDIR([gd.c])
AC_CONFIG_AUX_DIR(config)
GDLIB_MAJOR=2
GDLIB_MINOR=0
GDLIB_REVISION=22
GDLIB_REVISION=23
GDLIBNAME=gd
AC_SUBST(GDLIB_MAJOR)
@ -320,8 +320,8 @@ else
fi
#TBB: png12's png_create_read_struct is just as good
if test "$ac_cv_lib_png12_png_create_read_struct" == yes; then
#2.0.23: should be = not ==
if test "$ac_cv_lib_png12_png_create_read_struct" = yes; then
ac_cv_lib_png_png_create_read_struct=yes
fi

View File

@ -36,9 +36,11 @@ extern "C"
#endif
/* some might want to set DEFAULT_FONTPATH from configure in config.h */
/* 2.0.23: more Type 1 fonts */
#ifndef DEFAULT_FONTPATH
/* default fontpath for unix systems - whatever happened to standards ! */
#define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1"
#define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1:/usr/lib/X11/fonts/Type1:/usr/openwin/lib/X11/fonts/Type1"
#endif
#ifndef PATHSEPARATOR
#define PATHSEPARATOR ":"
@ -373,11 +375,15 @@ extern "C"
gdFTEX_Shift_JIS, or gdFTEX_Big5;
when not specified, maps are searched
for in the above order. */
int hdpi; /* if (flags & gdFTEX_RESOLUTION) */
int vdpi; /* if (flags & gdFTEX_RESOLUTION) */
}
gdFTStringExtra, *gdFTStringExtraPtr;
#define gdFTEX_LINESPACE 1
#define gdFTEX_CHARMAP 2
#define gdFTEX_RESOLUTION 4
/* These are NOT flags; set one in 'charmap' if you set the
gdFTEX_CHARMAP bit in 'flags'. */

View File

@ -486,7 +486,8 @@ gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h)
}
gdImagePtr
gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w, int h)
gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w,
int h)
{
gdImagePtr im;
gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
@ -669,7 +670,7 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
compBuf,
chunkIdx[chunkNum].size,
(char*) chunkBuf, &chunkLen, in))
(char *) chunkBuf, &chunkLen, in))
{
printf ("Error reading comproessed chunk\n");
goto fail2;
@ -691,7 +692,7 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
{
if (im->trueColor)
{
if (!gdGetInt ( (int*) &ch, in))
if (!gdGetInt ((int *) &ch, in))
{
ch = 0;
/*printf("EOF while reading file\n"); */
@ -701,7 +702,7 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
else
{
ch = gdGetC (in);
if ((int)ch == EOF)
if ((int) ch == EOF)
{
ch = 0;
/*printf("EOF while reading file\n"); */

View File

@ -72,7 +72,8 @@ static long dynamicTell (struct gdIOCtx *);
gdIOCtx *
gdNewDynamicCtx (int initialSize, void *data)
{
gdNewDynamicCtxEx(initialSize, data, 1);
/* 2.0.23: Phil Moore: 'return' keyword was missing! */
return gdNewDynamicCtxEx (initialSize, data, 1);
}
gdIOCtx *
@ -197,9 +198,10 @@ dynamicSeek (struct gdIOCtx *ctx, const int pos)
if (bytesNeeded > dp->realSize)
{
/* 2.0.21 */
if (!dp->freeOK) {
return FALSE;
}
if (!dp->freeOK)
{
return FALSE;
}
if (!gdReallocDynamic (dp, dp->realSize * 2))
{
dp->dataGood = FALSE;
@ -372,9 +374,10 @@ appendDynamic (dynamicPtr * dp, const void *src, int size)
if (bytesNeeded > dp->realSize)
{
/* 2.0.21 */
if (!dp->freeOK) {
return FALSE;
}
if (!dp->freeOK)
{
return FALSE;
}
if (!gdReallocDynamic (dp, bytesNeeded * 2))
{
dp->dataGood = FALSE;
@ -435,8 +438,9 @@ static int
trimDynamic (dynamicPtr * dp)
{
/* 2.0.21: we don't reallocate memory we don't own */
if (!dp->freeOK) {
return TRUE;
}
if (!dp->freeOK)
{
return TRUE;
}
return gdReallocDynamic (dp, dp->logicalSize);
}

View File

@ -281,7 +281,7 @@ gdImageCreateFromJpegPtr (int size, void *data)
void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
static int CMYKToRGB(int c, int m, int y, int k, int inverted);
static int CMYKToRGB (int c, int m, int y, int k, int inverted);
/*
* Create a gd-format image from the JPEG-format INFILE. Returns the
@ -329,14 +329,14 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
jpeg_gdIOCtx_src (&cinfo, infile);
/* 2.0.22: save the APP14 marker to check for Adobe Photoshop CMYK
files with inverted components. */
jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256);
files with inverted components. */
jpeg_save_markers (&cinfo, JPEG_APP0 + 14, 256);
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"
@ -355,15 +355,17 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
goto error;
}
/* 2.0.22: very basic support for reading CMYK colorspace files. Nice for
thumbnails but there's no support for fussy adjustment of the
assumed properties of inks and paper. */
thumbnails but there's no support for fussy adjustment of the
assumed properties of inks and paper. */
if ((cinfo.jpeg_color_space == JCS_CMYK) ||
(cinfo.jpeg_color_space == JCS_YCCK))
{
cinfo.out_color_space = JCS_CMYK;
} else {
cinfo.out_color_space = JCS_RGB;
}
(cinfo.jpeg_color_space == JCS_YCCK))
{
cinfo.out_color_space = JCS_CMYK;
}
else
{
cinfo.out_color_space = JCS_RGB;
}
if (jpeg_start_decompress (&cinfo) != TRUE)
fprintf (stderr, "gd-jpeg: warning: jpeg_start_decompress"
@ -426,41 +428,46 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
#if 0
gdImageInterlace (im, cinfo.progressive_mode != 0);
#endif
if (cinfo.out_color_space == JCS_RGB)
{
if (cinfo.output_components != 3)
if (cinfo.out_color_space == JCS_RGB)
{
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
" request resulted in output_components == %d"
" (expected 3 for RGB)\n", cinfo.output_components);
if (cinfo.output_components != 3)
{
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
" request resulted in output_components == %d"
" (expected 3 for RGB)\n", cinfo.output_components);
goto error;
}
channels = 3;
}
else if (cinfo.out_color_space == JCS_CMYK)
{
jpeg_saved_marker_ptr marker;
if (cinfo.output_components != 4)
{
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
" request resulted in output_components == %d"
" (expected 4 for CMYK)\n", cinfo.output_components);
goto error;
}
channels = 4;
marker = cinfo.marker_list;
while (marker)
{
if ((marker->marker == (JPEG_APP0 + 14)) &&
(marker->data_length >= 12)
&& (!strncmp ((const char *) marker->data, "Adobe", 5)))
{
inverted = 1;
break;
}
marker = marker->next;
}
}
else
{
fprintf (stderr, "gd-jpeg: error: unexpected colorspace\n");
goto error;
}
channels = 3;
} else if (cinfo.out_color_space == JCS_CMYK) {
jpeg_saved_marker_ptr marker;
if (cinfo.output_components != 4)
{
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
" request resulted in output_components == %d"
" (expected 4 for CMYK)\n", cinfo.output_components);
goto error;
}
channels = 4;
marker = cinfo.marker_list;
while (marker) {
if ((marker->marker == (JPEG_APP0 + 14)) &&
(marker->data_length >= 12) && (!strncmp((const char *) marker->data,
"Adobe", 5)))
{
inverted = 1;
break;
}
marker = marker->next;
}
} else {
fprintf (stderr, "gd-jpeg: error: unexpected colorspace\n");
goto error;
}
#if BITS_IN_JSAMPLE == 12
fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
"precision. This is mostly useless, because JPEGs on the web are\n"
@ -479,47 +486,52 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
goto error;
}
rowptr[0] = row;
if (cinfo.out_color_space == JCS_CMYK) {
for (i = 0; i < cinfo.output_height; i++)
{
register JSAMPROW currow = row;
register int *tpix = im->tpixels[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++, currow += 4, tpix++)
{
*tpix = CMYKToRGB (currow[0], currow[1], currow[2], currow[3], inverted);
}
}
} else {
for (i = 0; i < cinfo.output_height; i++)
{
register JSAMPROW currow = row;
register int *tpix = im->tpixels[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++, currow += 3, tpix++)
{
*tpix = gdTrueColor (currow[0], currow[1], currow[2]);
}
}
}
if (cinfo.out_color_space == JCS_CMYK)
{
for (i = 0; i < cinfo.output_height; i++)
{
register JSAMPROW currow = row;
register int *tpix = im->tpixels[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++, currow += 4, tpix++)
{
*tpix =
CMYKToRGB (currow[0], currow[1], currow[2], currow[3],
inverted);
}
}
}
else
{
for (i = 0; i < cinfo.output_height; i++)
{
register JSAMPROW currow = row;
register int *tpix = im->tpixels[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++, currow += 3, tpix++)
{
*tpix = gdTrueColor (currow[0], currow[1], currow[2]);
}
}
}
if (jpeg_finish_decompress (&cinfo) != TRUE)
fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress"
" reports suspended data source\n");
/* Thanks to Truxton Fulton */
if(cinfo.err->num_warnings>0)
goto error ;
if (cinfo.err->num_warnings > 0)
goto error;
jpeg_destroy_decompress (&cinfo);
gdFree (row);
@ -535,50 +547,59 @@ error:
}
/* A very basic conversion approach, TBB */
static int CMYKToRGB(int c, int m, int y, int k, int inverted)
static int
CMYKToRGB (int c, int m, int y, int k, int inverted)
{
if (inverted) {
c = 255 - c;
m = 255 - m;
y = 255 - y;
k = 255 - k;
}
return gdTrueColor((255 - c) * (255 - k) / 255,
(255 - m) * (255 - k) / 255,
(255 - y) * (255 - k) / 255);
if (inverted)
{
c = 255 - c;
m = 255 - m;
y = 255 - y;
k = 255 - k;
}
return gdTrueColor ((255 - c) * (255 - k) / 255,
(255 - m) * (255 - k) / 255,
(255 - y) * (255 - k) / 255);
#if 0
if (inverted) {
c = 255 - c;
m = 255 - m;
y = 255 - y;
k = 255 - k;
}
if (inverted)
{
c = 255 - c;
m = 255 - m;
y = 255 - y;
k = 255 - k;
}
c = c * (255 - k) / 255 + k;
if (c > 255) {
c = 255;
}
if (c < 0) {
c = 0;
}
if (c > 255)
{
c = 255;
}
if (c < 0)
{
c = 0;
}
m = m * (255 - k) / 255 + k;
if (m > 255) {
m = 255;
}
if (m < 0) {
m = 0;
}
if (m > 255)
{
m = 255;
}
if (m < 0)
{
m = 0;
}
y = y * (255 - k) / 255 + k;
if (y > 255) {
y = 255;
}
if (y < 0) {
y = 0;
}
if (y > 255)
{
y = 255;
}
if (y < 0)
{
y = 0;
}
c = 255 - c;
m = 255 - m;
y = 255 - y;
return gdTrueColor(c, m, y);
return gdTrueColor (c, m, y);
#endif
}
@ -677,7 +698,7 @@ fill_input_buffer (j_decompress_ptr cinfo)
my_src_ptr src = (my_src_ptr) cinfo->src;
/* 2.0.12: signed size. Thanks to Geert Jansen */
/* 2.0.14: some platforms (mingw-msys) don't have ssize_t. Call
an int an int. */
an int an int. */
int nbytes = 0;
memset (src->buffer, 0, INPUT_BUF_SIZE);

View File

@ -539,9 +539,9 @@ gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
fussing with such things. */
/* Faster if this is uncommented, but may produce larger truecolor files.
Wait for gdImagePngCtxEx. */
Wait for gdImagePngCtxEx. */
#if 0
png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
#endif
/* 2.0.12: this is finally a parameter */
@ -718,22 +718,22 @@ gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
int channels = im->saveAlphaFlag ? 4 : 3;
/* Our little 7-bit alpha channel trick costs us a bit here. */
png_bytep *row_pointers;
unsigned char* pOutputRow;
int **ptpixels=im->tpixels;
unsigned char *pOutputRow;
int **ptpixels = im->tpixels;
int *pThisRow;
unsigned char a;
int thisPixel;
png_bytep *prow_pointers;
int saveAlphaFlag=im->saveAlphaFlag;
int saveAlphaFlag = im->saveAlphaFlag;
row_pointers = gdMalloc (sizeof (png_bytep) * height);
if (row_pointers == NULL)
{
fprintf (stderr, "gd-png error: unable to allocate row_pointers\n");
}
prow_pointers=row_pointers;
prow_pointers = row_pointers;
for (j = 0; j < height; ++j)
{
if ((*prow_pointers =
if ((*prow_pointers =
(png_bytep) gdMalloc (width * channels)) == NULL)
{
fprintf (stderr, "gd-png error: unable to allocate rows\n");
@ -741,25 +741,25 @@ gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
gdFree (row_pointers[i]);
return;
}
pOutputRow=*prow_pointers++;
pThisRow=*ptpixels++;
pOutputRow = *prow_pointers++;
pThisRow = *ptpixels++;
for (i = 0; i < width; ++i)
{
thisPixel=*pThisRow++;
*pOutputRow++=gdTrueColorGetRed(thisPixel);
*pOutputRow++=gdTrueColorGetGreen(thisPixel);
*pOutputRow++=gdTrueColorGetBlue(thisPixel);
thisPixel = *pThisRow++;
*pOutputRow++ = gdTrueColorGetRed (thisPixel);
*pOutputRow++ = gdTrueColorGetGreen (thisPixel);
*pOutputRow++ = gdTrueColorGetBlue (thisPixel);
if (saveAlphaFlag)
if (saveAlphaFlag)
{
/* convert the 7-bit alpha channel to an 8-bit alpha channel.
We do a little bit-flipping magic, repeating the MSB
as the LSB, to ensure that 0 maps to 0 and
127 maps to 255. We also have to invert to match
PNG's convention in which 255 is opaque. */
a = gdTrueColorGetAlpha (thisPixel);
a = gdTrueColorGetAlpha (thisPixel);
/* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */
*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
}
}
}

View File

@ -757,15 +757,18 @@ LOCAL (void)
cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total >> 1)) / total);
#else
/* 2.0.16: Paul den Dulk found an occasion where total can be 0 */
if (count) {
im->red[icolor] = (int) ((c0total + (total >> 1)) / total);
im->green[icolor] = (int) ((c1total + (total >> 1)) / total);
im->blue[icolor] = (int) ((c2total + (total >> 1)) / total);
} else {
im->red[icolor] = 255;
im->green[icolor] = 255;
im->blue[icolor] = 255;
}
if (count)
{
im->red[icolor] = (int) ((c0total + (total >> 1)) / total);
im->green[icolor] = (int) ((c1total + (total >> 1)) / total);
im->blue[icolor] = (int) ((c2total + (total >> 1)) / total);
}
else
{
im->red[icolor] = 255;
im->green[icolor] = 255;
im->blue[icolor] = 255;
}
#endif
}

View File

@ -137,36 +137,40 @@ main (void)
gdImageLine (im_out, 0, 255, 255, 0, gdStyledBrushed);
}
/* Text (non-truetype; see gdtestft for a freetype demo) */
fonts[0] = gdFontGetTiny();
fonts[1] = gdFontGetSmall();
fonts[2] = gdFontGetMediumBold();
fonts[3] = gdFontGetLarge();
fonts[4] = gdFontGetGiant();
fonts[0] = gdFontGetTiny ();
fonts[1] = gdFontGetSmall ();
fonts[2] = gdFontGetMediumBold ();
fonts[3] = gdFontGetLarge ();
fonts[4] = gdFontGetGiant ();
y = 0;
for (i = 0; (i <= 4); i++) {
gdImageString (im_out, fonts[i], 32, 32 + y, (unsigned char *) "hi", red);
y += fonts[i]->h;
}
for (i = 0; (i <= 4); i++)
{
gdImageString (im_out, fonts[i], 32, 32 + y, (unsigned char *) "hi",
red);
y += fonts[i]->h;
}
y = 0;
for (i = 0; (i <= 4); i++) {
gdImageStringUp (im_out, fonts[i], 64 + y, 64,
(unsigned char *) "hi", red);
y += fonts[i]->h;
}
for (i = 0; (i <= 4); i++)
{
gdImageStringUp (im_out, fonts[i], 64 + y, 64,
(unsigned char *) "hi", red);
y += fonts[i]->h;
}
/* Random antialiased lines; coordinates all over the image,
but the output will respect a small clipping rectangle */
gdImageSetClip(im_out, 0, gdImageSY(im_out) - 100,
100, gdImageSY(im_out));
but the output will respect a small clipping rectangle */
gdImageSetClip (im_out, 0, gdImageSY (im_out) - 100,
100, gdImageSY (im_out));
/* Fixed seed for reproducibility of results */
srand(100);
for (i = 0; (i < 100); i++) {
int x1 = rand() % gdImageSX(im_out);
int y1 = rand() % gdImageSY(im_out);
int x2 = rand() % gdImageSX(im_out);
int y2 = rand() % gdImageSY(im_out);
gdImageSetAntiAliased(im_out, white);
gdImageLine (im_out, x1, y1, x2, y2, gdAntiAliased);
}
srand (100);
for (i = 0; (i < 100); i++)
{
int x1 = rand () % gdImageSX (im_out);
int y1 = rand () % gdImageSY (im_out);
int x2 = rand () % gdImageSX (im_out);
int y2 = rand () % gdImageSY (im_out);
gdImageSetAntiAliased (im_out, white);
gdImageLine (im_out, x1, y1, x2, y2, gdAntiAliased);
}
/* Make output image interlaced (progressive, in the case of JPEG) */
gdImageInterlace (im_out, 1);
out = fopen ("demoout.png", "wb");

View File

@ -4379,9 +4379,10 @@ gdFont gdFontGiantRep = {
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontGiant = &gdFontGiantRep;
gdFontPtr gdFontGetGiant(void)
gdFontPtr
gdFontGetGiant (void)
{
return gdFontGiant;
return gdFontGiant;
}
/* This file has not been truncated. */

View File

@ -4636,9 +4636,10 @@ gdFont gdFontLargeRep = {
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontLarge = &gdFontLargeRep;
gdFontPtr gdFontGetLarge(void)
gdFontPtr
gdFontGetLarge (void)
{
return gdFontLarge;
return gdFontLarge;
}
/* This file has not been truncated. */

View File

@ -3866,9 +3866,10 @@ gdFont gdFontMediumBoldRep = {
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontMediumBold = &gdFontMediumBoldRep;
gdFontPtr gdFontGetMediumBold(void)
gdFontPtr
gdFontGetMediumBold (void)
{
return gdFontMediumBold;
return gdFontMediumBold;
}
/* This file has not been truncated. */

View File

@ -3866,9 +3866,10 @@ gdFont gdFontSmallRep = {
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontSmall = &gdFontSmallRep;
gdFontPtr gdFontGetSmall(void)
gdFontPtr
gdFontGetSmall (void)
{
return gdFontSmall;
return gdFontSmall;
}
/* This file has not been truncated. */

View File

@ -2587,9 +2587,10 @@ gdFont gdFontTinyRep = {
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontTiny = &gdFontTinyRep;
gdFontPtr gdFontGetTiny(void)
gdFontPtr
gdFontGetTiny (void)
{
return gdFontTiny;
return gdFontTiny;
}
/* This file has not been truncated. */

View File

@ -386,8 +386,9 @@ fontFetch (char **error, void *key)
* Allocate an oversized buffer that is guaranteed to be
* big enough for all paths to be tested.
*/
/* 2.0.22: Thorben Kundinger: +8 is needed, not +6. */
fullname = gdRealloc (fullname,
strlen (fontsearchpath) + strlen (name) + 6);
strlen (fontsearchpath) + strlen (name) + 8);
/* if name is an absolute or relative pathname then test directly */
if (strchr (name, '/')
|| (name[0] != 0 && name[1] == ':'
@ -397,8 +398,8 @@ fontFetch (char **error, void *key)
if (access (fullname, R_OK) == 0)
{
font_found++;
/* 2.0.16: memory leak fixed, Gustavo Scotti */
gdFree(path);
/* 2.0.16: memory leak fixed, Gustavo Scotti */
gdFree (path);
break;
}
}
@ -479,16 +480,20 @@ fontFetch (char **error, void *key)
platform = charmap->platform_id;
encoding = charmap->encoding_id;
/* EAM DEBUG - Newer versions of libfree2 make it easier by defining encodings */
#if (defined(FREETYPE_MAJOR) && (FREETYPE_MAJOR >=2 ) && (FREETYPE_MINOR >= 1))
/* EAM DEBUG - Newer versions of libfree2 make it easier
by defining encodings */
/* TBB: get this exactly right: 2.1.3 *or better*, all possible cases. */
#if ((defined(FREETYPE_MAJOR)) && (((FREETYPE_MAJOR == 2) && (((FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 3)) || (FREETYPE_MINOR > 1))) || (FREETYPE_MAJOR > 2)))
if (charmap->encoding == FT_ENCODING_MS_SYMBOL
|| charmap->encoding == FT_ENCODING_ADOBE_CUSTOM
|| charmap->encoding == FT_ENCODING_ADOBE_STANDARD) {
a->have_char_map_unicode = 1;
found = charmap;
a->face->charmap = charmap;
return (void *)a;
}
|| charmap->encoding == FT_ENCODING_ADOBE_CUSTOM
|| charmap->encoding == FT_ENCODING_ADOBE_STANDARD)
{
a->have_char_map_unicode = 1;
found = charmap;
a->face->charmap = charmap;
return (void *) a;
}
#endif /* Freetype 2.1 or better */
/* EAM DEBUG */
@ -649,7 +654,7 @@ gdft_draw_bitmap (gdCache_head_t * tc_cache, gdImage * im, int fg,
pcr = pc;
y = pen_y + row;
/* clip if out of bounds */
/* 2.0.16: clipping rectangle, not image bounds */
/* 2.0.16: clipping rectangle, not image bounds */
if ((y > im->cy2) || (y < im->cy1))
continue;
for (col = 0; col < bitmap.width; col++, pc++)
@ -690,7 +695,7 @@ gdft_draw_bitmap (gdCache_head_t * tc_cache, gdImage * im, int fg,
level = gdAlphaMax - level;
x = pen_x + col;
/* clip if out of bounds */
/* 2.0.16: clip to clipping rectangle, Matt McNabb */
/* 2.0.16: clip to clipping rectangle, Matt McNabb */
if ((x > im->cx2) || (x < im->cx1))
continue;
/* get pixel location in gd buffer */
@ -804,14 +809,14 @@ extern int any2eucjp (char *, char *, unsigned int);
/* Fonts can be used across multiple images */
/* 2.0.16: thread safety (the font cache is shared) */
gdMutexDeclare(gdFontCacheMutex);
gdMutexDeclare (gdFontCacheMutex);
static gdCache_head_t *fontCache;
static FT_Library library;
void
gdFreeFontCache ()
{
gdFontCacheShutdown();
gdFontCacheShutdown ();
}
void
@ -819,7 +824,7 @@ gdFontCacheShutdown ()
{
if (fontCache)
{
gdMutexShutdown(gdFontCacheMutex);
gdMutexShutdown (gdFontCacheMutex);
gdCacheDelete (fontCache);
FT_Done_FreeType (library);
/* 2.0.16: Gustavo Scotti: make sure we don't free this twice */
@ -838,23 +843,25 @@ gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,
ptsize, angle, x, y, string, 0);
}
int gdFontCacheSetup(void)
int
gdFontCacheSetup (void)
{
if (fontCache) {
/* Already set up */
return 0;
}
gdMutexSetup(gdFontCacheMutex);
if (FT_Init_FreeType (&library))
{
gdMutexShutdown(gdFontCacheMutex);
return -1;
}
fontCache = gdCacheCreate (FONTCACHESIZE,
fontTest, fontFetch, fontRelease);
return 0;
if (fontCache)
{
/* Already set up */
return 0;
}
gdMutexSetup (gdFontCacheMutex);
if (FT_Init_FreeType (&library))
{
gdMutexShutdown (gdFontCacheMutex);
return -1;
}
fontCache = gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease);
return 0;
}
char *
gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
double ptsize, double angle, int x, int y, char *string,
@ -880,7 +887,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
int render = (im && (im->trueColor || (fg <= 255 && fg >= -255)));
FT_BitmapGlyph bm;
/* 2.0.13: Bob Ostermann: don't force autohint, that's just for testing
freetype and doesn't look as good */
freetype and doesn't look as good */
int render_mode = FT_LOAD_DEFAULT;
int m, mfound;
/* Now tuneable thanks to Wez Furlong */
@ -894,6 +901,8 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
* colorindexes. -- 27.06.2001 <krisku@arrak.fi>
*/
gdCache_head_t *tc_cache;
/* Tuneable horizontal and vertical resolution in dots per inch */
int hdpi, vdpi;
if (strex)
{
if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE)
@ -908,13 +917,14 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
/***** initialize font library and font cache on first call ******/
if (!fontCache)
{
if (gdFontCacheSetup() != 0) {
gdCacheDelete (tc_cache);
return "Failure to initialize font library";
}
if (gdFontCacheSetup () != 0)
{
gdCacheDelete (tc_cache);
return "Failure to initialize font library";
}
}
/*****/
gdMutexLock(gdFontCacheMutex);
gdMutexLock (gdFontCacheMutex);
/* get the font (via font cache) */
fontkey.fontlist = fontlist;
fontkey.library = &library;
@ -922,17 +932,29 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (!font)
{
gdCacheDelete (tc_cache);
gdMutexUnlock(gdFontCacheMutex);
gdMutexUnlock (gdFontCacheMutex);
return fontCache->error;
}
face = font->face; /* shortcut */
slot = face->glyph; /* shortcut */
if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64),
GD_RESOLUTION, GD_RESOLUTION))
/*
* Added hdpi and vdpi to support images at non-screen resolutions, i.e. 300 dpi TIFF,
* or 100h x 50v dpi FAX format. 2.0.23.
* 2004/02/27 Mark Shackelford, mark.shackelford@acs-inc.com
*/
hdpi = GD_RESOLUTION;
vdpi = GD_RESOLUTION;
if (strex && (strex->flags & gdFTEX_RESOLUTION))
{
hdpi = strex->hdpi;
vdpi = strex->vdpi;
}
if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64), hdpi, vdpi))
{
gdCacheDelete (tc_cache);
gdMutexUnlock(gdFontCacheMutex);
gdMutexUnlock (gdFontCacheMutex);
return "Could not set character size";
}
@ -993,7 +1015,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (!mfound)
{
/* No character set found! */
gdMutexUnlock(gdFontCacheMutex);
gdMutexUnlock (gdFontCacheMutex);
return "No character set found";
}
@ -1035,7 +1057,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
/* newlines */
if (ch == '\n')
{
/* 2.0.13: reset penf.x. Christopher J. Grayce */
/* 2.0.13: reset penf.x. Christopher J. Grayce */
penf.x = 0;
penf.y -= face->size->metrics.height * linespace;
penf.y = (penf.y - 32) & -64; /* round to next pixel row */
@ -1051,79 +1073,80 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
#if (defined(FREETYPE_MAJOR) && (FREETYPE_MAJOR >=2 ) && (FREETYPE_MINOR >= 1))
if (font->face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
{
/* I do not know the significance of the constant 0xf000. */
/* It was determined by inspection of the character codes */
/* stored in Microsoft font symbol.ttf */
len = gdTcl_UtfToUniChar (next, &ch);
ch |= 0xf000;
next += len;
} else
/* I do not know the significance of the constant 0xf000. */
/* It was determined by inspection of the character codes */
/* stored in Microsoft font symbol.ttf */
len = gdTcl_UtfToUniChar (next, &ch);
ch |= 0xf000;
next += len;
}
else
#endif /* Freetype 2.1 or better */
/* EAM DEBUG */
switch (m)
{
case gdFTEX_Unicode:
if (font->have_char_map_unicode)
{
/* use UTF-8 mapping from ASCII */
len = gdTcl_UtfToUniChar (next, &ch);
next += len;
}
break;
case gdFTEX_Shift_JIS:
if (font->have_char_map_sjis)
{
unsigned char c;
int jiscode;
c = *next;
if (0xA1 <= c && c <= 0xFE)
{
next++;
jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F);
ch = (jiscode >> 8) & 0xFF;
jiscode &= 0xFF;
if (ch & 1)
jiscode += 0x40 - 0x21;
else
jiscode += 0x9E - 0x21;
if (jiscode >= 0x7F)
jiscode++;
ch = (ch - 0x21) / 2 + 0x81;
if (ch >= 0xA0)
ch += 0x40;
ch = (ch << 8) + jiscode;
}
else
{
ch = c & 0xFF; /* don't extend sign */
}
next++;
}
break;
case gdFTEX_Big5:
switch (m)
{
/*
* Big 5 mapping:
* use "JIS-8 half-width katakana" coding from 8-bit characters. Ref:
* ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs
*/
ch = (*next) & 0xFF; /* don't extend sign */
next++;
if (ch >= 161 /* first code of JIS-8 pair */
&& *next)
{ /* don't advance past '\0' */
/* TBB: Fix from Kwok Wah On: & 255 needed */
ch = (ch * 256) + ((*next) & 255);
case gdFTEX_Unicode:
if (font->have_char_map_unicode)
{
/* use UTF-8 mapping from ASCII */
len = gdTcl_UtfToUniChar (next, &ch);
next += len;
}
break;
case gdFTEX_Shift_JIS:
if (font->have_char_map_sjis)
{
unsigned char c;
int jiscode;
c = *next;
if (0xA1 <= c && c <= 0xFE)
{
next++;
jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F);
ch = (jiscode >> 8) & 0xFF;
jiscode &= 0xFF;
if (ch & 1)
jiscode += 0x40 - 0x21;
else
jiscode += 0x9E - 0x21;
if (jiscode >= 0x7F)
jiscode++;
ch = (ch - 0x21) / 2 + 0x81;
if (ch >= 0xA0)
ch += 0x40;
ch = (ch << 8) + jiscode;
}
else
{
ch = c & 0xFF; /* don't extend sign */
}
next++;
}
break;
case gdFTEX_Big5:
{
/*
* Big 5 mapping:
* use "JIS-8 half-width katakana" coding from 8-bit characters. Ref:
* ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs
*/
ch = (*next) & 0xFF; /* don't extend sign */
next++;
if (ch >= 161 /* first code of JIS-8 pair */
&& *next)
{ /* don't advance past '\0' */
/* TBB: Fix from Kwok Wah On: & 255 needed */
ch = (ch * 256) + ((*next) & 255);
next++;
}
}
break;
}
break;
}
/* set rotation transform */
FT_Set_Transform (face, &matrix, NULL);
/* Convert character code to glyph index */
@ -1144,7 +1167,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (err)
{
gdCacheDelete (tc_cache);
gdMutexUnlock(gdFontCacheMutex);
gdMutexUnlock (gdFontCacheMutex);
return "Problem loading glyph";
}
@ -1188,7 +1211,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (err)
{
gdCacheDelete (tc_cache);
gdMutexUnlock(gdFontCacheMutex);
gdMutexUnlock (gdFontCacheMutex);
return "Problem rendering glyph";
}
}
@ -1242,7 +1265,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (tmpstr)
gdFree (tmpstr);
gdCacheDelete (tc_cache);
gdMutexUnlock(gdFontCacheMutex);
gdMutexUnlock (gdFontCacheMutex);
return (char *) NULL;
}

View File

@ -20,180 +20,200 @@
#define MAXY(x) MAX4(x[1],x[3],x[5],x[7])
#define MINY(x) MIN4(x[1],x[3],x[5],x[7])
char *gdImageStringFTCircle(
gdImagePtr im,
int cx,
int cy,
double radius,
double textRadius,
double fillPortion,
char *font,
double points,
char *top,
char *bottom,
int fgcolor)
char *
gdImageStringFTCircle (gdImagePtr im,
int cx,
int cy,
double radius,
double textRadius,
double fillPortion,
char *font,
double points, char *top, char *bottom, int fgcolor)
{
char *err;
int w;
int brect[8];
int sx1, sx2, sy1, sy2, sx, sy;
int x, y;
int fr, fg, fb, fa;
int ox, oy;
double prop;
gdImagePtr im1;
gdImagePtr im2;
gdImagePtr im3;
/* obtain brect so that we can size the image */
err = gdImageStringFT ((gdImagePtr) NULL,
&brect[0], 0, font, points * MAG, 0, 0, 0, bottom);
if (err)
char *err;
int w;
int brect[8];
int sx1, sx2, sy1, sy2, sx, sy;
int x, y;
int fr, fg, fb, fa;
int ox, oy;
double prop;
gdImagePtr im1;
gdImagePtr im2;
gdImagePtr im3;
/* obtain brect so that we can size the image */
err = gdImageStringFT ((gdImagePtr) NULL,
&brect[0], 0, font, points * MAG, 0, 0, 0, bottom);
if (err)
{
return err;
}
sx1 = MAXX (brect) - MINX (brect) + 6;
sy1 = MAXY (brect) - MINY (brect) + 6;
err = gdImageStringFT ((gdImagePtr) NULL,
&brect[0], 0, font, points * MAG, 0, 0, 0, top);
if (err)
{
return err;
}
sx2 = MAXX (brect) - MINX (brect) + 6;
sy2 = MAXY (brect) - MINY (brect) + 6;
/* Pad by 4 pixels to allow for slight errors
observed in the bounding box returned by freetype */
if (sx1 > sx2)
{
sx = sx1 * 2 + 4;
}
else
{
sx = sx2 * 2 + 4;
}
if (sy1 > sy2)
{
sy = sy1;
}
else
{
sy = sy2;
}
im1 = gdImageCreateTrueColor (sx, sy);
if (!im1)
{
return "could not create first image";
}
err = gdImageStringFT (im1, 0, gdTrueColor (255, 255, 255),
font, points * MAG,
0, ((sx / 2) - sx1) / 2, points * MAG, bottom);
if (err)
{
gdImageDestroy (im1);
return err;
}
/* We don't know the descent, which would be needed to do this
with the angle parameter. Instead, implement a simple
flip operation ourselves. */
err = gdImageStringFT (im1, 0, gdTrueColor (255, 255, 255),
font, points * MAG,
0, sx / 2 + ((sx / 2) - sx2) / 2, points * MAG, top);
if (err)
{
gdImageDestroy (im1);
return err;
}
/* Flip in place is tricky, be careful not to double-swap things */
if (sy & 1)
{
for (y = 0; (y <= (sy / 2)); y++)
{
return err;
int xlimit = sx - 2;
if (y == (sy / 2))
{
/* If there is a "middle" row, be careful
not to swap twice! */
xlimit -= (sx / 4);
}
for (x = (sx / 2) + 2; (x < xlimit); x++)
{
int t;
int ox = sx - x + (sx / 2) - 1;
int oy = sy - y - 1;
t = im1->tpixels[oy][ox];
im1->tpixels[oy][ox] = im1->tpixels[y][x];
im1->tpixels[y][x] = t;
}
}
sx1 = MAXX (brect) - MINX (brect) + 6;
sy1 = MAXY (brect) - MINY (brect) + 6;
err = gdImageStringFT ((gdImagePtr) NULL,
&brect[0], 0, font, points * MAG, 0, 0, 0, top);
if (err)
}
else
{
for (y = 0; (y < (sy / 2)); y++)
{
return err;
}
sx2 = MAXX (brect) - MINX (brect) + 6;
sy2 = MAXY (brect) - MINY (brect) + 6;
/* Pad by 4 pixels to allow for slight errors
observed in the bounding box returned by freetype */
if (sx1 > sx2) {
sx = sx1 * 2 + 4;
} else {
sx = sx2 * 2 + 4;
}
if (sy1 > sy2) {
sy = sy1;
} else {
sy = sy2;
}
im1 = gdImageCreateTrueColor(sx, sy);
if (!im1) {
return "could not create first image";
}
err = gdImageStringFT (im1, 0, gdTrueColor(255, 255, 255),
font, points * MAG,
0, ((sx / 2) - sx1) / 2, points * MAG, bottom);
if (err) {
gdImageDestroy(im1);
return err;
}
/* We don't know the descent, which would be needed to do this
with the angle parameter. Instead, implement a simple
flip operation ourselves. */
err = gdImageStringFT (im1, 0, gdTrueColor(255, 255, 255),
font, points * MAG,
0, sx / 2 + ((sx / 2) - sx2) / 2, points * MAG, top);
if (err) {
gdImageDestroy(im1);
return err;
}
/* Flip in place is tricky, be careful not to double-swap things */
if (sy & 1) {
for (y = 0; (y <= (sy / 2)); y++) {
int xlimit = sx - 2;
if (y == (sy / 2)) {
/* If there is a "middle" row, be careful
not to swap twice! */
xlimit -= (sx / 4);
}
for (x = (sx / 2) + 2; (x < xlimit); x++) {
int t;
int ox = sx - x + (sx / 2) - 1;
int oy = sy - y - 1;
t = im1->tpixels[oy][ox];
im1->tpixels[oy][ox] = im1->tpixels[y][x];
im1->tpixels[y][x] = t;
}
}
} else {
for (y = 0; (y < (sy / 2)); y++) {
int xlimit = sx - 2;
for (x = (sx / 2) + 2; (x < xlimit); x++) {
int t;
int ox = sx - x + (sx / 2) - 1;
int oy = sy - y - 1;
t = im1->tpixels[oy][ox];
im1->tpixels[oy][ox] = im1->tpixels[y][x];
im1->tpixels[y][x] = t;
}
}
int xlimit = sx - 2;
for (x = (sx / 2) + 2; (x < xlimit); x++)
{
int t;
int ox = sx - x + (sx / 2) - 1;
int oy = sy - y - 1;
t = im1->tpixels[oy][ox];
im1->tpixels[oy][ox] = im1->tpixels[y][x];
im1->tpixels[y][x] = t;
}
}
}
#if STEP_PNGS
{
FILE *out = fopen("gdfx1.png", "wb");
gdImagePng(im1, out);
fclose(out);
}
{
FILE *out = fopen ("gdfx1.png", "wb");
gdImagePng (im1, out);
fclose (out);
}
#endif /* STEP_PNGS */
/* Resample taller; the exact proportions of the text depend on the
ratio of textRadius to radius, and the value of fillPortion */
if (sx > sy * 10) {
w = sx;
} else {
w = sy * 10;
}
im2 = gdImageCreateTrueColor(w, w);
if (!im2) {
gdImageDestroy(im1);
return "could not create resampled image";
}
prop = textRadius / radius;
gdImageCopyResampled(im2, im1,
gdImageSX(im2) * (1.0 - fillPortion) / 4,
sy * 10 * (1.0 - prop),
0, 0,
gdImageSX(im2) * fillPortion / 2, sy * 10 * prop,
gdImageSX(im1) / 2, gdImageSY(im1));
gdImageCopyResampled(im2, im1,
(gdImageSX(im2) / 2) +
gdImageSX(im2) * (1.0 - fillPortion) / 4,
sy * 10 * (1.0 - prop),
gdImageSX(im1) / 2, 0,
gdImageSX(im2) * fillPortion / 2, sy * 10 * prop,
gdImageSX(im1) / 2, gdImageSY(im1));
/* Resample taller; the exact proportions of the text depend on the
ratio of textRadius to radius, and the value of fillPortion */
if (sx > sy * 10)
{
w = sx;
}
else
{
w = sy * 10;
}
im2 = gdImageCreateTrueColor (w, w);
if (!im2)
{
gdImageDestroy (im1);
return "could not create resampled image";
}
prop = textRadius / radius;
gdImageCopyResampled (im2, im1,
gdImageSX (im2) * (1.0 - fillPortion) / 4,
sy * 10 * (1.0 - prop),
0, 0,
gdImageSX (im2) * fillPortion / 2, sy * 10 * prop,
gdImageSX (im1) / 2, gdImageSY (im1));
gdImageCopyResampled (im2, im1,
(gdImageSX (im2) / 2) +
gdImageSX (im2) * (1.0 - fillPortion) / 4,
sy * 10 * (1.0 - prop),
gdImageSX (im1) / 2, 0,
gdImageSX (im2) * fillPortion / 2, sy * 10 * prop,
gdImageSX (im1) / 2, gdImageSY (im1));
#if STEP_PNGS
{
FILE *out = fopen("gdfx2.png", "wb");
gdImagePng(im2, out);
fclose(out);
}
{
FILE *out = fopen ("gdfx2.png", "wb");
gdImagePng (im2, out);
fclose (out);
}
#endif /* STEP_PNGS */
/* Ready to produce a circle */
im3 = gdImageSquareToCircle(im2, radius);
gdImageDestroy(im1);
gdImageDestroy(im2);
/* Now blend im3 with the destination. Cheat a little. The
source (im3) is white-on-black, so we can use the
red component as a basis for alpha as long as we're
careful to shift off the extra bit and invert
(alpha ranges from 0 to 127 where 0 is OPAQUE).
Also be careful to allow for an alpha component
in the fgcolor parameter itself (gug!) */
fr = gdTrueColorGetRed(fgcolor);
fg = gdTrueColorGetGreen(fgcolor);
fb = gdTrueColorGetBlue(fgcolor);
fa = gdTrueColorGetAlpha(fgcolor);
ox = cx - (im3->sx / 2);
oy = cy - (im3->sy / 2);
for (y = 0; (y < im3->sy); y++) {
for (x = 0; (x < im3->sx); x++) {
int a = gdTrueColorGetRed(im3->tpixels[y][x]) >> 1;
a *= (127 - fa);
a /= 127;
a = 127 - a;
gdImageSetPixel(im, x + ox, y + oy,
gdTrueColorAlpha(fr, fg, fb, a));
}
}
gdImageDestroy(im3);
return 0;
/* Ready to produce a circle */
im3 = gdImageSquareToCircle (im2, radius);
gdImageDestroy (im1);
gdImageDestroy (im2);
/* Now blend im3 with the destination. Cheat a little. The
source (im3) is white-on-black, so we can use the
red component as a basis for alpha as long as we're
careful to shift off the extra bit and invert
(alpha ranges from 0 to 127 where 0 is OPAQUE).
Also be careful to allow for an alpha component
in the fgcolor parameter itself (gug!) */
fr = gdTrueColorGetRed (fgcolor);
fg = gdTrueColorGetGreen (fgcolor);
fb = gdTrueColorGetBlue (fgcolor);
fa = gdTrueColorGetAlpha (fgcolor);
ox = cx - (im3->sx / 2);
oy = cy - (im3->sy / 2);
for (y = 0; (y < im3->sy); y++)
{
for (x = 0; (x < im3->sx); x++)
{
int a = gdTrueColorGetRed (im3->tpixels[y][x]) >> 1;
a *= (127 - fa);
a /= 127;
a = 127 - a;
gdImageSetPixel (im, x + ox, y + oy,
gdTrueColorAlpha (fr, fg, fb, a));
}
}
gdImageDestroy (im3);
return 0;
}
#if GDFX_MAIN
@ -201,46 +221,51 @@ char *gdImageStringFTCircle(
int
main (int argc, char *argv[])
{
FILE *in;
FILE *out;
gdImagePtr im;
int radius;
/* Create an image of text on a circle, with an
alpha channel so that we can copy it onto a
background */
in = fopen("eleanor.jpg", "rb");
if (!in) {
im = gdImageCreateTrueColor(300, 300);
} else {
im = gdImageCreateFromJpeg(in);
fclose(in);
}
if (gdImageSX(im) < gdImageSY(im)) {
radius = gdImageSX(im) / 2;
} else {
radius = gdImageSY(im) / 2;
}
gdStringFTCircle(
im,
gdImageSX(im) / 2,
gdImageSY(im) / 2,
radius,
radius / 2,
0.8,
"arial",
24,
"top text",
"bottom text",
gdTrueColorAlpha(240, 240, 255, 32));
out = fopen("gdfx.png", "wb");
if (!out) {
fprintf(stderr, "Can't create gdfx.png\n");
return 1;
}
gdImagePng(im, out);
fclose(out);
gdImageDestroy(im);
return 0;
FILE *in;
FILE *out;
gdImagePtr im;
int radius;
/* Create an image of text on a circle, with an
alpha channel so that we can copy it onto a
background */
in = fopen ("eleanor.jpg", "rb");
if (!in)
{
im = gdImageCreateTrueColor (300, 300);
}
else
{
im = gdImageCreateFromJpeg (in);
fclose (in);
}
if (gdImageSX (im) < gdImageSY (im))
{
radius = gdImageSX (im) / 2;
}
else
{
radius = gdImageSY (im) / 2;
}
gdStringFTCircle (im,
gdImageSX (im) / 2,
gdImageSY (im) / 2,
radius,
radius / 2,
0.8,
"arial",
24,
"top text",
"bottom text", gdTrueColorAlpha (240, 240, 255, 32));
out = fopen ("gdfx.png", "wb");
if (!out)
{
fprintf (stderr, "Can't create gdfx.png\n");
return 1;
}
gdImagePng (im, out);
fclose (out);
gdImageDestroy (im);
return 0;
}
#endif /* GDFX_MAIN */
@ -250,70 +275,90 @@ main (int argc, char *argv[])
#define SUPERBITS1 1
#define SUPERBITS2 2
gdImagePtr gdImageSquareToCircle(gdImagePtr im, int radius)
gdImagePtr
gdImageSquareToCircle (gdImagePtr im, int radius)
{
int x, y;
double c;
gdImagePtr im2;
if (im->sx != im->sy) {
/* Source image must be square */
return 0;
int x, y;
double c;
gdImagePtr im2;
if (im->sx != im->sy)
{
/* Source image must be square */
return 0;
}
im2 = gdImageCreateTrueColor (radius * 2, radius * 2);
/* Supersampling for a nicer result */
c = (im2->sx / 2) * SUPER;
for (y = 0; (y < im2->sy * SUPER); y++)
{
for (x = 0; (x < im2->sx * SUPER); x++)
{
double rho = sqrt ((x - c) * (x - c) + (y - c) * (y - c));
int pix;
int cpix;
double theta;
double ox;
double oy;
int red, green, blue, alpha;
if (rho > c)
{
continue;
}
theta = atan2 (x - c, y - c) + PI / 2;
if (theta < 0)
{
theta += 2 * PI;
}
/* Undo supersampling */
oy = (rho * im->sx) / (im2->sx * SUPER / 2);
ox = theta * im->sx / (3.141592653 * 2);
pix = gdImageGetPixel (im, ox, oy);
cpix = im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1];
red =
(gdImageRed (im, pix) >> SUPERBITS2) + gdTrueColorGetRed (cpix);
green =
(gdImageGreen (im, pix) >> SUPERBITS2) +
gdTrueColorGetGreen (cpix);
blue =
(gdImageBlue (im, pix) >> SUPERBITS2) + gdTrueColorGetBlue (cpix);
alpha =
(gdImageAlpha (im, pix) >> SUPERBITS2) +
gdTrueColorGetAlpha (cpix);
im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1] =
gdTrueColorAlpha (red, green, blue, alpha);
}
im2 = gdImageCreateTrueColor(radius * 2, radius * 2);
/* Supersampling for a nicer result */
c = (im2->sx / 2) * SUPER;
for (y = 0; (y < im2->sy * SUPER); y++) {
for (x = 0; (x < im2->sx * SUPER); x++) {
double rho = sqrt((x - c) * (x - c) +
(y - c) * (y - c));
int pix;
int cpix;
double theta;
double ox;
double oy;
int red, green, blue, alpha;
if (rho > c) {
continue;
}
theta = atan2(x - c, y - c) + PI / 2;
if (theta < 0) {
theta += 2 * PI;
}
/* Undo supersampling */
oy = (rho * im->sx) / (im2->sx * SUPER / 2);
ox = theta * im->sx / (3.141592653 * 2);
pix = gdImageGetPixel(im, ox, oy);
cpix = im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1];
red = (gdImageRed(im, pix) >> SUPERBITS2) + gdTrueColorGetRed(cpix);
green = (gdImageGreen(im, pix) >> SUPERBITS2) + gdTrueColorGetGreen(cpix);
blue = (gdImageBlue(im, pix) >> SUPERBITS2) + gdTrueColorGetBlue(cpix);
alpha = (gdImageAlpha(im, pix) >> SUPERBITS2) + gdTrueColorGetAlpha(cpix);
im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1] = gdTrueColorAlpha(
red, green, blue, alpha);
}
}
/* Restore full dynamic range, 0-63 yields 0-252. Replication of
first 2 bits in last 2 bits has the desired effect. Note
slightly different arithmetic for alpha which is 7-bit.
NOTE: only correct for SUPER == 2 */
for (y = 0; (y < im2->sy); y++) {
for (x = 0; (x < im2->sx); x++) {
/* Copy first 2 bits to last 2 bits, matching the
dynamic range of the original cheaply */
int cpix = im2->tpixels[y][x];
}
/* Restore full dynamic range, 0-63 yields 0-252. Replication of
first 2 bits in last 2 bits has the desired effect. Note
slightly different arithmetic for alpha which is 7-bit.
NOTE: only correct for SUPER == 2 */
for (y = 0; (y < im2->sy); y++)
{
for (x = 0; (x < im2->sx); x++)
{
/* Copy first 2 bits to last 2 bits, matching the
dynamic range of the original cheaply */
int cpix = im2->tpixels[y][x];
im2->tpixels[y][x] = gdTrueColorAlpha(
(gdTrueColorGetRed(cpix) & 0xFC) +
((gdTrueColorGetRed(cpix) & 0xC0) >> 6),
(gdTrueColorGetGreen(cpix) & 0xFC) +
((gdTrueColorGetGreen(cpix) & 0xC0) >> 6),
(gdTrueColorGetBlue(cpix) & 0xFC) +
((gdTrueColorGetBlue(cpix) & 0xC0) >> 6),
(gdTrueColorGetAlpha(cpix) & 0x7C) +
((gdTrueColorGetAlpha(cpix) & 0x60) >> 6));
}
}
return im2;
im2->tpixels[y][x] = gdTrueColorAlpha ((gdTrueColorGetRed (cpix) &
0xFC) +
((gdTrueColorGetRed (cpix) &
0xC0) >> 6),
(gdTrueColorGetGreen (cpix) &
0xFC) +
((gdTrueColorGetGreen (cpix)
& 0xC0) >> 6),
(gdTrueColorGetBlue (cpix) &
0xFC) +
((gdTrueColorGetBlue (cpix) &
0xC0) >> 6),
(gdTrueColorGetAlpha (cpix) &
0x7C) +
((gdTrueColorGetAlpha (cpix)
& 0x60) >> 6));
}
}
return im2;
}
/* 2.0.16: Called by gdImageSharpen to avoid excessive code repetition
@ -323,40 +368,47 @@ gdImagePtr gdImageSquareToCircle(gdImagePtr im, int radius)
returns new colour for centre pixel
*/
int gdImageSubSharpen (int pc, int c, int nc, float inner_coeff, float
outer_coeff) {
float red, green, blue, alpha;
int
gdImageSubSharpen (int pc, int c, int nc, float inner_coeff, float
outer_coeff)
{
float red, green, blue, alpha;
red = inner_coeff * gdTrueColorGetRed (c) + outer_coeff *
(gdTrueColorGetRed (pc) + gdTrueColorGetRed (nc));
green = inner_coeff * gdTrueColorGetGreen (c) + outer_coeff *
(gdTrueColorGetGreen (pc) + gdTrueColorGetGreen (nc));
blue = inner_coeff * gdTrueColorGetBlue (c) + outer_coeff *
(gdTrueColorGetBlue (pc) + gdTrueColorGetBlue (nc));
alpha = gdTrueColorGetAlpha (c);
red = inner_coeff * gdTrueColorGetRed (c) + outer_coeff *
(gdTrueColorGetRed (pc) + gdTrueColorGetRed (nc));
green = inner_coeff * gdTrueColorGetGreen (c) + outer_coeff *
(gdTrueColorGetGreen (pc) + gdTrueColorGetGreen (nc));
blue = inner_coeff * gdTrueColorGetBlue (c) + outer_coeff *
(gdTrueColorGetBlue (pc) + gdTrueColorGetBlue (nc));
alpha = gdTrueColorGetAlpha (c);
/* Clamping, as can overshoot bounds in either direction */
if (red > 255.0f) {
red = 255.0f;
}
if (green > 255.0f) {
green = 255.0f;
}
if (blue > 255.0f) {
blue = 255.0f;
}
if (red < 0.0f) {
red = 0.0f;
}
if (green < 0.0f) {
green = 0.0f;
}
if (blue < 0.0f) {
blue = 0.0f;
}
/* Clamping, as can overshoot bounds in either direction */
if (red > 255.0f)
{
red = 255.0f;
}
if (green > 255.0f)
{
green = 255.0f;
}
if (blue > 255.0f)
{
blue = 255.0f;
}
if (red < 0.0f)
{
red = 0.0f;
}
if (green < 0.0f)
{
green = 0.0f;
}
if (blue < 0.0f)
{
blue = 0.0f;
}
return gdTrueColorAlpha ((int) red, (int) green, (int) blue,
(int) alpha);
return gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha);
}
/*
@ -370,84 +422,88 @@ outer_coeff) {
* Silently does nothing for pct<0, as not a useful blurring function
* Leaves transparency/alpha-channel untouched
*/
void gdImageSharpen (gdImagePtr im, int pct)
void
gdImageSharpen (gdImagePtr im, int pct)
{
int x, y;
int sx, sy;
float inner_coeff, outer_coeff;
int x, y;
int sx, sy;
float inner_coeff, outer_coeff;
sx = im->sx;
sy = im->sy;
sx = im->sx;
sy = im->sy;
/* Must sum to 1 to avoid overall change in brightness.
* Scaling chosen so that pct=100 gives 1-D filter [-1 6 -1]/4,
* resulting in a 2-D filter [1 -6 1; -6 36 -6; 1 -6 1]/16,
* which gives noticeable, but not excessive, sharpening
*/
/* Must sum to 1 to avoid overall change in brightness.
* Scaling chosen so that pct=100 gives 1-D filter [-1 6 -1]/4,
* resulting in a 2-D filter [1 -6 1; -6 36 -6; 1 -6 1]/16,
* which gives noticeable, but not excessive, sharpening
*/
outer_coeff = -pct / 400.0;
inner_coeff = 1 - 2 * outer_coeff;
outer_coeff = -pct / 400.0;
inner_coeff = 1 - 2 * outer_coeff;
/* Don't try to do anything with non-truecolor images, as
pointless,
* nor for pct<=0, as small kernel size leads to nasty
artefacts when blurring
*/
if ( (im->trueColor) && (pct>0) ) {
/* Don't try to do anything with non-truecolor images, as
pointless,
* nor for pct<=0, as small kernel size leads to nasty
artefacts when blurring
*/
if ((im->trueColor) && (pct > 0))
{
/* First pass, 1-D convolution column-wise */
for (x = 0; x < sx; x++) {
/* First pass, 1-D convolution column-wise */
for (x = 0; x < sx; x++)
{
/* pc is colour of previous pixel; c of the
current pixel and nc of the next */
int pc, c, nc;
/* pc is colour of previous pixel; c of the
current pixel and nc of the next */
int pc, c, nc;
/* Replicate edge pixel at image boundary */
pc = gdImageGetPixel (im, x, 0);
/* Replicate edge pixel at image boundary */
pc = gdImageGetPixel (im, x, 0);
/* Stop looping before last pixel to avoid
conditional within loop */
for (y = 0; y < sy-1; y++) {
/* Stop looping before last pixel to avoid
conditional within loop */
for (y = 0; y < sy - 1; y++)
{
c = gdImageGetPixel (im, x, y);
c = gdImageGetPixel (im, x, y);
nc = gdImageGetTrueColorPixel (im, x,
y+1);
nc = gdImageGetTrueColorPixel (im, x, y + 1);
/* Update centre pixel to new colour */
gdImageSetPixel(im, x, y,
gdImageSubSharpen (pc, c, nc, inner_coeff, outer_coeff) );
/* Update centre pixel to new colour */
gdImageSetPixel (im, x, y,
gdImageSubSharpen (pc, c, nc, inner_coeff,
outer_coeff));
/* Save original colour of current
pixel for next time round */
pc = c;
}
/* Save original colour of current
pixel for next time round */
pc = c;
}
/* Deal with last pixel, replicating current
pixel at image boundary */
c = gdImageGetPixel (im, x, y);
gdImageSetPixel(im, x, y, gdImageSubSharpen
(pc, c, c, inner_coeff, outer_coeff) );
}
/* Deal with last pixel, replicating current
pixel at image boundary */
c = gdImageGetPixel (im, x, y);
gdImageSetPixel (im, x, y, gdImageSubSharpen
(pc, c, c, inner_coeff, outer_coeff));
}
/* Second pass, 1-D convolution row-wise */
for (y = 0; y < sy; y++) {
int pc, c, nc;
pc = gdImageGetPixel (im, 0, y);
for (x = 0; x < sx-1; x++) {
int c, nc;
c = gdImageGetPixel (im, x, y);
nc = gdImageGetTrueColorPixel (im, x+1,
y);
gdImageSetPixel(im, x, y,
gdImageSubSharpen (pc, c, nc, inner_coeff, outer_coeff) );
pc = c;
}
c = gdImageGetPixel (im, x, y);
gdImageSetPixel(im, x, y, gdImageSubSharpen
(pc, c, c, inner_coeff, outer_coeff) );
}
}
/* Second pass, 1-D convolution row-wise */
for (y = 0; y < sy; y++)
{
int pc, c, nc;
pc = gdImageGetPixel (im, 0, y);
for (x = 0; x < sx - 1; x++)
{
int c, nc;
c = gdImageGetPixel (im, x, y);
nc = gdImageGetTrueColorPixel (im, x + 1, y);
gdImageSetPixel (im, x, y,
gdImageSubSharpen (pc, c, nc, inner_coeff,
outer_coeff));
pc = c;
}
c = gdImageGetPixel (im, x, y);
gdImageSetPixel (im, x, y, gdImageSubSharpen
(pc, c, c, inner_coeff, outer_coeff));
}
}
}

File diff suppressed because it is too large Load Diff