- sync to 2.0.10
parent
27f8befffa
commit
9fc2ebf3d0
136
src/gd.c
136
src/gd.c
|
@ -11,6 +11,8 @@
|
|||
#include "gd.h"
|
||||
#include "gdhelpers.h"
|
||||
|
||||
#define gdImageBoundsSafeMacro(im, x, y) (!((((y) < 0) || ((y) >= (im)->sy)) || (((x) < 0) || ((x) >= (im)->sx))))
|
||||
|
||||
#ifdef _OSD_POSIX /* BS2000 uses the EBCDIC char set instead of ASCII */
|
||||
#define CHARSET_EBCDIC
|
||||
#define __attribute__(any) /*nothing */
|
||||
|
@ -611,6 +613,75 @@ gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
|
|||
|
||||
}
|
||||
|
||||
/* 2.0.10: before the drawing routines, some code to clip points that are
|
||||
* outside the drawing window. Nick Atty (nick@canalplan.org.uk)
|
||||
*
|
||||
* This is the Sutherland Hodgman Algorithm, as implemented by
|
||||
* Duvanenko, Robbins and Gyurcsik - SH(DRG) for short. See Dr Dobb's
|
||||
* Journal, January 1996, pp107-110 and 116-117
|
||||
*
|
||||
* Given the end points of a line, and a bounding rectangle (which we
|
||||
* know to be from (0,0) to (SX,SY)), adjust the endpoints to be on
|
||||
* the edges of the rectangle if the line should be drawn at all,
|
||||
* otherwise return a failure code */
|
||||
|
||||
/* this does "one-dimensional" clipping: note that the second time it
|
||||
is called, all the x parameters refer to height and the y to width
|
||||
- the comments ignore this (if you can understand it when it's
|
||||
looking at the X parameters, it should become clear what happens on
|
||||
the second call!) The code is simplified from that in the article,
|
||||
as we know that gd images always start at (0,0) */
|
||||
|
||||
static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
|
||||
double m; /* gradient of line */
|
||||
if(*x0 < 0) { /* start of line is left of window */
|
||||
if(*x1 < 0) /* as is the end, so the line never cuts the window */
|
||||
return 0;
|
||||
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
|
||||
/* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
|
||||
*y0 -= m * *x0;
|
||||
*x0 = 0;
|
||||
/* now, perhaps, adjust the far end of the line as well */
|
||||
if(*x1 > maxdim) {
|
||||
*y1 += m * (maxdim - *x1);
|
||||
*x1 = maxdim;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if(*x0 > maxdim) { /* start of line is right of window -
|
||||
complement of above */
|
||||
if(*x1 > maxdim) /* as is the end, so the line misses the window */
|
||||
return 0;
|
||||
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
|
||||
*y0 += m * (maxdim - *x0); /* adjust so point is on the right
|
||||
boundary */
|
||||
*x0 = maxdim;
|
||||
/* now, perhaps, adjust the end of the line */
|
||||
if(*x1 < 0) {
|
||||
*y1 -= m * *x1;
|
||||
*x1 = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* the final case - the start of the line is inside the window */
|
||||
if(*x1 > maxdim) { /* other end is outside to the right */
|
||||
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
|
||||
*y1 += m * (maxdim - *x1);
|
||||
*x1 = maxdim;
|
||||
return 1;
|
||||
}
|
||||
if(*x1 < 0) { /* other end is outside to the left */
|
||||
m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */
|
||||
*y1 -= m * *x1;
|
||||
*x1 = 0;
|
||||
return 1;
|
||||
}
|
||||
/* only get here if both points are inside the window */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* end of line clipping code */
|
||||
|
||||
void
|
||||
gdImageSetPixel (gdImagePtr im, int x, int y, int color)
|
||||
{
|
||||
|
@ -653,7 +724,7 @@ gdImageSetPixel (gdImagePtr im, int x, int y, int color)
|
|||
gdImageTileApply (im, x, y);
|
||||
break;
|
||||
default:
|
||||
if (gdImageBoundsSafe (im, x, y))
|
||||
if (gdImageBoundsSafeMacro (im, x, y))
|
||||
{
|
||||
if (im->trueColor)
|
||||
{
|
||||
|
@ -800,7 +871,7 @@ gdImageTileApply (gdImagePtr im, int x, int y)
|
|||
int
|
||||
gdImageGetPixel (gdImagePtr im, int x, int y)
|
||||
{
|
||||
if (gdImageBoundsSafe (im, x, y))
|
||||
if (gdImageBoundsSafeMacro (im, x, y))
|
||||
{
|
||||
if (im->trueColor)
|
||||
{
|
||||
|
@ -841,6 +912,15 @@ gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
|
|||
int wid;
|
||||
int w, wstart;
|
||||
int thick = im->thick;
|
||||
|
||||
/* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
|
||||
points need to be drawn */
|
||||
|
||||
if(clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) == 0)
|
||||
return;
|
||||
if(clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im)) == 0)
|
||||
return;
|
||||
|
||||
dx = abs (x2 - x1);
|
||||
dy = abs (y2 - y1);
|
||||
if (dy <= dx)
|
||||
|
@ -1162,7 +1242,7 @@ dashedSet (gdImagePtr im, int x, int y, int color,
|
|||
int
|
||||
gdImageBoundsSafe (gdImagePtr im, int x, int y)
|
||||
{
|
||||
return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx))));
|
||||
return gdImageBoundsSafeMacro(im, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1663,6 +1743,18 @@ gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
|
|||
int color)
|
||||
{
|
||||
int x, y;
|
||||
/* Nick Atty: limit the points at the edge. Note that this also
|
||||
nicely kills any plotting for rectangles completely outside the
|
||||
window as it makes the tests in the for loops fail */
|
||||
if(x1 < 0)
|
||||
x1=0;
|
||||
if(x1 > gdImageSX(im))
|
||||
x1=gdImageSX(im);
|
||||
if(y1 < 0)
|
||||
y1 = 0;
|
||||
if(y1 > gdImageSY(im))
|
||||
y1 = gdImageSY(im);
|
||||
|
||||
for (y = y1; (y <= y2); y++)
|
||||
{
|
||||
for (x = x1; (x <= x2); x++)
|
||||
|
@ -1684,16 +1776,18 @@ gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX,
|
|||
if (dst->trueColor)
|
||||
{
|
||||
/* 2.0: much easier when the destination is truecolor. */
|
||||
/* 2.0.10: needs a transparent-index check that is still valid if
|
||||
the source is not truecolor. Thanks to Frank Warmerdam. */
|
||||
for (y = 0; (y < h); y++)
|
||||
{
|
||||
for (x = 0; (x < w); x++)
|
||||
{
|
||||
int c = gdImageGetTrueColorPixel (src, srcX + x,
|
||||
int p = gdImageGetPixel(src, srcX + x, srcY + y);
|
||||
if (p != src->transparent) {
|
||||
int c = gdImageGetTrueColorPixel (src, srcX + x,
|
||||
srcY + y);
|
||||
if (c != src->transparent)
|
||||
{
|
||||
gdImageSetPixel (dst, dstX + x, dstY + y, c);
|
||||
}
|
||||
gdImageSetPixel (dst, dstX + x, dstY + y, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -2101,6 +2195,12 @@ gdImageCopyRotated (gdImagePtr dst,
|
|||
arithmetic. The routine below is shamelessly, gloriously
|
||||
floating point. TBB */
|
||||
|
||||
/* 2.0.10: cast instead of floor() yields 35% performance improvement.
|
||||
Thanks to John Buckman. */
|
||||
|
||||
#define floor2(exp) ((long) exp)
|
||||
/*#define floor2(exp) floor(exp)*/
|
||||
|
||||
void
|
||||
gdImageCopyResampled (gdImagePtr dst,
|
||||
gdImagePtr src,
|
||||
|
@ -2130,18 +2230,18 @@ gdImageCopyResampled (gdImagePtr dst,
|
|||
do
|
||||
{
|
||||
float yportion;
|
||||
if (floor (sy) == floor (sy1))
|
||||
if (floor2 (sy) == floor2 (sy1))
|
||||
{
|
||||
yportion = 1.0 - (sy - floor (sy));
|
||||
yportion = 1.0 - (sy - floor2 (sy));
|
||||
if (yportion > sy2 - sy1)
|
||||
{
|
||||
yportion = sy2 - sy1;
|
||||
}
|
||||
sy = floor (sy);
|
||||
sy = floor2 (sy);
|
||||
}
|
||||
else if (sy == floor (sy2))
|
||||
else if (sy == floor2 (sy2))
|
||||
{
|
||||
yportion = sy2 - floor (sy2);
|
||||
yportion = sy2 - floor2 (sy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2155,18 +2255,18 @@ gdImageCopyResampled (gdImagePtr dst,
|
|||
float xportion;
|
||||
float pcontribution;
|
||||
int p;
|
||||
if (floor (sx) == floor (sx1))
|
||||
if (floor2 (sx) == floor2 (sx1))
|
||||
{
|
||||
xportion = 1.0 - (sx - floor (sx));
|
||||
xportion = 1.0 - (sx - floor2 (sx));
|
||||
if (xportion > sx2 - sx1)
|
||||
{
|
||||
xportion = sx2 - sx1;
|
||||
}
|
||||
sx = floor (sx);
|
||||
sx = floor2 (sx);
|
||||
}
|
||||
else if (sx == floor (sx2))
|
||||
else if (sx == floor2 (sx2))
|
||||
{
|
||||
xportion = sx2 - floor (sx2);
|
||||
xportion = sx2 - floor2 (sx2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
5
src/gd.h
5
src/gd.h
|
@ -218,8 +218,9 @@ extern "C"
|
|||
int h);
|
||||
gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtxPtr in, int srcx, int srcy,
|
||||
int w, int h);
|
||||
|
||||
gdImagePtr gdImageCreateFromXbm (FILE * fd);
|
||||
/* 2.0.10: prototype was missing */
|
||||
gdImagePtr gdImageCreateFromXpm (char *filename);
|
||||
gdImagePtr gdImageCreateFromXbm (FILE * in);
|
||||
|
||||
void gdImageDestroy (gdImagePtr im);
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* Modification 4/18/00 TBB: JPEG_DEBUG rather than just DEBUG,
|
||||
* so VC++ builds don't spew to standard output, causing
|
||||
* major CGI brain damage
|
||||
*
|
||||
* 2.0.10: more efficient gdImageCreateFromJpegCtx, thanks to
|
||||
* Christian Aberger
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -429,8 +432,10 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
|||
}
|
||||
rowptr[0] = row;
|
||||
|
||||
for (i = 0; i < cinfo.output_height; i++)
|
||||
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)
|
||||
{
|
||||
|
@ -438,10 +443,10 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
|||
" returns %u, expected 1\n", nrows);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (j = 0; j < cinfo.output_width; j++)
|
||||
im->tpixels[i][j] = gdTrueColor (row[j * 3], row[j * 3 + 1],
|
||||
row[j * 3 + 2]);
|
||||
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)
|
||||
|
@ -491,7 +496,8 @@ typedef struct
|
|||
gdIOCtx *infile; /* source stream */
|
||||
unsigned char *buffer; /* start of buffer */
|
||||
safeboolean start_of_file; /* have we gotten any data yet? */
|
||||
}
|
||||
|
||||
}
|
||||
my_source_mgr;
|
||||
|
||||
typedef my_source_mgr *my_src_ptr;
|
||||
|
@ -548,35 +554,46 @@ init_source (j_decompress_ptr cinfo)
|
|||
* 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"
|
||||
|
||||
#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)
|
||||
|
||||
while (nbytes < INPUT_BUF_SIZE)
|
||||
{
|
||||
int got = gdGetBuf (src->buffer + nbytes,
INPUT_BUF_SIZE - nbytes,
|
||||
|
||||
int got = gdGetBuf (src->buffer + nbytes,
|
||||
INPUT_BUF_SIZE - nbytes,
|
||||
src->infile);
|
||||
if ((got == EOF) || (got == 0))
|
||||
|
||||
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. */
|
||||
|
||||
/* 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)
|
||||
|
||||
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);
|
||||
|
@ -652,11 +669,11 @@ skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
|||
void
|
||||
term_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
|
||||
|
||||
#if 0
|
||||
/* never used */
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -688,7 +705,8 @@ jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile)
|
|||
src->buffer = (unsigned char *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
INPUT_BUF_SIZE * sizeof (unsigned char));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->pub.init_source = init_source;
|
||||
|
|
|
@ -60,7 +60,7 @@ main (void)
|
|||
im_in = gdImageCreateFromPng (in);
|
||||
fclose (in);
|
||||
/* Now copy, and magnify as we do so */
|
||||
gdImageCopyResized (im_out, im_in, 32, 32, 0, 0, 192, 192, 255, 255);
|
||||
gdImageCopyResampled (im_out, im_in, 32, 32, 0, 0, 192, 192, 255, 255);
|
||||
/* Now display variously rotated space shuttles in a circle of our own */
|
||||
for (a = 0; (a < 360); a += 45)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#include "gd.h"
|
||||
#include "gdhelpers.h"
|
||||
|
||||
#ifndef MSWIN32
|
||||
/* 2.0.10: WIN32, not MSWIN32 */
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
|
|
|
@ -81,7 +81,7 @@ main (int argc, char *argv[])
|
|||
/* create an image just big enough for the string (x3) */
|
||||
sx = MAXX (brect) - MINX (brect) + 6;
|
||||
sy = MAXY (brect) - MINY (brect) + 6;
|
||||
#if 1
|
||||
#if 0
|
||||
/* Would be palette color 8-bit (which of course is still allowed,
|
||||
but not impressive when used with a JPEG background and antialiasing
|
||||
and alpha channel and so on!) */
|
||||
|
@ -189,7 +189,8 @@ main (int argc, char *argv[])
|
|||
fprintf (stderr, "Can't create test/fttest.png\n");
|
||||
exit (1);
|
||||
}
|
||||
#ifdef HAVE_LIBJPEG
|
||||
/* 2.0.10: correct ifdef, thanks to Gabriele Verzeletti */
|
||||
#ifdef HAVE_LIBPNG
|
||||
gdImagePng (im, out);
|
||||
#else
|
||||
fprintf (stderr, "No PNG library support.\n");
|
||||
|
|
Loading…
Reference in New Issue