- sync to 2.0.29

master
pierre 2006-04-05 15:54:20 +00:00
parent a4e6625f81
commit 5742a4107e
9 changed files with 680 additions and 55 deletions

116
src/gd.c
View File

@ -65,7 +65,7 @@ extern int gdSinT[];
static void gdImageBrushApply (gdImagePtr im, int x, int y);
static void gdImageTileApply (gdImagePtr im, int x, int y);
int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy)
{
@ -575,7 +575,8 @@ BGD_DECLARE(void) gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
{
for (y = 0; y < (to->sy); y++)
{
p = gdImageGetPixel (to, x, y);
/* Optimization: no gdImageGetPixel */
p = to->pixels[y][x];
if (xlate[p] == -1)
{
/* This ought to use HWB, but we don't have an alpha-aware
@ -587,7 +588,8 @@ BGD_DECLARE(void) gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
/* p, to->red[p], to->green[p], to->blue[p], to->alpha[p], */
/* xlate[p], from->red[xlate[p]], from->green[xlate[p]], from->blue[xlate[p]], from->alpha[xlate[p]]); */
};
gdImageSetPixel (to, x, y, xlate[p]);
/* Optimization: no gdImageSetPixel */
to->pixels[y][x] = xlate[p];
};
};
@ -924,8 +926,7 @@ BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y)
}
}
int
gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
{
int p = gdImageGetPixel (im, x, y);
if (!im->trueColor)
@ -2063,10 +2064,14 @@ BGD_DECLARE(void) gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX,
int *sty;
/* We only need to use floating point to determine the correct
stretch vector for one line's worth. */
double accum;
if (overflow2(sizeof (int), srcW)) {
return;
}
if (overflow2(sizeof (int), srcH)) {
return;
}
stx = (int *) gdMalloc (sizeof (int) * srcW);
sty = (int *) gdMalloc (sizeof (int) * srcH);
accum = 0;
/* Fixed by Mao Morimoto 2.0.16 */
for (i = 0; (i < srcW); i++)
{
@ -2518,6 +2523,18 @@ fail:
}
BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
{
if (!n)
{
return;
}
gdImageLine (im, p->x, p->y, p[n - 1].x, p[n - 1].y, c);
gdImageOpenPolygon (im, p, n, c);
}
BGD_DECLARE(void) gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
{
int i;
int lx, ly;
@ -2529,7 +2546,6 @@ BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
lx = p->x;
ly = p->y;
gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c);
for (i = 1; (i < n); i++)
{
p++;
@ -2547,8 +2563,10 @@ BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
/* That could help to adjust intersections to produce a nice */
/* interior_extrema. */
#if 0
static void horizontalLine(gdImagePtr im, int minx, int maxx, int y,
int fill_color);
#endif
BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
{
@ -2570,6 +2588,9 @@ BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int
if (!im->polyAllocated)
{
if (overflow2(sizeof (int), n)) {
return;
}
im->polyInts = (int *) gdMalloc (sizeof (int) * n);
im->polyAllocated = n;
}
@ -2611,7 +2632,7 @@ BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int
/*1.4 int interLast = 0; */
/* int dirLast = 0; */
/* int interFirst = 1; */
int yshift = 0;
/* 2.0.26+ int yshift = 0; */
if (c == gdAntiAliased) {
fill_color = im->AA_color;
} else {
@ -2683,7 +2704,10 @@ BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int
{
int minx = im->polyInts[i];
int maxx = im->polyInts[i + 1];
horizontalLine(im, minx, maxx, y, fill_color);
/* 2.0.29: back to gdImageLine to prevent segfaults when
performing a pattern fill */
gdImageLine (im, im->polyInts[i], y, im->polyInts[i + 1], y,
fill_color);
}
}
/* If we are drawing this AA, then redraw the border with AA lines. */
@ -2693,6 +2717,7 @@ BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int
}
}
#if 0
static void horizontalLine(gdImagePtr im, int minx, int maxx, int y,
int fill_color)
{
@ -2715,8 +2740,9 @@ static void horizontalLine(gdImagePtr im, int minx, int maxx, int y,
}
}
}
#endif
inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t);
static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t);
BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
{
@ -2724,6 +2750,9 @@ BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
{
gdFree (im->style);
}
if (overflow2(sizeof (int), noOfPixels)) {
return;
}
im->style = (int *) gdMalloc (sizeof (int) * noOfPixels);
memcpy (im->style, style, sizeof (int) * noOfPixels);
im->styleLength = noOfPixels;
@ -2884,25 +2913,54 @@ BGD_DECLARE(int) gdImageCompare (gdImagePtr im1, gdImagePtr im2)
return cmpStatus;
}
/* Thanks to Frank Warmerdam for this superior implementation
of gdAlphaBlend(), which merges alpha in the
destination color much better. */
BGD_DECLARE(int) gdAlphaBlend (int dst, int src)
{
/* 2.0.12: TBB: alpha in the destination should be a
component of the result. Thanks to Frank Warmerdam for
pointing out the issue. */
return ((((gdTrueColorGetAlpha (src) *
gdTrueColorGetAlpha (dst)) / gdAlphaMax) << 24) +
((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
gdTrueColorGetRed (src) / gdAlphaMax) +
(gdTrueColorGetAlpha (src) *
gdTrueColorGetRed (dst)) / gdAlphaMax) << 16) +
((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
gdTrueColorGetGreen (src) / gdAlphaMax) +
(gdTrueColorGetAlpha (src) *
gdTrueColorGetGreen (dst)) / gdAlphaMax) << 8) +
(((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
gdTrueColorGetBlue (src) / gdAlphaMax) +
(gdTrueColorGetAlpha (src) *
gdTrueColorGetBlue (dst)) / gdAlphaMax));
int src_alpha = gdTrueColorGetAlpha(src);
int dst_alpha, alpha, red, green, blue;
int src_weight, dst_weight, tot_weight;
/* -------------------------------------------------------------------- */
/* Simple cases we want to handle fast. */
/* -------------------------------------------------------------------- */
if( src_alpha == gdAlphaOpaque )
return src;
dst_alpha = gdTrueColorGetAlpha(dst);
if( src_alpha == gdAlphaTransparent )
return dst;
if( dst_alpha == gdAlphaTransparent )
return src;
/* -------------------------------------------------------------------- */
/* What will the source and destination alphas be? Note that */
/* the destination weighting is substantially reduced as the */
/* overlay becomes quite opaque. */
/* -------------------------------------------------------------------- */
src_weight = gdAlphaTransparent - src_alpha;
dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax;
tot_weight = src_weight + dst_weight;
/* -------------------------------------------------------------------- */
/* What red, green and blue result values will we use? */
/* -------------------------------------------------------------------- */
alpha = src_alpha * dst_alpha / gdAlphaMax;
red = (gdTrueColorGetRed(src) * src_weight
+ gdTrueColorGetRed(dst) * dst_weight) / tot_weight;
green = (gdTrueColorGetGreen(src) * src_weight
+ gdTrueColorGetGreen(dst) * dst_weight) / tot_weight;
blue = (gdTrueColorGetBlue(src) * src_weight
+ gdTrueColorGetBlue(dst) * dst_weight) / tot_weight;
/* -------------------------------------------------------------------- */
/* Return merged result. */
/* -------------------------------------------------------------------- */
return ((alpha << 24) + (red << 16) + (green << 8) + blue);
}
BGD_DECLARE(void) gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg)
@ -2969,7 +3027,7 @@ BGD_DECLARE(void) gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, i
#define BLEND_COLOR(a, nc, c, cc) \
nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8);
inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t)
static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t)
{
int dr,dg,db,p,r,g,b;
p = gdImageGetPixel(im,x,y);

123
src/gd.h
View File

@ -1,3 +1,7 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GD_H
#define GD_H 1
@ -11,32 +15,39 @@
and other languages. This breaks ABI compatibility
with previous DLL revs, but it's necessary. */
/* 2.0.29: WIN32 programmers can declare the NONDLL macro if they
wish to build gd as a static library or by directly including
the gd sources in a project. */
#ifndef WIN32
#define NONDLL 1
#endif /* WIN32 */
#ifdef NONDLL
#define BGD_DECLARE(rt) extern rt
#else
#ifdef BGDWIN32
#define BGD_DECLARE(rt) __declspec(dllexport) rt __stdcall
#else
#ifdef WIN32
#define BGD_DECLARE(rt) __declspec(dllimport) rt _stdcall
#else
/* 2.0.19: should be 'extern', especially for font data pointers */
#define BGD_DECLARE(rt) extern rt
#endif /* WIN32 */
#endif /* BGDWIN32 */
#endif /* NONDLL */
/* 2.0.20: for actual storage of exported data, functions don't need this,
currently needed only for font pointers */
#ifdef NONDLL
/* 2.0.25: bring back extern */
#define BGD_EXPORT_DATA_PROT extern
#define BGD_EXPORT_DATA_IMPL
#else
#ifdef BGDWIN32
#define BGD_EXPORT_DATA_PROT __declspec(dllexport) extern
#define BGD_EXPORT_DATA_IMPL __declspec(dllexport)
#else
#ifdef WIN32
#define BGD_EXPORT_DATA_PROT __declspec(dllimport) extern
#define BGD_EXPORT_DATA_IMPL __declspec(dllimport)
#else
/* 2.0.25: bring back extern */
#define BGD_EXPORT_DATA_PROT extern
#define BGD_EXPORT_DATA_IMPL
#endif /* WIN32 */
#endif /* BGDWIN32 */
#endif /* NONDLL */
#ifdef __cplusplus
extern "C"
@ -253,6 +264,8 @@ BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy);
BGD_DECLARE(gdImagePtr) gdImageCreateFromPng (FILE * fd);
BGD_DECLARE(gdImagePtr) gdImageCreateFromPngCtx (gdIOCtxPtr in);
BGD_DECLARE(gdImagePtr) gdImageCreateFromPngPtr (int size, void *data);
/* These read the first frame only */
BGD_DECLARE(gdImagePtr) gdImageCreateFromGif (FILE * fd);
BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx (gdIOCtxPtr in);
BGD_DECLARE(gdImagePtr) gdImageCreateFromGifPtr (int size, void *data);
@ -308,8 +321,16 @@ BGD_DECLARE(void) gdImageDestroy (gdImagePtr im);
allowing for many useful effects. */
BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color);
/* FreeType 2 text output with hook to extra flags */
BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y);
BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
/* translate a fontconfig fontpattern into a fontpath. return NULL if OK, else return error string */
BGD_DECLARE(char *) font_pattern(char **fontpath, char *fontpattern);
/* translate a font file basename, or relative file name, or a list of such, into a fontpath, retun NULL if OK, else return error string */
BGD_DECLARE(char *) font_path(char **fontpath, char *name_list);
/* Now a No-Op, but kept for binary compatibility. */
BGD_DECLARE(void) gdImageAABlend (gdImagePtr im);
@ -381,6 +402,23 @@ BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, char *fon
for in the above order. */
int hdpi; /* if (flags & gdFTEX_RESOLUTION) */
int vdpi; /* if (flags & gdFTEX_RESOLUTION) */
char *xshow; /* if (flags & gdFTEX_XSHOW)
then, on return, xshow is a malloc'ed
string contining xshow position data for
the last string.
NB. The caller is responsible for gdFree'ing
the xshow string.
*/
char *fontpath; /* if (flags & gdFTEX_RETURNFONTPATHNAME)
then, on return, fontpath is a malloc'ed
string containing the actual font file path name
used, which can be interesting when fontconfig
is in use.
The caller is responsible for gdFree'ing the
fontpath string.
*/
}
gdFTStringExtra, *gdFTStringExtraPtr;
@ -388,6 +426,27 @@ BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, char *fon
#define gdFTEX_LINESPACE 1
#define gdFTEX_CHARMAP 2
#define gdFTEX_RESOLUTION 4
#define gdFTEX_DISABLE_KERNING 8
#define gdFTEX_XSHOW 16
/* The default unless gdFTUseFontConfig(1); has been called:
fontlist is a full or partial font file pathname or list thereof
(i.e. just like before 2.0.29) */
#define gdFTEX_FONTPATHNAME 32
/* Necessary to use fontconfig patterns instead of font pathnames
as the fontlist argument, unless gdFTUseFontConfig(1); has
been called. New in 2.0.29 */
#define gdFTEX_FONTCONFIG 64
/* Sometimes interesting when fontconfig is used: the fontpath
element of the structure above will contain a gdMalloc'd string
copy of the actual font file pathname used, if this flag is set
when the call is made */
#define gdFTEX_RETURNFONTPATHNAME 128
/* If flag is nonzero, the fontlist parameter to gdImageStringFT
and gdImageStringFTEx shall be assumed to be a fontconfig font pattern
if fontconfig was compiled into gd. This function returns zero
if fontconfig is not available, nonzero otherwise. */
BGD_DECLARE(int) gdFTUseFontConfig(int flag);
/* These are NOT flags; set one in 'charmap' if you set the
gdFTEX_CHARMAP bit in 'flags'. */
@ -407,6 +466,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f
gdPoint, *gdPointPtr;
BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c);
BGD_DECLARE(void) gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c);
BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c);
/* These functions still work with truecolor images,
@ -492,10 +552,11 @@ BGD_DECLARE(void) gdImageGif (gdImagePtr im, FILE * out);
BGD_DECLARE(void) gdImagePng (gdImagePtr im, FILE * out);
BGD_DECLARE(void) gdImagePngCtx (gdImagePtr im, gdIOCtx * out);
BGD_DECLARE(void) gdImageGifCtx (gdImagePtr im, gdIOCtx * out);
/* 2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all,
1 is FASTEST but produces larger files, 9 provides the best
compression (smallest files) but takes a long time to compress, and
-1 selects the default compiled into the zlib library. */
/* 2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all,
1 is FASTEST but produces larger files, 9 provides the best
compression (smallest files) but takes a long time to compress, and
-1 selects the default compiled into the zlib library. */
BGD_DECLARE(void) gdImagePngEx (gdImagePtr im, FILE * out, int level);
BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * out, int level);
@ -507,7 +568,7 @@ BGD_DECLARE(void) gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out);
BGD_DECLARE(void) gdFree (void *m);
/* Best to free this memory with gdFree(), not free() */
void *gdImageWBMPPtr (gdImagePtr im, int *size, int fg);
BGD_DECLARE(void *) gdImageWBMPPtr (gdImagePtr im, int *size, int fg);
/* 100 is highest quality (there is always a little loss with JPEG).
0 is lowest. 10 is about the lowest useful setting. */
@ -517,6 +578,26 @@ BGD_DECLARE(void) gdImageJpegCtx (gdImagePtr im, gdIOCtx * out, int quality);
/* Best to free this memory with gdFree(), not free() */
BGD_DECLARE(void *) gdImageJpegPtr (gdImagePtr im, int *size, int quality);
/* Legal values for Disposal. gdDisposalNone is always used by
the built-in optimizer if previm is passed. */
enum {
gdDisposalUnknown,
gdDisposalNone,
gdDisposalRestoreBackground,
gdDisposalRestorePrevious
};
BGD_DECLARE(void) gdImageGifAnimBegin(gdImagePtr im, FILE *outFile, int GlobalCM, int Loops);
BGD_DECLARE(void) gdImageGifAnimAdd(gdImagePtr im, FILE *outFile, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm);
BGD_DECLARE(void) gdImageGifAnimEnd(FILE *outFile);
BGD_DECLARE(void) gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtx *out, int GlobalCM, int Loops);
BGD_DECLARE(void) gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtx *out, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm);
BGD_DECLARE(void) gdImageGifAnimEndCtx(gdIOCtx *out);
BGD_DECLARE(void *) gdImageGifAnimBeginPtr(gdImagePtr im, int *size, int GlobalCM, int Loops);
BGD_DECLARE(void *) gdImageGifAnimAddPtr(gdImagePtr im, int *size, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm);
BGD_DECLARE(void *) gdImageGifAnimEndPtr(int *size);
/* A custom data sink. For backwards compatibility. Use
gdIOCtx instead. */
/* The sink function must return -1 on error, otherwise the number
@ -707,11 +788,15 @@ BGD_DECLARE(int) gdImageCompare (gdImagePtr im1, gdImagePtr im2);
/* resolution affects ttf font rendering, particularly hinting */
#define GD_RESOLUTION 96 /* pixels per inch */
/* newfangled special effects */
#include "gdfx.h"
#ifdef __cplusplus
}
#endif
/* newfangled special effects */
#include "gdfx.h"
#endif /* GD_H */
#ifdef __cplusplus
}
#endif

View File

@ -34,5 +34,7 @@ int main(int argc, char **argv)
gdImageGif(im, out);
fclose(out);
gdImageDestroy(im);
return 0;
}

View File

@ -15,7 +15,7 @@
#endif
#include <stdio.h>
#include <errno.h>
/* 2.0.29: no more errno.h, makes windows happy */
#include <math.h>
#include <string.h>
#include <stdlib.h>
@ -649,7 +649,7 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int
Longstanding bug. 01/16/03 */
if (!gdSeek (in, dpos))
{
printf ("Error from seek: %d\n", errno);
fprintf (stderr, "Seek error\n");
goto fail2;
};
GD2_DBG (printf
@ -958,8 +958,7 @@ _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt)
if (gdPutBuf (compData, compLen, out) <= 0)
{
/* Any alternate suggestions for handling this? */
printf ("Error %d on write\n", errno);
fprintf(stderr, "gd write error\n");
};
};
};

View File

@ -3,6 +3,7 @@
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#include "gdhelpers.h"
/* Code drawn from ppmtogif.c, from the pbmplus package
**
@ -90,6 +91,7 @@ static int colorstobpp(int colors);
static void BumpPixel (GifCtx *ctx);
static int GIFNextPixel (gdImagePtr im, GifCtx *ctx);
static void GIFEncode (gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
static void GIFAnimEncode (gdIOCtxPtr fp, int IWidth, int IHeight, int LeftOfs, int TopOfs, int GInterlace, int Transparent, int Delay, int Disposal, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
static void compress (int init_bits, gdIOCtx *outfile, gdImagePtr im, GifCtx *ctx);
static void output (code_int code, GifCtx *ctx);
static void cl_block (GifCtx *ctx);
@ -141,6 +143,322 @@ BGD_DECLARE(void) gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)
}
}
BGD_DECLARE(void *) gdImageGifAnimBeginPtr (gdImagePtr im, int *size, int GlobalCM, int Loops)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
gdImageGifAnimBeginCtx(im, out, GlobalCM, Loops);
rv = gdDPExtractData (out, size);
out->gd_free (out);
return rv;
}
BGD_DECLARE(void) gdImageGifAnimBegin (gdImagePtr im, FILE *outFile, int GlobalCM, int Loops)
{
gdIOCtx *out = gdNewFileCtx (outFile);
gdImageGifAnimBeginCtx (im, out, GlobalCM, Loops);
out->gd_free (out);
}
BGD_DECLARE(void) gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtxPtr out, int GlobalCM, int Loops)
{
int B;
int RWidth, RHeight;
int Resolution;
int ColorMapSize;
int BitsPerPixel;
int Background = 0;
int i;
/* Default is to use global color map */
if (GlobalCM < 0) GlobalCM = 1;
BitsPerPixel = colorstobpp(im->colorsTotal);
ColorMapSize = 1 << BitsPerPixel;
RWidth = im->sx;
RHeight = im->sy;
Resolution = BitsPerPixel;
/*
* Write the Magic header
*/
gdPutBuf("GIF89a", 6, out );
/*
* Write out the screen width and height
*/
gifPutWord( RWidth, out );
gifPutWord( RHeight, out );
/*
* Indicate that there is a global colour map
*/
B = GlobalCM ? 0x80 : 0;
/*
* OR in the resolution
*/
B |= (Resolution - 1) << 5;
/*
* OR in the Bits per Pixel
*/
B |= (BitsPerPixel - 1);
/*
* Write it out
*/
gdPutC( B, out );
/*
* Write out the Background colour
*/
gdPutC( Background, out );
/*
* Byte of 0's (future expansion)
*/
gdPutC( 0, out );
/*
* Write out the Global Colour Map
*/
if (GlobalCM)
for( i=0; i<ColorMapSize; ++i ) {
gdPutC( im->red[i], out );
gdPutC( im->green[i], out );
gdPutC( im->blue[i], out );
}
if (Loops >= 0) {
gdPutBuf( "!\377\13NETSCAPE2.0\3\1", 16, out );
gifPutWord( Loops, out );
gdPutC( 0, out );
}
}
BGD_DECLARE(void *) gdImageGifAnimAddPtr (gdImagePtr im, int *size, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm)
{
void *rv;
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
gdImageGifAnimAddCtx(im, out, LocalCM, LeftOfs, TopOfs, Delay, Disposal, previm);
rv = gdDPExtractData (out, size);
out->gd_free (out);
return rv;
}
BGD_DECLARE(void) gdImageGifAnimAdd (gdImagePtr im, FILE * outFile, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm)
{
gdIOCtx *out = gdNewFileCtx (outFile);
gdImageGifAnimAddCtx (im, out, LocalCM, LeftOfs, TopOfs, Delay, Disposal, previm);
out->gd_free (out);
}
static int
comparewithmap (gdImagePtr im1, gdImagePtr im2, int c1, int c2, int *colorMap)
{
if (!colorMap)
return c1 == c2;
if (-2 != colorMap[c1])
return colorMap[c1] == c2;
return (colorMap[c1] = gdImageColorExactAlpha (im2, im1->red[c1], im1->green[c1], im1->blue[c1], im1->alpha[c1]))
== c2;
}
BGD_DECLARE(void) gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtxPtr out, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm)
{
gdImagePtr pim = 0, tim = im;
int interlace, transparent, BitsPerPixel;
interlace = im->interlace;
transparent = im->transparent;
/* Default is no local color map */
if (LocalCM < 0) LocalCM = 0;
if (im->trueColor) {
/* Expensive, but the only way that produces an
acceptable result: mix down to a palette
based temporary image. */
pim = gdImageCreatePaletteFromTrueColor(im, 1, 256);
if (!pim) {
return;
}
tim = pim;
}
if (previm) {
/* create optimized animation. Compare this image to
the previous image and crop the temporary copy of
current image to include only changed rectangular
area. Also replace unchanged pixels inside this
area with transparent color. Transparent color
needs to be already allocated!
Preconditions:
TopOfs, LeftOfs are assumed 0
Images should be of same size. If not, a temporary
copy is made with the same size as previous image.
*/
gdImagePtr prev_pim = 0, prev_tim = previm;
int x, y;
int min_x;
int min_y = tim->sy;
int max_x;
int max_y;
int colorMap[256];
if (previm->trueColor) {
prev_pim = gdImageCreatePaletteFromTrueColor(previm, 1, 256);
if (!prev_pim) {
return;
}
prev_tim = prev_pim;
}
for (x = 0; x < 256; ++x)
colorMap[x] = -2;
/* First find bounding box of changed areas. */
/* first find the top changed row */
for (y = 0; y < tim->sy; ++y)
for (x = 0; x < tim->sx; ++x)
if (!comparewithmap(prev_tim, tim,
prev_tim->pixels[y][x],
tim->pixels[y][x],
colorMap)) {
min_y = max_y = y;
min_x = max_x = x;
goto break_top;
}
break_top:
if (tim->sy == min_y) {
/* No changes in this frame!! Encode empty image. */
transparent = 0;
min_x = min_y = 1;
max_x = max_y = 0;
} else {
/* Then the bottom row */
for (y = tim->sy - 1; y > min_y; --y)
for (x = 0; x < tim->sx; ++x)
if (!comparewithmap
(prev_tim, tim,
prev_tim->pixels[y][x],
tim->pixels[y][x],
colorMap)) {
max_y = y;
if (x < min_x) min_x = x;
if (x > max_x) max_x = x;
goto break_bot;
}
break_bot:
/* left side */
for (x = 0; x < min_x; ++x)
for (y = min_y; y <= max_y; ++y)
if (!comparewithmap
(prev_tim, tim,
prev_tim->pixels[y][x],
tim->pixels[y][x],
colorMap)) {
min_x = x;
goto break_left;
}
break_left:
/* right side */
for (x = tim->sx-1; x > max_x; --x)
for (y = min_y; y <= max_y; ++y)
if (!comparewithmap
(prev_tim, tim,
prev_tim->pixels[y][x],
tim->pixels[y][x],
colorMap)) {
max_x = x;
goto break_right;
}
break_right:
;
}
LeftOfs = min_x;
TopOfs = min_y;
Disposal = 1;
/* Make a copy of the image with the new offsets.
But only if necessary. */
if (min_x != 0 || max_x != tim->sx-1
|| min_y != 0 || max_y != tim->sy-1
|| transparent >= 0) {
gdImagePtr pim2
= gdImageCreate(max_x-min_x+1, max_y-min_y+1);
if (!pim2) {
if (prev_pim)
gdImageDestroy (prev_pim);
goto fail_end;
}
gdImagePaletteCopy (pim2, LocalCM ? tim : prev_tim);
gdImageCopy (pim2, tim, 0, 0, min_x, min_y,
max_x-min_x+1, max_y-min_y+1);
if (pim)
gdImageDestroy (pim);
tim = pim = pim2;
}
/* now let's compare pixels for transparent
optimization. But only if transparent is set. */
if (transparent >= 0) {
for (y = 0; y < tim->sy; ++y)
for (x = 0; x < tim->sx; ++x)
if (comparewithmap
(prev_tim, tim,
prev_tim->pixels[min_y+y][min_x+x],
tim->pixels[y][x], 0)) {
gdImageSetPixel (tim, x, y,
transparent);
break;
}
}
if (prev_pim)
gdImageDestroy (prev_pim);
}
BitsPerPixel = colorstobpp(tim->colorsTotal);
/* All set, let's do it. */
GIFAnimEncode(
out, tim->sx, tim->sy, LeftOfs, TopOfs, interlace, transparent,
Delay, Disposal, BitsPerPixel,
LocalCM ? tim->red : 0, tim->green, tim->blue, tim);
fail_end:
if (pim) {
/* Destroy palette based temporary image. */
gdImageDestroy( pim);
}
}
BGD_DECLARE(void) gdImageGifAnimEnd(FILE *outFile)
{
#if 1
putc (';', outFile);
#else
gdIOCtx *out = gdNewFileCtx (outFile);
gdImageGifAnimEndCtx (out);
out->gd_free (out);
#endif
}
BGD_DECLARE(void *) gdImageGifAnimEndPtr (int *size)
{
char *rv = (char *) gdMalloc (1);
*rv = ';';
*size = 1;
return (void *)rv;
}
BGD_DECLARE(void) gdImageGifAnimEndCtx(gdIOCtx *out)
{
/*
* Write the GIF file terminator
*/
gdPutC( ';', out );
}
static int
colorstobpp(int colors)
{
@ -406,6 +724,122 @@ GIFEncode(gdIOCtxPtr fp, int GWidth, int GHeight, int GInterlace, int Background
gdPutC( ';', fp );
}
static void
GIFAnimEncode(gdIOCtxPtr fp, int IWidth, int IHeight, int LeftOfs, int TopOfs, int GInterlace, int Transparent, int Delay, int Disposal, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
{
int B;
int ColorMapSize;
int InitCodeSize;
int i;
GifCtx ctx;
ctx.Interlace = GInterlace;
ctx.in_count = 1;
memset(&ctx, 0, sizeof(ctx));
ColorMapSize = 1 << BitsPerPixel;
if (LeftOfs < 0) LeftOfs = 0;
if (TopOfs < 0) TopOfs = 0;
if (Delay < 0) Delay = 100;
if (Disposal < 0) Disposal = 1;
ctx.Width = IWidth;
ctx.Height = IHeight;
/*
* Calculate number of bits we are expecting
*/
ctx.CountDown = (long)ctx.Width * (long)ctx.Height;
/*
* Indicate which pass we are on (if interlace)
*/
ctx.Pass = 0;
/*
* The initial code size
*/
if( BitsPerPixel <= 1 )
InitCodeSize = 2;
else
InitCodeSize = BitsPerPixel;
/*
* Set up the current x and y position
*/
ctx.curx = ctx.cury = 0;
/*
* Write out extension for image animation and looping
*/
gdPutC( '!', fp );
gdPutC( 0xf9, fp );
gdPutC( 4, fp );
gdPutC( (Transparent >= 0 ? 1 : 0)
| (Disposal << 2), fp );
gdPutC( (unsigned char)(Delay & 255), fp );
gdPutC( (unsigned char)((Delay >> 8) & 255), fp );
gdPutC( (unsigned char) Transparent, fp );
gdPutC( 0, fp );
/*
* Write an Image separator
*/
gdPutC( ',', fp );
/*
* Write out the Image header
*/
gifPutWord( LeftOfs, fp );
gifPutWord( TopOfs, fp );
gifPutWord( ctx.Width, fp );
gifPutWord( ctx.Height, fp );
/*
* Indicate that there is a local colour map
*/
B = (Red && Green && Blue) ? 0x80 : 0;
/*
* OR in the interlacing
*/
B |= ctx.Interlace ? 0x40 : 0;
/*
* OR in the Bits per Pixel
*/
B |= (Red && Green && Blue) ? (BitsPerPixel - 1) : 0;
/*
* Write it out
*/
gdPutC( B, fp );
/*
* Write out the Local Colour Map
*/
if (Red && Green && Blue)
for( i=0; i<ColorMapSize; ++i ) {
gdPutC( Red[i], fp );
gdPutC( Green[i], fp );
gdPutC( Blue[i], fp );
}
/*
* Write out the initial code size
*/
gdPutC( InitCodeSize, fp );
/*
* Go and actually compress the data
*/
compress( InitCodeSize+1, fp, im, &ctx );
/*
* Write out a Zero-length packet (to end the series)
*/
gdPutC( 0, fp );
}
/***************************************************************************
*
* GIFCOMPR.C - GIF Image compression routines

View File

@ -1,3 +1,7 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GD_IO_H
#define GD_IO_H 1
@ -45,3 +49,7 @@ void Putchar (int c, gdIOCtx * ctx);
long gdTell (gdIOCtx * ctx);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -199,6 +199,9 @@ dynamicSeek (struct gdIOCtx *ctx, const int pos)
{
return FALSE;
}
if (overflow2(dp->realSize, 2)) {
return FALSE;
}
if (!gdReallocDynamic (dp, dp->realSize * 2))
{
dp->dataGood = FALSE;
@ -375,6 +378,9 @@ appendDynamic (dynamicPtr * dp, const void *src, int size)
{
return FALSE;
}
if (overflow2(dp->realSize, 2)) {
return FALSE;
}
if (!gdReallocDynamic (dp, bytesNeeded * 2))
{
dp->dataGood = FALSE;

View File

@ -37,6 +37,12 @@
#ifdef HAVE_LIBJPEG
#include "gdhelpers.h"
/* JCE undef two symbols that we don't need anymore but which are
may be defined in config.h from ./configure but which are
redefined incompatibly in jpeglib.h */
#undef HAVE_STDDEF_H
#undef HAVE_STDLIB_H
/* 1.8.1: remove dependency on jinclude.h */
#include "jpeglib.h"
#include "jerror.h"
@ -523,9 +529,13 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtx (gdIOCtx * infile)
if (jpeg_finish_decompress (&cinfo) != TRUE)
fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress"
" reports suspended data source\n");
/* Thanks to Truxton Fulton */
/* TBB 2.0.29: we should do our best to read whatever we can read, and a
warning is a warning. A fatal error on warnings doesn't make sense. */
#if 0
/* This was originally added by Truxton Fulton */
if (cinfo.err->num_warnings > 0)
goto error;
#endif
jpeg_destroy_decompress (&cinfo);
gdFree (row);

View File

@ -312,12 +312,21 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromPngCtx (gdIOCtx * infile)
/* allocate space for the PNG image data */
rowbytes = png_get_rowbytes (png_ptr, info_ptr);
if (overflow2(rowbytes, height)) {
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return NULL;
}
if ((image_data = (png_bytep) gdMalloc (rowbytes * height)) == NULL)
{
fprintf (stderr, "gd-png error: cannot allocate image data\n");
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return NULL;
}
if (overflow2(height, sizeof (png_bytep))) {
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
gdFree (image_data);
return NULL;
}
if ((row_pointers =
(png_bytepp) gdMalloc (height * sizeof (png_bytep))) == NULL)
{
@ -715,20 +724,27 @@ BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
int thisPixel;
png_bytep *prow_pointers;
int saveAlphaFlag = im->saveAlphaFlag;
if (overflow2(sizeof (png_bytep), height)) {
return;
}
row_pointers = gdMalloc (sizeof (png_bytep) * height);
if (row_pointers == NULL)
{
fprintf (stderr, "gd-png error: unable to allocate row_pointers\n");
/* 2.0.29: return was missing */
return;
}
prow_pointers = row_pointers;
for (j = 0; j < height; ++j)
{
if ((*prow_pointers =
(png_bytep) gdMalloc (width * channels)) == NULL)
if (overflow2(width, channels) || ((*prow_pointers =
(png_bytep) gdMalloc (width * channels)) == NULL))
{
fprintf (stderr, "gd-png error: unable to allocate rows\n");
for (i = 0; i < j; ++i)
gdFree (row_pointers[i]);
/* 2.0.29: memory leak TBB */
free(row_pointers);
return;
}
pOutputRow = *prow_pointers++;
@ -766,11 +782,16 @@ BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
if (remap)
{
png_bytep *row_pointers;
if (overflow2(sizeof (png_bytep), height)) {
return;
}
row_pointers = gdMalloc (sizeof (png_bytep) * height);
if (row_pointers == NULL)
{
fprintf (stderr,
"gd-png error: unable to allocate row_pointers\n");
/* TBB: return missing */
return;
}
for (j = 0; j < height; ++j)
{
@ -779,6 +800,8 @@ BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
fprintf (stderr, "gd-png error: unable to allocate rows\n");
for (i = 0; i < j; ++i)
gdFree (row_pointers[i]);
/* TBB: memory leak */
gdFree (row_pointers);
return;
}
for (i = 0; i < width; ++i)