- sync to 2.0.29
parent
a4e6625f81
commit
5742a4107e
116
src/gd.c
116
src/gd.c
|
@ -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
123
src/gd.h
|
@ -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
|
||||
|
|
|
@ -34,5 +34,7 @@ int main(int argc, char **argv)
|
|||
gdImageGif(im, out);
|
||||
fclose(out);
|
||||
gdImageDestroy(im);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
434
src/gd_gif_out.c
434
src/gd_gif_out.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
27
src/gd_png.c
27
src/gd_png.c
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue