iliaa Fri Jan 17 13:34:07 2003 EDT
Modified files:
/php4/ext/gd gd.c
/php4/ext/gd/libgd gd.c gd.h gd_gd2.c gd_jpeg.c
Log:
Syncronize bundled GD library with latest GD (2.0.11).
Index: php4/ext/gd/gd.c
diff -u php4/ext/gd/gd.c:1.243 php4/ext/gd/gd.c:1.244
--- php4/ext/gd/gd.c:1.243 Wed Jan 8 13:11:40 2003
+++ php4/ext/gd/gd.c Fri Jan 17 13:34:07 2003
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: gd.c,v 1.243 2003/01/08 18:11:40 iliaa Exp $ */
+/* $Id: gd.c,v 1.244 2003/01/17 18:34:07 iliaa Exp $ */
/* gd 1.2 is copyright 1994, 1995, Quest Protein Database Center,
Cold Spring Harbor Labs. */
@@ -1562,17 +1562,18 @@
*/
static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn,
void (*func_p)())
{
- zval **imgind, **file, **quality;
+ zval **imgind, **file, **quality, **type;
gdImagePtr im;
char *fn = NULL;
FILE *fp;
int argc = ZEND_NUM_ARGS();
- int q = -1, i;
+ int q = -1, i, t = 1;
/* The quality parameter for Wbmp stands for the threshold when called from
image2wbmp() */
/* When called from imagewbmp() the quality parameter stands for the
foreground color. Default: black. */
+ /* The quality parameter for gd2 stands for chunk size */
- if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &imgind, &file,
&quality) == FAILURE) {
+ if (argc < 1 || argc > 4 || zend_get_parameters_ex(argc, &imgind, &file,
+&quality, &type) == FAILURE) {
ZEND_WRONG_PARAM_COUNT();
}
@@ -1585,6 +1586,10 @@
convert_to_long_ex(quality);
q = Z_LVAL_PP(quality);
}
+ if (argc == 4) {
+ convert_to_long_ex(type);
+ t = Z_LVAL_PP(type);
+ }
}
if ((argc == 2) || (argc == 3 && Z_STRLEN_PP(file))) {
@@ -1622,7 +1627,10 @@
break;
#endif
default:
- (*func_p)(im, fp);
+ if (q == -1) {
+ q = 128;
+ }
+ (*func_p)(im, fp, q, t);
break;
}
fflush(fp);
@@ -1749,7 +1757,7 @@
/* }}} */
#ifdef HAVE_GD_GD2
-/* {{{ proto int imagegd2(int im [, string filename])
+/* {{{ proto int imagegd2(int im [, string filename, [, int chunk_size, [, int
+type]]])
Output GD2 image to browser or file */
PHP_FUNCTION(imagegd2)
{
Index: php4/ext/gd/libgd/gd.c
diff -u php4/ext/gd/libgd/gd.c:1.40 php4/ext/gd/libgd/gd.c:1.41
--- php4/ext/gd/libgd/gd.c:1.40 Thu Jan 9 21:00:39 2003
+++ php4/ext/gd/libgd/gd.c Fri Jan 17 13:34:07 2003
@@ -81,6 +81,9 @@
};
#endif /*CHARSET_EBCDIC */
+/* 2.0.10: cast instead of floor() yields 35% performance improvement. Thanks to John
+Buckman. */
+#define floor_cast(exp) ((long) exp)
+
extern int gdCosT[];
extern int gdSinT[];
@@ -661,6 +664,76 @@
}
+/* 2.0.10: before the drawing routines, some code to clip points that are
+ * outside the drawing window. Nick Atty ([EMAIL PROTECTED])
+ *
+ * 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;
+}
+
void
gdImageSetPixel (gdImagePtr im, int x, int y, int color)
{
@@ -871,158 +944,139 @@
void
gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
{
- int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
- int wid;
- int w, wstart;
- int thick = im->thick;
- dx = abs (x2 - x1);
- dy = abs (y2 - y1);
- if (dy <= dx)
- {
- /* More-or-less horizontal. use wid for vertical stroke */
- /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
- if ((dx == 0) && (dy == 0)) {
- wid = 1;
- } else {
- wid = (int)(thick * cos (atan2 (dy, dx)));
- if (wid == 0) {
- wid = 1;
- }
- }
- d = 2 * dy - dx;
- incr1 = 2 * dy;
- incr2 = 2 * (dy - dx);
- if (x1 > x2)
- {
- x = x2;
- y = y2;
- ydirflag = (-1);
- xend = x1;
- }
- else
- {
- x = x1;
- y = y1;
- ydirflag = 1;
- xend = x2;
- }
-
- /* Set up line thickness */
- wstart = y - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- gdImageSetPixel (im, x, w, color);
-
- if (((y2 - y1) * ydirflag) > 0)
- {
- while (x < xend)
- {
- x++;
- if (d < 0)
- {
- d += incr1;
- }
- else
- {
- y++;
- d += incr2;
- }
- wstart = y - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- gdImageSetPixel (im, x, w, color);
- }
- }
- else
- {
- while (x < xend)
- {
- x++;
- if (d < 0)
- {
- d += incr1;
- }
- else
- {
- y--;
- d += incr2;
- }
- wstart = y - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- gdImageSetPixel (im, x, w, color);
- }
- }
- }
- else
- {
- /* More-or-less vertical. use wid for horizontal stroke */
- wid = (int)(thick * sin (atan2 (dy, dx)));
- if (wid == 0)
- wid = 1;
+ int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
+ int wid;
+ int w, wstart;
+ int thick = im->thick;
- d = 2 * dx - dy;
- incr1 = 2 * dx;
- incr2 = 2 * (dx - dy);
- if (y1 > y2)
- {
- y = y2;
- x = x2;
- yend = y1;
- xdirflag = (-1);
- }
- else
- {
- y = y1;
- x = x1;
- yend = y2;
- xdirflag = 1;
+ /* 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)) ||
+!clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im))) {
+ return;
}
-
- /* Set up line thickness */
- wstart = x - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- gdImageSetPixel (im, w, y, color);
-
- if (((x2 - x1) * xdirflag) > 0)
- {
- while (y < yend)
- {
- y++;
- if (d < 0)
- {
- d += incr1;
+
+ dx = abs(x2 - x1);
+ dy = abs(y2 - y1);
+ if (dy <= dx) {
+ /* More-or-less horizontal. use wid for vertical stroke */
+ /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
+ if ((dx == 0) && (dy == 0)) {
+ wid = 1;
+ } else {
+ wid = (int)(thick * cos (atan2 (dy, dx)));
+ if (wid == 0) {
+ wid = 1;
+ }
}
- else
- {
- x++;
- d += incr2;
+ d = 2 * dy - dx;
+ incr1 = 2 * dy;
+ incr2 = 2 * (dy - dx);
+ if (x1 > x2) {
+ x = x2;
+ y = y2;
+ ydirflag = (-1);
+ xend = x1;
+ } else {
+ x = x1;
+ y = y1;
+ ydirflag = 1;
+ xend = x2;
+ }
+
+ /* Set up line thickness */
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetPixel(im, x, w, color);
+ }
+
+ if (((y2 - y1) * ydirflag) > 0) {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y++;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetPixel (im, x, w, color);
+ }
+ }
+ } else {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y--;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetPixel (im, x, w, color);
+ }
+ }
}
- wstart = x - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- gdImageSetPixel (im, w, y, color);
- }
- }
- else
- {
- while (y < yend)
- {
- y++;
- if (d < 0)
- {
- d += incr1;
+ } else {
+ /* More-or-less vertical. use wid for horizontal stroke */
+ wid = (int)(thick * sin (atan2 (dy, dx)));
+ if (wid == 0) {
+ wid = 1;
}
- else
- {
- x--;
- d += incr2;
+
+ d = 2 * dx - dy;
+ incr1 = 2 * dx;
+ incr2 = 2 * (dx - dy);
+ if (y1 > y2) {
+ y = y2;
+ x = x2;
+ yend = y1;
+ xdirflag = (-1);
+ } else {
+ y = y1;
+ x = x1;
+ yend = y2;
+ xdirflag = 1;
+ }
+
+ /* Set up line thickness */
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetPixel (im, w, y, color);
+ }
+
+ if (((x2 - x1) * xdirflag) > 0) {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x++;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetPixel (im, w, y, color);
+ }
+ }
+ } else {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x--;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetPixel (im, w, y, color);
+ }
+ }
}
- wstart = x - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- gdImageSetPixel (im, w, y, color);
- }
}
- }
}
-
#define BLEND_COLOR(a, nc, c, cc) \
nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8);
@@ -1317,13 +1371,6 @@
*onP = on;
}
-int
-gdImageBoundsSafe (gdImagePtr im, int x, int y)
-{
- return (!(((y < 0) || (y >= im->sy)) ||
- ((x < 0) || (x >= im->sx))));
-}
-
void
gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y,
int c, int color)
@@ -1831,154 +1878,127 @@
void
gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
{
- int x, y;
- for (y = y1; (y <= y2); y++)
- {
- for (x = x1; (x <= x2); x++)
- {
- gdImageSetPixel (im, x, y, 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++) {
+ gdImageSetPixel (im, x, y, color);
+ }
}
- }
}
void
gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY,
int w, int h)
{
- int c;
- int x, y;
- int tox, toy;
- int i;
- int colorMap[gdMaxColors];
- if (dst->trueColor)
- {
- /* 2.0: much easier when the destination is truecolor. */
+ int c;
+ int x, y;
+ int tox, toy;
+ int i;
+ int colorMap[gdMaxColors];
+ 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.
+ */
- if (src->trueColor) {
- for (y = 0; (y < h); y++)
- {
- for (x = 0; (x < w); x++)
- {
- int c = gdImageGetTrueColorPixel (src, srcX + x,
- srcY + y);
- gdImageSetPixel (dst,
- dstX + x,
- dstY + y,
- c);
+ if (src->trueColor) {
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ int c = gdImageGetTrueColorPixel (src, srcX +
+x, srcY + y);
+ gdImageSetPixel (dst, dstX + x, dstY + y, c);
}
}
-
- }
- else {
+ } else {
/* source is palette based */
- for (y = 0; (y < h); y++)
- {
- for (x = 0; (x < w); x++)
- {
- int c = gdImageGetPixel (src, srcX + x,
- srcY + y);
- if (c != src->transparent)
- {
- gdImageSetPixel (dst,
- dstX + x,
- dstY + y,
-
gdTrueColor(src->red[c], src->green[c], src->blue[c]));
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ int c = gdImageGetPixel (src, srcX + x, srcY +
+y);
+ if (c != src->transparent) {
+ gdImageSetPixel (dst, dstX + x, dstY +
+y, gdTrueColor(src->red[c], src->green[c], src->blue[c]));
}
+ }
+ }
}
- }
+ return;
}
- return;
- }
- /* Destination is palette based */
+ /* Destination is palette based */
+ if (src->trueColor) { /* But source is truecolor (Ouch!) */
+ toy = dstY;
+ for (y = srcY; (y < (srcY + h)); y++) {
+ tox = dstX;
+ for (x = srcX; (x < (srcX + w)); x++) {
+ int nc;
+ c = gdImageGetPixel (src, x, y);
- if (src->trueColor) { /* But source is truecolor (Ouch!) */
- toy = dstY;
- for (y = srcY; (y < (srcY + h)); y++)
- {
- tox = dstX;
- for (x = srcX; (x < (srcX + w)); x++)
- {
- int nc;
- c = gdImageGetPixel (src, x, y);
-
- /* Get best match possible. */
- nc = gdImageColorResolveAlpha (
- dst,
- gdTrueColorGetRed(c),
- gdTrueColorGetGreen(c),
- gdTrueColorGetBlue(c),
- gdTrueColorGetAlpha(c));
-
- gdImageSetPixel (dst, tox, toy, nc);
- tox++;
- }
- toy++;
- }
- return;
- }
+ /* Get best match possible. */
+ nc = gdImageColorResolveAlpha (dst,
+gdTrueColorGetRed(c), gdTrueColorGetGreen(c), gdTrueColorGetBlue(c),
+gdTrueColorGetAlpha(c));
- /* Palette based to palette based */
+ gdImageSetPixel (dst, tox, toy, nc);
+ tox++;
+ }
+ toy++;
+ }
+ return;
+ }
- for (i = 0; (i < gdMaxColors); i++)
- {
- colorMap[i] = (-1);
- }
- toy = dstY;
- for (y = srcY; (y < (srcY + h)); y++)
- {
- tox = dstX;
- for (x = srcX; (x < (srcX + w)); x++)
- {
- int nc;
- int mapTo;
- c = gdImageGetPixel (src, x, y);
- /* Added 7/24/95: support transparent copies */
- if (gdImageGetTransparent (src) == c)
- {
- tox++;
- continue;
- }
- /* Have we established a mapping for this color? */
- if (src->trueColor)
- {
- /* 2.05: remap to the palette available in the
- destination image. This is slow and
- works badly, but it beats crashing! Thanks
- to Padhrig McCarthy. */
- mapTo = gdImageColorResolveAlpha (dst,
- gdTrueColorGetRed (c),
- gdTrueColorGetGreen (c),
- gdTrueColorGetBlue (c),
- gdTrueColorGetAlpha (c));
- }
- else if (colorMap[c] == (-1))
- {
- /* If it's the same image, mapping is trivial */
- if (dst == src)
- {
- nc = c;
+ /* Palette based to palette based */
+ for (i = 0; (i < gdMaxColors); i++) {
+ colorMap[i] = (-1);
+ }
+ toy = dstY;
+ for (y = srcY; (y < (srcY + h)); y++) {
+ tox = dstX;
+ for (x = srcX; (x < (srcX + w)); x++) {
+ int nc;
+ int mapTo;
+ c = gdImageGetPixel (src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent (src) == c) {
+ tox++;
+ continue;
+ }
+ /* Have we established a mapping for this color? */
+ if (src->trueColor) {
+ /* 2.05: remap to the palette available in the
+destination image. This is slow and
+ * works badly, but it beats crashing! Thanks to
+Padhrig McCarthy.
+ */
+ mapTo = gdImageColorResolveAlpha (dst,
+gdTrueColorGetRed (c), gdTrueColorGetGreen (c), gdTrueColorGetBlue (c),
+gdTrueColorGetAlpha (c));
+ } else if (colorMap[c] == (-1)) {
+ /* If it's the same image, mapping is trivial */
+ if (dst == src) {
+ nc = c;
+ } else {
+ /* Get best match possible. This function
+never returns error. */
+ nc = gdImageColorResolveAlpha (dst,
+src->red[c], src->green[c], src->blue[c], src->alpha[c]);
+ }
+ colorMap[c] = nc;
+ mapTo = colorMap[c];
+ } else {
+ mapTo = colorMap[c];
+ }
+ gdImageSetPixel (dst, tox, toy, mapTo);
+ tox++;
}
- else
- {
- /* Get best match possible. This
- function never returns error. */
- nc = gdImageColorResolveAlpha (
- dst,
- src->red[c], src->green[c],
- src->blue[c], src->alpha[c]);
- }
- colorMap[c] = nc;
- mapTo = colorMap[c];
- }
- else
- {
- mapTo = colorMap[c];
- }
- gdImageSetPixel (dst, tox, toy, mapTo);
- tox++;
+ toy++;
}
- toy++;
- }
}
/* This function is a substitute for real alpha channel operations,
@@ -2230,14 +2250,14 @@
sy = sy1;
do {
float yportion;
- if (floorf(sy) == floorf(sy1)) {
- yportion = 1.0f - (sy - floorf(sy));
+ if (floor_cast(sy) == floor_cast(sy1)) {
+ yportion = 1.0f - (sy - floor_cast(sy));
if (yportion > sy2 - sy1) {
yportion = sy2 - sy1;
}
- sy = floorf(sy);
+ sy = floor_cast(sy);
} else if (sy == floorf(sy2)) {
- yportion = sy2 - floorf(sy2);
+ yportion = sy2 - floor_cast(sy2);
} else {
yportion = 1.0f;
}
@@ -2248,14 +2268,14 @@
float xportion;
float pcontribution;
int p;
- if (floorf(sx) == floorf(sx1)) {
- xportion = 1.0f - (sx - floorf(sx));
+ if (floorf(sx) == floor_cast(sx1)) {
+ xportion = 1.0f - (sx -
+floor_cast(sx));
if (xportion > sx2 - sx1) {
xportion = sx2 - sx1;
}
- sx = floorf(sx);
+ sx = floor_cast(sx);
} else if (sx == floorf(sx2)) {
- xportion = sx2 - floorf(sx2);
+ xportion = sx2 - floor_cast(sx2);
} else {
xportion = 1.0f;
}
Index: php4/ext/gd/libgd/gd.h
diff -u php4/ext/gd/libgd/gd.h:1.13 php4/ext/gd/libgd/gd.h:1.14
--- php4/ext/gd/libgd/gd.h:1.13 Sun Jan 5 19:47:40 2003
+++ php4/ext/gd/libgd/gd.h Fri Jan 17 13:34:07 2003
@@ -256,7 +256,6 @@
void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color);
/* Solid bar. Upper left corner first, lower right corner second. */
void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color);
-int gdImageBoundsSafe(gdImagePtr im, int x, int y);
void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color);
void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color);
void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int
color);
@@ -585,5 +584,7 @@
#ifdef __cplusplus
}
#endif
+
+#define gdImageBoundsSafe(im, x, y) (!(y < 0 || y >= (im)->sy || x < 0 || x >=
+(im)->sx))
#endif /* GD_H */
Index: php4/ext/gd/libgd/gd_gd2.c
diff -u php4/ext/gd/libgd/gd_gd2.c:1.9 php4/ext/gd/libgd/gd_gd2.c:1.10
--- php4/ext/gd/libgd/gd_gd2.c:1.9 Tue Dec 3 10:43:17 2002
+++ php4/ext/gd/libgd/gd_gd2.c Fri Jan 17 13:34:07 2003
@@ -23,902 +23,767 @@
#define TRUE 1
#define FALSE 0
+/* 2.11: not part of the API, as the save routine can figure it out
+ * from im->trueColor, and the load routine doesn't need to tell
+ * the end user the saved format. NOTE: adding 2 is assumed
+ * to result in the correct format value for truecolor!
+*/
+#define GD2_FMT_TRUECOLOR_RAW 3
+#define GD2_FMT_TRUECOLOR_COMPRESSED 4
+
+#define gd2_compressed(fmt) (((fmt) == GD2_FMT_COMPRESSED) || ((fmt) ==
+GD2_FMT_TRUECOLOR_COMPRESSED))
+#define gd2_truecolor(fmt) (((fmt) == GD2_FMT_TRUECOLOR_RAW) || ((fmt) ==
+GD2_FMT_TRUECOLOR_COMPRESSED))
+
/* Use this for commenting out debug-print statements. */
/* Just use the first '#define' to allow all the prints... */
/* #define GD2_DBG(s) (s) */
#define GD2_DBG(s)
typedef struct
- {
- int offset;
- int size;
- }
+{
+ int offset;
+ int size;
+}
t_chunk_info;
-extern int _gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag);
-extern void _gdPutColors (gdImagePtr im, gdIOCtx * out);
+extern int _gdGetColors(gdIOCtx * in, gdImagePtr im, int gd2xFlag);
+extern void _gdPutColors(gdImagePtr im, gdIOCtx * out);
/* */
/* Read the extra info in the gd2 header. */
/* */
-static
-int
-_gd2GetHeader (gdIOCtxPtr in, int *sx, int *sy,
- int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** chunkIdx)
-{
- int i;
- int ch;
- char id[5];
- t_chunk_info *cidx;
- int sidx;
- int nc;
-
- GD2_DBG(php_gd_error("Reading gd2 header info\n"));
-
- for (i = 0; i < 4; i++)
- {
- ch = gdGetC (in);
- if (ch == EOF)
- {
- goto fail1;
- };
- id[i] = ch;
- };
- id[4] = 0;
-
- GD2_DBG(php_gd_error("Got file code: %s\n", id));
-
- /* Equiv. of 'magick'. */
- if (strcmp (id, GD2_ID) != 0)
- {
- GD2_DBG(php_gd_error("Not a valid gd2 file\n"));
- goto fail1;
- };
-
- /* Version */
- if (gdGetWord (vers, in) != 1)
- {
- goto fail1;
- };
- GD2_DBG(php_gd_error("Version: %d\n", *vers));
-
- if ((*vers != 1) && (*vers != 2))
- {
- GD2_DBG(php_gd_error("Bad version: %d\n", *vers));
- goto fail1;
- };
-
- /* Image Size */
- if (!gdGetWord (sx, in))
- {
- GD2_DBG(php_gd_error("Could not get x-size\n"));
- goto fail1;
- }
- if (!gdGetWord (sy, in))
- {
- GD2_DBG(php_gd_error("Could not get y-size\n"));
- goto fail1;
- }
- GD2_DBG(php_gd_error("Image is %dx%d\n", *sx, *sy));
-
- /* Chunk Size (pixels, not bytes!) */
- if (gdGetWord (cs, in) != 1)
- {
- goto fail1;
- };
- GD2_DBG(php_gd_error("ChunkSize: %d\n", *cs));
-
- if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX))
- {
- GD2_DBG(php_gd_error("Bad chunk size: %d\n", *cs));
- goto fail1;
- };
-
- /* Data Format */
- if (gdGetWord (fmt, in) != 1)
- {
- goto fail1;
- };
- GD2_DBG(php_gd_error("Format: %d\n", *fmt));
-
- if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED))
- {
- GD2_DBG(php_gd_error("Bad data format: %d\n", *fmt));
- goto fail1;
- };
-
-
- /* # of chunks wide */
- if (gdGetWord (ncx, in) != 1)
- {
- goto fail1;
- };
- GD2_DBG(php_gd_error("%d Chunks Wide\n", *ncx));
-
- /* # of chunks high */
- if (gdGetWord (ncy, in) != 1)
- {
- goto fail1;
- };
- GD2_DBG(php_gd_error("%d Chunks vertically\n", *ncy));
-
- if ((*fmt) == GD2_FMT_COMPRESSED)
- {
- nc = (*ncx) * (*ncy);
- GD2_DBG(php_gd_error("Reading %d chunk index entries\n", nc));
- sidx = sizeof (t_chunk_info) * nc;
- cidx = gdCalloc (sidx, 1);
- for (i = 0; i < nc; i++)
- {
- if (gdGetInt (&cidx[i].offset, in) != 1)
- {
- goto fail1;
- };
- if (gdGetInt (&cidx[i].size, in) != 1)
- {
- goto fail1;
- };
- };
- *chunkIdx = cidx;
- };
+static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, int
+*fmt, int *ncx, int *ncy, t_chunk_info ** chunkIdx)
+{
+ int i;
+ int ch;
+ char id[5];
+ t_chunk_info *cidx;
+ int sidx;
+ int nc;
+
+ GD2_DBG(php_gd_error("Reading gd2 header info\n"));
+
+ for (i = 0; i < 4; i++) {
+ ch = gdGetC(in);
+ if (ch == EOF) {
+ goto fail1;
+ }
+ id[i] = ch;
+ }
+ id[4] = 0;
+
+ GD2_DBG(php_gd_error("Got file code: %s\n", id));
+
+ /* Equiv. of 'magick'. */
+ if (strcmp(id, GD2_ID) != 0) {
+ GD2_DBG(php_gd_error("Not a valid gd2 file\n"));
+ goto fail1;
+ }
+
+ /* Version */
+ if (gdGetWord(vers, in) != 1) {
+ goto fail1;
+ }
+ GD2_DBG(php_gd_error("Version: %d\n", *vers));
+
+ if ((*vers != 1) && (*vers != 2)) {
+ GD2_DBG(php_gd_error("Bad version: %d\n", *vers));
+ goto fail1;
+ }
+
+ /* Image Size */
+ if (!gdGetWord(sx, in)) {
+ GD2_DBG(php_gd_error("Could not get x-size\n"));
+ goto fail1;
+ }
+ if (!gdGetWord(sy, in)) {
+ GD2_DBG(php_gd_error("Could not get y-size\n"));
+ goto fail1;
+ }
+ GD2_DBG(php_gd_error("Image is %dx%d\n", *sx, *sy));
+
+ /* Chunk Size (pixels, not bytes!) */
+ if (gdGetWord(cs, in) != 1) {
+ goto fail1;
+ }
+ GD2_DBG(php_gd_error("ChunkSize: %d\n", *cs));
+
+ if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) {
+ GD2_DBG(php_gd_error("Bad chunk size: %d\n", *cs));
+ goto fail1;
+ }
+
+ /* Data Format */
+ if (gdGetWord(fmt, in) != 1) {
+ goto fail1;
+ }
+ GD2_DBG(php_gd_error("Format: %d\n", *fmt));
+
+ if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED) && (*fmt !=
+GD2_FMT_TRUECOLOR_RAW) && (*fmt != GD2_FMT_TRUECOLOR_COMPRESSED)) {
+ GD2_DBG(php_gd_error("Bad data format: %d\n", *fmt));
+ goto fail1;
+ }
+
+ /* # of chunks wide */
+ if (gdGetWord(ncx, in) != 1) {
+ goto fail1;
+ }
+ GD2_DBG(php_gd_error("%d Chunks Wide\n", *ncx));
- GD2_DBG(php_gd_error("gd2 header complete\n"));
+ /* # of chunks high */
+ if (gdGetWord(ncy, in) != 1) {
+ goto fail1;
+ }
+ GD2_DBG(php_gd_error("%d Chunks vertically\n", *ncy));
- return 1;
+ if (gd2_compressed(*fmt)) {
+ nc = (*ncx) * (*ncy);
+ GD2_DBG(php_gd_error("Reading %d chunk index entries\n", nc));
+ sidx = sizeof(t_chunk_info) * nc;
+ cidx = gdCalloc(sidx, 1);
+ for (i = 0; i < nc; i++) {
+ if (gdGetInt(&cidx[i].offset, in) != 1) {
+ goto fail1;
+ }
+ if (gdGetInt(&cidx[i].size, in) != 1) {
+ goto fail1;
+ }
+ }
+ *chunkIdx = cidx;
+ }
+
+ GD2_DBG(php_gd_error("gd2 header complete\n"));
+
+ return 1;
fail1:
- return 0;
+ return 0;
}
-static
- gdImagePtr
-_gd2CreateFromFile (gdIOCtxPtr in, int *sx, int *sy,
- int *cs, int *vers, int *fmt,
- int *ncx, int *ncy, t_chunk_info ** cidx)
-{
- gdImagePtr im;
-
- if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1)
- {
- GD2_DBG(php_gd_error("Bad GD2 header\n"));
- goto fail1;
- }
-
- im = gdImageCreateTrueColor(*sx, *sy);
- if (im == NULL)
- {
- GD2_DBG(php_gd_error("Could not create gdImage\n"));
- goto fail1;
- };
-
- if (!_gdGetColors (in, im, (*vers) == 2))
- {
- GD2_DBG(php_gd_error("Could not read color palette\n"));
- goto fail2;
- }
- GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal));
+static gdImagePtr _gd2CreateFromFile (gdIOCtxPtr in, int *sx, int *sy, int *cs, int
+*vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** cidx)
+{
+ gdImagePtr im;
+
+ if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1) {
+ GD2_DBG(php_gd_error("Bad GD2 header\n"));
+ goto fail1;
+ }
- return im;
+ if (gd2_truecolor(*fmt)) {
+ im = gdImageCreateTrueColor(*sx, *sy);
+ } else {
+ im = gdImageCreate(*sx, *sy);
+ }
+ if (im == NULL) {
+ GD2_DBG(php_gd_error("Could not create gdImage\n"));
+ goto fail1;
+ }
+
+ if (!_gdGetColors(in, im, (*vers) == 2)) {
+ GD2_DBG(php_gd_error("Could not read color palette\n"));
+ goto fail2;
+ }
+ GD2_DBG(php_gd_error("Image palette completed: %d colours\n",
+im->colorsTotal));
+
+ return im;
fail2:
- gdImageDestroy (im);
- return 0;
+ gdImageDestroy(im);
+ return 0;
fail1:
- return 0;
+ return 0;
+}
+
+static int _gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf,
+uLongf * chunkLen, gdIOCtx * in)
+{
+ int zerr;
+
+ if (gdTell(in) != offset) {
+ GD2_DBG(php_gd_error("Positioning in file to %d\n", offset));
+ gdSeek(in, offset);
+ } else {
+ GD2_DBG(php_gd_error("Already Positioned in file to %d\n", offset));
+ }
+
+ /* Read and uncompress an entire chunk. */
+ GD2_DBG(php_gd_error("Reading file\n"));
+ if (gdGetBuf(compBuf, compSize, in) != compSize) {
+ return FALSE;
+ }
+ GD2_DBG(php_gd_error("Got %d bytes. Uncompressing into buffer of %d bytes\n",
+compSize, (int)*chunkLen));
+ zerr = uncompress((unsigned char *) chunkBuf, chunkLen, (unsigned char *)
+compBuf, compSize);
+ if (zerr != Z_OK) {
+ GD2_DBG(php_gd_error("Error %d from uncompress\n", zerr));
+ return FALSE;
+ }
+ GD2_DBG(php_gd_error("Got chunk\n"));
+
+ return TRUE;
+}
+
+gdImagePtr gdImageCreateFromGd2 (FILE * inFile)
+{
+ gdIOCtx *in = gdNewFileCtx(inFile);
+ gdImagePtr im;
+
+ im = gdImageCreateFromGd2Ctx(in);
+ in->gd_free(in);
+
+ return im;
}
-static
-int
-_gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf, uLongf *
chunkLen, gdIOCtx * in)
-{
- int zerr;
-
- if (gdTell (in) != offset)
- {
- GD2_DBG(php_gd_error("Positioning in file to %d\n", offset));
- gdSeek (in, offset);
- }
- else
- {
- GD2_DBG(php_gd_error("Already Positioned in file to %d\n", offset));
- };
-
- /* Read and uncompress an entire chunk. */
- GD2_DBG(php_gd_error("Reading file\n"));
- if (gdGetBuf (compBuf, compSize, in) != compSize)
- {
- return FALSE;
- };
- GD2_DBG(php_gd_error("Got %d bytes. Uncompressing into buffer of %d bytes\n",
compSize, (int)*chunkLen));
- zerr = uncompress ((unsigned char *) chunkBuf, chunkLen,
- (unsigned char *) compBuf, compSize);
- if (zerr != Z_OK)
- {
- GD2_DBG(php_gd_error("Error %d from uncompress\n", zerr));
- return FALSE;
- };
- GD2_DBG(php_gd_error("Got chunk\n"));
- return TRUE;
-}
-
-gdImagePtr
-gdImageCreateFromGd2 (FILE * inFile)
-{
- gdIOCtx *in = gdNewFileCtx (inFile);
- gdImagePtr im;
-
- im = gdImageCreateFromGd2Ctx (in);
-
- in->gd_free (in);
-
- return im;
-}
-
-gdImagePtr
-gdImageCreateFromGd2Ctx (gdIOCtxPtr in)
-{
- int sx, sy;
- int i;
- int ncx, ncy, nc, cs, cx, cy;
- int x, y, ylo, yhi, xlo, xhi;
- int vers, fmt;
- t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */
- unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */
- int chunkNum = 0;
- int chunkMax = 0;
- uLongf chunkLen;
- int chunkPos = 0;
- int compMax = 0;
- int bytesPerPixel;
- char *compBuf = NULL; /* So we can gdFree it with impunity. */
-
- gdImagePtr im;
-
- /* Get the header */
- im = _gd2CreateFromFile (in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx);
-
- if (im == NULL)
- {
- return 0;
- };
- bytesPerPixel = im->trueColor ? 4 : 1;
- nc = ncx * ncy;
-
- if (fmt == GD2_FMT_COMPRESSED)
- {
- /* Find the maximum compressed chunk size. */
- compMax = 0;
- for (i = 0; (i < nc); i++)
- {
- if (chunkIdx[i].size > compMax)
- {
- compMax = chunkIdx[i].size;
- };
- };
- compMax++;
-
- /* Allocate buffers */
- chunkMax = cs * bytesPerPixel * cs;
- chunkBuf = gdCalloc (chunkMax, 1);
- compBuf = gdCalloc (compMax, 1);
- GD2_DBG(php_gd_error("Largest compressed chunk is %d bytes\n", compMax));
- };
-
-/* if ( (ncx != sx / cs) || (ncy != sy / cs)) { */
-/* goto fail2; */
-/* }; */
-
- /* Read the data... */
- for (cy = 0; (cy < ncy); cy++)
- {
- for (cx = 0; (cx < ncx); cx++)
- {
-
- ylo = cy * cs;
- yhi = ylo + cs;
- if (yhi > im->sy)
- {
- yhi = im->sy;
- };
-
- GD2_DBG(php_gd_error("Processing Chunk %d (%d, %d), y from %d to %d\n",
chunkNum, cx, cy, ylo, yhi));
-
- if (fmt == GD2_FMT_COMPRESSED)
- {
-
- chunkLen = chunkMax;
-
- if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
- compBuf,
- chunkIdx[chunkNum].size,
- chunkBuf, &chunkLen, in))
- {
- GD2_DBG(php_gd_error("Error reading comproessed chunk\n"));
- goto fail2;
- };
-
- chunkPos = 0;
- };
-
- for (y = ylo; (y < yhi); y++)
- {
-
- xlo = cx * cs;
- xhi = xlo + cs;
- if (xhi > im->sx)
- {
- xhi = im->sx;
- };
- /*GD2_DBG(php_gd_error("y=%d: ",y)); */
- if (fmt == GD2_FMT_RAW)
- {
- for (x = xlo; x < xhi; x++)
- {
-
- if (im->trueColor)
- {
- if (!gdGetInt (&im->tpixels[y][x], in))
- {
- /*php_gd_error("EOF while reading\n"); */
- /*gdImageDestroy(im); */
- /*return 0; */
- im->tpixels[y][x] = 0;
- }
- }
- else
- {
- int ch;
- if (!gdGetByte (&ch, in))
- {
- /*php_gd_error("EOF while reading\n"); */
- /*gdImageDestroy(im); */
- /*return 0; */
- ch = 0;
- }
- im->pixels[y][x] = ch;
+gdImagePtr gdImageCreateFromGd2Ctx (gdIOCtxPtr in)
+{
+ int sx, sy;
+ int i;
+ int ncx, ncy, nc, cs, cx, cy;
+ int x, y, ylo, yhi, xlo, xhi;
+ int vers, fmt;
+ t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */
+ unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */
+ int chunkNum = 0;
+ int chunkMax = 0;
+ uLongf chunkLen;
+ int chunkPos = 0;
+ int compMax = 0;
+ int bytesPerPixel;
+ char *compBuf = NULL; /* So we can gdFree it with impunity. */
+
+ gdImagePtr im;
+
+ /* Get the header */
+ if (!(im = _gd2CreateFromFile(in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy,
+&chunkIdx))) {
+ return 0;
+ }
+
+ bytesPerPixel = im->trueColor ? 4 : 1;
+ nc = ncx * ncy;
+
+ if (gd2_compressed(fmt)) {
+ /* Find the maximum compressed chunk size. */
+ compMax = 0;
+ for (i = 0; (i < nc); i++) {
+ if (chunkIdx[i].size > compMax) {
+ compMax = chunkIdx[i].size;
+ }
+ }
+ compMax++;
+
+ /* Allocate buffers */
+ chunkMax = cs * bytesPerPixel * cs;
+ chunkBuf = gdCalloc(chunkMax, 1);
+ compBuf = gdCalloc(compMax, 1);
+
+ GD2_DBG(php_gd_error("Largest compressed chunk is %d bytes\n",
+compMax));
+ }
+
+ /* Read the data... */
+ for (cy = 0; (cy < ncy); cy++) {
+ for (cx = 0; (cx < ncx); cx++) {
+ ylo = cy * cs;
+ yhi = ylo + cs;
+ if (yhi > im->sy) {
+ yhi = im->sy;
+ }
+
+ GD2_DBG(php_gd_error("Processing Chunk %d (%d, %d), y from %d
+to %d\n", chunkNum, cx, cy, ylo, yhi));
+
+ if (gd2_compressed(fmt)) {
+ chunkLen = chunkMax;
+
+ if (!_gd2ReadChunk(chunkIdx[chunkNum].offset, compBuf,
+chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) {
+ GD2_DBG(php_gd_error("Error reading
+comproessed chunk\n"));
+ goto fail2;
+ }
+
+ chunkPos = 0;
+ }
+
+ for (y = ylo; (y < yhi); y++) {
+ xlo = cx * cs;
+ xhi = xlo + cs;
+ if (xhi > im->sx) {
+ xhi = im->sx;
+ }
+
+ if (!gd2_compressed(fmt)) {
+ for (x = xlo; x < xhi; x++) {
+ if (im->trueColor) {
+ if
+(!gdGetInt(&im->tpixels[y][x], in)) {
+ im->tpixels[y][x] = 0;
+ }
+ } else {
+ int ch;
+ if (!gdGetByte(&ch, in)) {
+ ch = 0;
+ }
+ im->pixels[y][x] = ch;
+ }
+ }
+ } else {
+ for (x = xlo; x < xhi; x++) {
+ if (im->trueColor) {
+ /* 2.0.1: work around a gcc
+bug by being verbose. TBB */
+ int a = chunkBuf[chunkPos++]
+<< 24;
+ int r = chunkBuf[chunkPos++]
+<< 16;
+ int g = chunkBuf[chunkPos++]
+<< 8;
+ int b = chunkBuf[chunkPos++];
+ im->tpixels[y][x] = a + r + g
++ b;
+ } else {
+ im->pixels[y][x] =
+chunkBuf[chunkPos++];
+ }
+ }
+ }
}
- }
+ chunkNum++;
}
- else
- {
- for (x = xlo; x < xhi; x++)
- {
- if (im->trueColor)
- {
- /* 2.0.1: work around a gcc bug by being verbose.
- TBB */
- int a = chunkBuf[chunkPos++] << 24;
- int r = chunkBuf[chunkPos++] << 16;
- int g = chunkBuf[chunkPos++] << 8;
- int b = chunkBuf[chunkPos++];
- im->tpixels[y][x] = a + r + g + b;
- }
- else
- {
- im->pixels[y][x] = chunkBuf[chunkPos++];
- }
- };
- };
- /*GD2_DBG(php_gd_error("\n")); */
- };
- chunkNum++;
- };
- };
-
- GD2_DBG(php_gd_error("Freeing memory\n"));
-
- gdFree (chunkBuf);
- gdFree (compBuf);
- gdFree (chunkIdx);
+ }
- GD2_DBG(php_gd_error("Done\n"));
+ GD2_DBG(php_gd_error("Freeing memory\n"));
- return im;
+ if (chunkBuf) {
+ gdFree(chunkBuf);
+ }
+ if (compBuf) {
+ gdFree(compBuf);
+ }
+ if (chunkIdx) {
+ gdFree(chunkIdx);
+ }
+
+ GD2_DBG(php_gd_error("Done\n"));
+
+ return im;
fail2:
- gdImageDestroy (im);
- gdFree (chunkBuf);
- gdFree (compBuf);
- gdFree (chunkIdx);
- return 0;
-
-}
-
-gdImagePtr
-gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h)
-{
- gdImagePtr im;
- gdIOCtx *in = gdNewFileCtx (inFile);
-
- im = gdImageCreateFromGd2PartCtx (in, srcx, srcy, w, h);
-
- in->gd_free (in);
-
- return im;
-}
-
-gdImagePtr
-gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
-{
- int scx, scy, ecx, ecy, fsx, fsy;
- int nc, ncx, ncy, cs, cx, cy;
- int x, y, ylo, yhi, xlo, xhi;
- int dstart, dpos;
- int i;
- int ch, vers, fmt;
- t_chunk_info *chunkIdx = NULL;
- char *chunkBuf = NULL;
- int chunkNum;
- int chunkMax = 0;
- uLongf chunkLen;
- int chunkPos = 0;
- int compMax;
- char *compBuf = NULL;
-
- gdImagePtr im;
-
- /* */
- /* The next few lines are basically copied from gd2CreateFromFile */
- /* - we change the file size, so don't want to use the code directly. */
- /* but we do need to know the file size. */
- /* */
- if (_gd2GetHeader (in, &fsx, &fsy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx) != 1)
- {
- goto fail1;
- }
-
- GD2_DBG(php_gd_error("File size is %dx%d\n", fsx, fsy));
-
- /* This is the difference - make a file based on size of chunks. */
- im = gdImageCreate (w, h);
- if (im == NULL)
- {
- goto fail1;
- };
-
- if (!_gdGetColors (in, im, vers == 2))
- {
- goto fail2;
- }
- GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal));
-
- /* Process the header info */
- nc = ncx * ncy;
-
- if (fmt == GD2_FMT_COMPRESSED)
- {
- /* Find the maximum compressed chunk size. */
- compMax = 0;
- for (i = 0; (i < nc); i++)
- {
- if (chunkIdx[i].size > compMax)
- {
- compMax = chunkIdx[i].size;
- };
- };
- compMax++;
-
- if (im->trueColor)
- {
- chunkMax = cs * cs * 4;
- }
- else
- {
- chunkMax = cs * cs;
- }
- chunkBuf = gdCalloc (chunkMax, 1);
- compBuf = gdCalloc (compMax, 1);
- };
-
-/* Don't bother with this... */
-/* if ( (ncx != sx / cs) || (ncy != sy / cs)) { */
-/* goto fail2; */
-/* }; */
-
-
- /* Work out start/end chunks */
- scx = srcx / cs;
- scy = srcy / cs;
- if (scx < 0)
- {
- scx = 0;
- };
- if (scy < 0)
- {
- scy = 0;
- };
-
- ecx = (srcx + w) / cs;
- ecy = (srcy + h) / cs;
- if (ecx >= ncx)
- {
- ecx = ncx - 1;
- };
- if (ecy >= ncy)
- {
- ecy = ncy - 1;
- };
-
- /* Remember file position of image data. */
- dstart = gdTell (in);
- GD2_DBG(php_gd_error("Data starts at %d\n", dstart));
-
- /* Loop through the chunks. */
- for (cy = scy; (cy <= ecy); cy++)
- {
-
- ylo = cy * cs;
- yhi = ylo + cs;
- if (yhi > fsy)
- {
- yhi = fsy;
- };
-
- for (cx = scx; (cx <= ecx); cx++)
- {
-
- xlo = cx * cs;
- xhi = xlo + cs;
- if (xhi > fsx)
- {
- xhi = fsx;
- };
-
- GD2_DBG(php_gd_error("Processing Chunk (%d, %d), from %d to %d\n", cx, cy,
ylo, yhi));
-
- if (fmt == GD2_FMT_RAW)
- {
- GD2_DBG(php_gd_error("Using raw format data\n"));
- if (im->trueColor)
- {
- dpos = (cy * (cs * fsx) + cx * cs * (yhi - ylo) * 4) + dstart;
+ gdImageDestroy(im);
+ if (chunkBuf) {
+ gdFree(chunkBuf);
+ }
+ if (compBuf) {
+ gdFree(compBuf);
+ }
+ if (chunkIdx) {
+ gdFree(chunkIdx);
+ }
+
+ return 0;
+}
+
+gdImagePtr gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h)
+{
+ gdImagePtr im;
+ gdIOCtx *in = gdNewFileCtx(inFile);
+
+ im = gdImageCreateFromGd2PartCtx(in, srcx, srcy, w, h);
+
+ in->gd_free(in);
+
+ return im;
+}
+
+gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int
+h)
+{
+ int scx, scy, ecx, ecy, fsx, fsy;
+ int nc, ncx, ncy, cs, cx, cy;
+ int x, y, ylo, yhi, xlo, xhi;
+ int dstart, dpos;
+ int i;
+ int ch, vers, fmt;
+ t_chunk_info *chunkIdx = NULL;
+ char *chunkBuf = NULL;
+ int chunkNum;
+ int chunkMax = 0;
+ uLongf chunkLen;
+ int chunkPos = 0;
+ int compMax;
+ char *compBuf = NULL;
+
+ gdImagePtr im;
+
+ /* The next few lines are basically copied from gd2CreateFromFile
+ * we change the file size, so don't want to use the code directly.
+ * but we do need to know the file size.
+ */
+ if (_gd2GetHeader(in, &fsx, &fsy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx) !=
+1) {
+ goto fail1;
+ }
+
+ GD2_DBG(php_gd_error("File size is %dx%d\n", fsx, fsy));
+
+ /* This is the difference - make a file based on size of chunks. */
+ if (gd2_truecolor(fmt)) {
+ im = gdImageCreateTrueColor(w, h);
+ } else {
+ im = gdImageCreate(w, h);
+ }
+ if (im == NULL) {
+ goto fail1;
+ }
+
+ if (!_gdGetColors(in, im, vers == 2)) {
+ goto fail2;
+ }
+ GD2_DBG(php_gd_error("Image palette completed: %d colours\n",
+im->colorsTotal));
+
+ /* Process the header info */
+ nc = ncx * ncy;
+
+ if (gd2_compressed(fmt)) {
+ /* Find the maximum compressed chunk size. */
+ compMax = 0;
+ for (i = 0; (i < nc); i++) {
+ if (chunkIdx[i].size > compMax) {
+ compMax = chunkIdx[i].size;
+ }
+ }
+ compMax++;
+
+ if (im->trueColor) {
+ chunkMax = cs * cs * 4;
+ } else {
+ chunkMax = cs * cs;
}
- else
- {
- dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo) + dstart;
+ chunkBuf = gdCalloc(chunkMax, 1);
+ compBuf = gdCalloc(compMax, 1);
+ }
+
+ /* Work out start/end chunks */
+ scx = srcx / cs;
+ scy = srcy / cs;
+ if (scx < 0) {
+ scx = 0;
+ }
+ if (scy < 0) {
+ scy = 0;
+ }
+
+ ecx = (srcx + w) / cs;
+ ecy = (srcy + h) / cs;
+ if (ecx >= ncx) {
+ ecx = ncx - 1;
+ }
+ if (ecy >= ncy) {
+ ecy = ncy - 1;
+ }
+
+ /* Remember file position of image data. */
+ dstart = gdTell(in);
+ GD2_DBG(php_gd_error("Data starts at %d\n", dstart));
+
+ /* Loop through the chunks. */
+ for (cy = scy; (cy <= ecy); cy++) {
+ ylo = cy * cs;
+ yhi = ylo + cs;
+ if (yhi > fsy) {
+ yhi = fsy;
}
- if (gdSeek (in, dpos) != 0)
- {
- php_gd_error_ex(E_WARNING, "Error from seek: %d\n", errno);
- goto fail2;
- };
- GD2_DBG(php_gd_error("Reading (%d, %d) from position %d\n", cx, cy, dpos
- dstart));
- }
- else
- {
- chunkNum = cx + cy * ncx;
-
- chunkLen = chunkMax;
- if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
- compBuf,
- chunkIdx[chunkNum].size,
- chunkBuf, &chunkLen, in))
- {
- php_gd_error("Error reading comproessed chunk\n");
- goto fail2;
- };
- chunkPos = 0;
- GD2_DBG(php_gd_error("Reading (%d, %d) from chunk %d\n", cx, cy,
chunkNum));
- };
-
- GD2_DBG(php_gd_error(" into (%d, %d) - (%d, %d)\n", xlo, ylo, xhi, yhi));
- for (y = ylo; (y < yhi); y++)
- {
-
- for (x = xlo; x < xhi; x++)
- {
- if (fmt == GD2_FMT_RAW)
- {
- if (im->trueColor)
- {
- if (!gdGetInt (&ch, in))
- {
- ch = 0;
- /*php_gd_error("EOF while reading file\n"); */
- /*goto fail2; */
- }
- }
- else
- {
- ch = gdGetC (in);
- if (ch == EOF)
- {
- ch = 0;
- /*php_gd_error("EOF while reading file\n"); */
- /*goto fail2; */
- }
- }
- }
- else
- {
- if (im->trueColor)
- {
- ch = chunkBuf[chunkPos++];
- ch = (ch << 8) + chunkBuf[chunkPos++];
- ch = (ch << 8) + chunkBuf[chunkPos++];
- ch = (ch << 8) + chunkBuf[chunkPos++];
- }
- else
- {
- ch = chunkBuf[chunkPos++];
- }
- };
-
- /* Only use a point that is in the image. */
- if ((x >= srcx) && (x < (srcx + w)) && (x < fsx) && (x >= 0)
- && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0)
- )
- {
- im->pixels[y - srcy][x - srcx] = ch;
- }
- };
- };
- };
- };
-
- gdFree (chunkBuf);
- gdFree (compBuf);
- gdFree (chunkIdx);
+ for (cx = scx; cx <= ecx; cx++) {
- return im;
+ xlo = cx * cs;
+ xhi = xlo + cs;
+ if (xhi > fsx) {
+ xhi = fsx;
+ }
+
+ GD2_DBG(php_gd_error("Processing Chunk (%d, %d), from %d to
+%d\n", cx, cy, ylo, yhi));
+
+ if (!gd2_compressed(fmt)) {
+ GD2_DBG(php_gd_error("Using raw format data\n"));
+ if (im->trueColor) {
+ dpos = (cy * (cs * fsx) * 4 + cx * cs * (yhi -
+ylo) * 4) + dstart;
+ } else {
+ dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo)
++ dstart;
+ }
+
+ /* gd 2.0.11: gdSeek returns TRUE on success, not 0.
+Longstanding bug. 01/16/03 */
+ if (!gdSeek(in, dpos)) {
+ php_gd_error_ex(E_WARNING, "Error from seek:
+%d\n", errno);
+ goto fail2;
+ }
+ GD2_DBG(php_gd_error("Reading (%d, %d) from position
+%d\n", cx, cy, dpos - dstart));
+ } else {
+ chunkNum = cx + cy * ncx;
+
+ chunkLen = chunkMax;
+ if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
+compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) {
+ php_gd_error("Error reading comproessed
+chunk\n");
+ goto fail2;
+ }
+ chunkPos = 0;
+ GD2_DBG(php_gd_error("Reading (%d, %d) from chunk
+%d\n", cx, cy, chunkNum));
+ }
+
+ GD2_DBG(php_gd_error(" into (%d, %d) - (%d, %d)\n", xlo,
+ylo, xhi, yhi));
+
+ for (y = ylo; (y < yhi); y++) {
+ for (x = xlo; x < xhi; x++) {
+ if (!gd2_compressed(fmt)) {
+ if (im->trueColor) {
+ if (!gdGetInt(&ch, in)) {
+ ch = 0;
+ }
+ } else {
+ ch = gdGetC(in);
+ if (ch == EOF) {
+ ch = 0;
+ }
+ }
+ } else {
+ if (im->trueColor) {
+ ch = chunkBuf[chunkPos++];
+ ch = (ch << 8) +
+chunkBuf[chunkPos++];
+ ch = (ch << 8) +
+chunkBuf[chunkPos++];
+ ch = (ch << 8) +
+chunkBuf[chunkPos++];
+ } else {
+ ch = chunkBuf[chunkPos++];
+ }
+ }
+
+ /* Only use a point that is in the image. */
+ if ((x >= srcx) && (x < (srcx + w)) && (x <
+fsx) && (x >= 0) && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0)) {
+ if (im->trueColor) {
+ im->tpixels[y - srcy][x -
+srcx] = ch;
+ } else {
+ im->pixels[y - srcy][x - srcx]
+= ch;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (chunkBuf) {
+ gdFree(chunkBuf);
+ }
+ if (compBuf) {
+ gdFree(compBuf);
+ }
+ if (chunkIdx) {
+ gdFree(chunkIdx);
+ }
+
+ return im;
fail2:
- gdImageDestroy (im);
+ gdImageDestroy(im);
fail1:
- gdFree (chunkBuf);
- gdFree (compBuf);
- gdFree (chunkIdx);
-
- return 0;
-
-}
-
-static
-void
-_gd2PutHeader (gdImagePtr im, gdIOCtx * out, int cs, int fmt, int cx, int cy)
-{
- int i;
-
- /* Send the gd2 id, to verify file format. */
- for (i = 0; i < 4; i++)
- {
- gdPutC ((unsigned char) (GD2_ID[i]), out);
- };
-
- /* */
- /* We put the version info first, so future versions can easily change header info.
*/
- /* */
- gdPutWord (GD2_VERS, out);
- gdPutWord (im->sx, out);
- gdPutWord (im->sy, out);
- gdPutWord (cs, out);
- gdPutWord (fmt, out);
- gdPutWord (cx, out);
- gdPutWord (cy, out);
-
-}
-
-static void
-_gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt)
-{
- int ncx, ncy, cx, cy;
- int x, y, ylo, yhi, xlo, xhi;
- int chunkLen;
- int chunkNum = 0;
- char *chunkData = NULL; /* So we can gdFree it with impunity. */
- char *compData = NULL; /* So we can gdFree it with impunity. */
- uLongf compLen;
- int idxPos = 0;
- int idxSize;
- t_chunk_info *chunkIdx = NULL;
- int posSave;
- int bytesPerPixel = im->trueColor ? 4 : 1;
- int compMax = 0;
-
- /*php_gd_error("Trying to write GD2 file\n"); */
-
- /* */
- /* Force fmt to a valid value since we don't return anything. */
- /* */
- if ((fmt == 0) || ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)))
- {
- fmt = GD2_FMT_COMPRESSED;
- };
-
- /* */
- /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems */
- /* a little silly to expect performance improvements on a 64x64 bit scale, and */
- /* 4096 because we buffer one chunk, and a 16MB buffer seems a little largei - it
may be */
- /* OK for one user, but for another to read it, they require the buffer. */
- /* */
- if (cs == 0)
- {
- cs = GD2_CHUNKSIZE;
- }
- else if (cs < GD2_CHUNKSIZE_MIN)
- {
- cs = GD2_CHUNKSIZE_MIN;
- }
- else if (cs > GD2_CHUNKSIZE_MAX)
- {
- cs = GD2_CHUNKSIZE_MAX;
- };
-
- /* Work out number of chunks. */
- ncx = im->sx / cs + 1;
- ncy = im->sy / cs + 1;
-
- /* Write the standard header. */
- _gd2PutHeader (im, out, cs, fmt, ncx, ncy);
-
- if (fmt == GD2_FMT_COMPRESSED)
- {
- /* */
- /* Work out size of buffer for compressed data, If CHUNKSIZE is large, */
- /* then these will be large! */
- /* */
- /* The zlib notes say output buffer size should be (input size) * 1.01 * 12 */
- /* - we'll use 1.02 to be paranoid. */
- /* */
- compMax = (int)(cs * bytesPerPixel * cs * 1.02f) + 12;
-
- /* */
- /* Allocate the buffers. */
- /* */
- chunkData = gdCalloc (cs * bytesPerPixel * cs, 1);
- compData = gdCalloc (compMax, 1);
-
- /* */
- /* Save the file position of chunk index, and allocate enough space for */
- /* each chunk_info block . */
- /* */
- idxPos = gdTell (out);
- idxSize = ncx * ncy * sizeof (t_chunk_info);
- GD2_DBG(php_gd_error("Index size is %d\n", idxSize));
- gdSeek (out, idxPos + idxSize);
-
- chunkIdx = gdCalloc (idxSize * sizeof (t_chunk_info), 1);
- };
-
- _gdPutColors (im, out);
-
- GD2_DBG(php_gd_error("Size: %dx%d\n", im->sx, im->sy));
- GD2_DBG(php_gd_error("Chunks: %dx%d\n", ncx, ncy));
-
- for (cy = 0; (cy < ncy); cy++)
- {
- for (cx = 0; (cx < ncx); cx++)
- {
-
- ylo = cy * cs;
- yhi = ylo + cs;
- if (yhi > im->sy)
- {
- yhi = im->sy;
- };
-
- GD2_DBG(php_gd_error("Processing Chunk (%dx%d), y from %d to %d\n", cx, cy,
ylo, yhi));
- chunkLen = 0;
- for (y = ylo; (y < yhi); y++)
- {
-
- GD2_DBG(php_gd_error("y=%d: ",y));
-
- xlo = cx * cs;
- xhi = xlo + cs;
- if (xhi > im->sx)
- {
- xhi = im->sx;
- };
-
- if (fmt == GD2_FMT_COMPRESSED)
- {
- for (x = xlo; x < xhi; x++)
- {
- GD2_DBG(php_gd_error("%d...",x));
- if (im->trueColor)
- {
- int p = im->tpixels[y][x];
- chunkData[chunkLen++] = gdTrueColorGetAlpha (p);
- chunkData[chunkLen++] = gdTrueColorGetRed (p);
- chunkData[chunkLen++] = gdTrueColorGetGreen (p);
- chunkData[chunkLen++] = gdTrueColorGetBlue (p);
- }
- else
- {
- chunkData[chunkLen++] = im->pixels[y][x];
+ if (chunkBuf) {
+ gdFree(chunkBuf);
+ }
+ if (compBuf) {
+ gdFree(compBuf);
+ }
+ if (chunkIdx) {
+ gdFree(chunkIdx);
+ }
+
+ return 0;
+}
+
+static void _gd2PutHeader (gdImagePtr im, gdIOCtx * out, int cs, int fmt, int cx, int
+cy)
+{
+ int i;
+
+ /* Send the gd2 id, to verify file format. */
+ for (i = 0; i < 4; i++) {
+ gdPutC((unsigned char) (GD2_ID[i]), out);
+ }
+
+ /* We put the version info first, so future versions can easily change header
+info. */
+
+ gdPutWord(GD2_VERS, out);
+ gdPutWord(im->sx, out);
+ gdPutWord(im->sy, out);
+ gdPutWord(cs, out);
+ gdPutWord(fmt, out);
+ gdPutWord(cx, out);
+ gdPutWord(cy, out);
+}
+
+static void _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt)
+{
+ int ncx, ncy, cx, cy;
+ int x, y, ylo, yhi, xlo, xhi;
+ int chunkLen;
+ int chunkNum = 0;
+ char *chunkData = NULL; /* So we can gdFree it with impunity. */
+ char *compData = NULL; /* So we can gdFree it with impunity. */
+ uLongf compLen;
+ int idxPos = 0;
+ int idxSize;
+ t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */
+ int posSave;
+ int bytesPerPixel = im->trueColor ? 4 : 1;
+ int compMax = 0;
+
+ /* Force fmt to a valid value since we don't return anything. */
+ if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) {
+ fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED :
+GD2_FMT_COMPRESSED;
+ }
+ if (im->trueColor) {
+ fmt += 2;
+ }
+ /* Make sure chunk size is valid. These are arbitrary values; 64 because it
+seems
+ * a little silly to expect performance improvements on a 64x64 bit scale, and
+ * 4096 because we buffer one chunk, and a 16MB buffer seems a little large -
+it may be
+ * OK for one user, but for another to read it, they require the buffer.
+ */
+ if (cs == 0) {
+ cs = GD2_CHUNKSIZE;
+ } else if (cs < GD2_CHUNKSIZE_MIN) {
+ cs = GD2_CHUNKSIZE_MIN;
+ } else if (cs > GD2_CHUNKSIZE_MAX) {
+ cs = GD2_CHUNKSIZE_MAX;
+ }
+
+ /* Work out number of chunks. */
+ ncx = im->sx / cs + 1;
+ ncy = im->sy / cs + 1;
+
+ /* Write the standard header. */
+ _gd2PutHeader (im, out, cs, fmt, ncx, ncy);
+
+ if (gd2_compressed(fmt)) {
+ /* Work out size of buffer for compressed data, If CHUNKSIZE is large,
+ * then these will be large!
+ */
+
+ /* The zlib notes say output buffer size should be (input size) * 1.01
+* 12
+ * - we'll use 1.02 to be paranoid.
+ */
+ compMax = (int)(cs * bytesPerPixel * cs * 1.02f) + 12;
+
+ /* Allocate the buffers. */
+ chunkData = gdCalloc(cs * bytesPerPixel * cs, 1);
+ compData = gdCalloc(compMax, 1);
+
+ /* Save the file position of chunk index, and allocate enough space for
+ * each chunk_info block .
+ */
+ idxPos = gdTell(out);
+ idxSize = ncx * ncy * sizeof(t_chunk_info);
+ GD2_DBG(php_gd_error("Index size is %d\n", idxSize));
+ gdSeek(out, idxPos + idxSize);
+
+ chunkIdx = gdCalloc(idxSize * sizeof(t_chunk_info), 1);
+ }
+
+ _gdPutColors (im, out);
+
+ GD2_DBG(php_gd_error("Size: %dx%d\n", im->sx, im->sy));
+ GD2_DBG(php_gd_error("Chunks: %dx%d\n", ncx, ncy));
+
+ for (cy = 0; (cy < ncy); cy++) {
+ for (cx = 0; (cx < ncx); cx++) {
+ ylo = cy * cs;
+ yhi = ylo + cs;
+ if (yhi > im->sy) {
+ yhi = im->sy;
+ }
+
+ GD2_DBG(php_gd_error("Processing Chunk (%dx%d), y from %d to
+%d\n", cx, cy, ylo, yhi));
+ chunkLen = 0;
+ for (y = ylo; (y < yhi); y++) {
+ GD2_DBG(php_gd_error("y=%d: ",y));
+ xlo = cx * cs;
+ xhi = xlo + cs;
+ if (xhi > im->sx) {
+ xhi = im->sx;
+ }
+
+ if (gd2_compressed(fmt)) {
+ for (x = xlo; x < xhi; x++) {
+ GD2_DBG(php_gd_error("%d...",x));
+ if (im->trueColor) {
+ int p = im->tpixels[y][x];
+ chunkData[chunkLen++] =
+gdTrueColorGetAlpha(p);
+ chunkData[chunkLen++] =
+gdTrueColorGetRed(p);
+ chunkData[chunkLen++] =
+gdTrueColorGetGreen(p);
+ chunkData[chunkLen++] =
+gdTrueColorGetBlue(p);
+ } else {
+ chunkData[chunkLen++] =
+im->pixels[y][x];
+ }
+ }
+ } else {
+ for (x = xlo; x < xhi; x++) {
+ GD2_DBG(php_gd_error("%d, ",x));
+
+ if (im->trueColor) {
+ gdPutInt(im->tpixels[y][x],
+out);
+ } else {
+ gdPutC((unsigned char)
+im->pixels[y][x], out);
+ }
+ }
+ }
+ GD2_DBG(php_gd_error("y=%d done.\n",y));
+ }
+
+ if (gd2_compressed(fmt)) {
+ compLen = compMax;
+ if (compress((unsigned char *) &compData[0], &compLen,
+(unsigned char *) &chunkData[0], chunkLen) != Z_OK) {
+ php_gd_error("Error from compressing\n");
+ } else {
+ chunkIdx[chunkNum].offset = gdTell(out);
+ chunkIdx[chunkNum++].size = compLen;
+ GD2_DBG(php_gd_error("Chunk %d size %d offset
+%d\n", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset));
+
+ if (gdPutBuf (compData, compLen, out) <= 0) {
+ /* Any alternate suggestions for
+handling this? */
+ php_gd_error_ex(E_WARNING, "Error %d
+on write\n", errno);
+ }
+ }
}
- };
}
- else
- {
- for (x = xlo; x < xhi; x++)
- {
- GD2_DBG(php_gd_error("%d, ",x));
-
- if (im->trueColor)
- {
- gdPutInt (im->tpixels[y][x], out);
- }
- else
- {
- gdPutC ((unsigned char) im->pixels[y][x], out);
- }
- };
- };
- GD2_DBG(php_gd_error("y=%d done.\n",y));
- };
- if (fmt == GD2_FMT_COMPRESSED)
- {
- compLen = compMax;
- if (compress ((unsigned char *)
- &compData[0], &compLen,
- (unsigned char *) &chunkData[0],
- chunkLen) != Z_OK)
- {
- php_gd_error ("Error from compressing\n");
+ }
+
+ if (gd2_compressed(fmt)) {
+ /* Save the position, write the index, restore position (paranoia). */
+ GD2_DBG(php_gd_error("Seeking %d to write index\n", idxPos));
+ posSave = gdTell(out);
+ gdSeek(out, idxPos);
+ GD2_DBG(php_gd_error("Writing index\n"));
+ for (x = 0; x < chunkNum; x++) {
+ GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", x,
+chunkIdx[x].size, chunkIdx[x].offset));
+ gdPutInt(chunkIdx[x].offset, out);
+ gdPutInt(chunkIdx[x].size, out);
}
- else
- {
- chunkIdx[chunkNum].offset = gdTell (out);
- chunkIdx[chunkNum++].size = compLen;
- GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", chunkNum,
chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset));
-
- if (gdPutBuf (compData, compLen, out) <= 0)
- {
- /* Any alternate suggestions for handling this? */
- php_gd_error_ex (E_WARNING, "Error %d on write\n", errno);
- };
- };
- };
- };
- };
- if (fmt == GD2_FMT_COMPRESSED)
- {
- /* Save the position, write the index, restore position (paranoia). */
- GD2_DBG(php_gd_error("Seeking %d to write index\n", idxPos));
- posSave = gdTell (out);
- gdSeek (out, idxPos);
- GD2_DBG(php_gd_error("Writing index\n"));
- for (x = 0; x < chunkNum; x++)
- {
- GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", x, chunkIdx[x].size,
chunkIdx[x].offset));
- gdPutInt (chunkIdx[x].offset, out);
- gdPutInt (chunkIdx[x].size, out);
- };
- /* We don't use fwrite for *endian reasons. */
- /*fwrite(chunkIdx, sizeof(int)*2, chunkNum, out); */
- gdSeek (out, posSave);
- };
-
- GD2_DBG(php_gd_error("Freeing memory\n"));
- gdFree (chunkData);
- gdFree (compData);
- gdFree (chunkIdx);
- GD2_DBG(php_gd_error("Done\n"));
-
- /*php_gd_error("Memory block size is %d\n",gdTell(out)); */
+ gdSeek(out, posSave);
+ }
+ GD2_DBG(php_gd_error("Freeing memory\n"));
+ if (chunkData) {
+ gdFree(chunkData);
+ }
+ if (compData) {
+ gdFree(compData);
+ }
+ if (chunkIdx) {
+ gdFree(chunkIdx);
+ }
+ GD2_DBG(php_gd_error("Done\n"));
}
-void
-gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt)
-{
- gdIOCtx *out = gdNewFileCtx (outFile);
- _gdImageGd2 (im, out, cs, fmt);
- out->gd_free (out);
-}
-
-void *
-gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size)
-{
- void *rv;
- gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
- _gdImageGd2 (im, out, cs, fmt);
- rv = gdDPExtractData (out, size);
- out->gd_free (out);
- return rv;
+void gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt)
+{
+ gdIOCtx *out = gdNewFileCtx(outFile);
+
+ _gdImageGd2(im, out, cs, fmt);
+
+ out->gd_free(out);
+}
+
+void *gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size)
+{
+ void *rv;
+ gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
+
+ _gdImageGd2(im, out, cs, fmt);
+ rv = gdDPExtractData(out, size);
+ out->gd_free(out);
+
+ return rv;
}
Index: php4/ext/gd/libgd/gd_jpeg.c
diff -u php4/ext/gd/libgd/gd_jpeg.c:1.9 php4/ext/gd/libgd/gd_jpeg.c:1.10
--- php4/ext/gd/libgd/gd_jpeg.c:1.9 Sun Dec 1 06:43:54 2002
+++ php4/ext/gd/libgd/gd_jpeg.c Fri Jan 17 13:34:07 2003
@@ -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
*/
#include <stdio.h>
@@ -38,36 +41,30 @@
static const char *const GD_JPEG_VERSION = "1.0";
typedef struct _jmpbuf_wrapper
- {
- jmp_buf jmpbuf;
- }
-jmpbuf_wrapper;
+{
+ jmp_buf jmpbuf;
+} jmpbuf_wrapper;
/* Called by the IJG JPEG library upon encountering a fatal error */
static void
fatal_jpeg_error (j_common_ptr cinfo)
{
- jmpbuf_wrapper *jmpbufw;
+ jmpbuf_wrapper *jmpbufw;
- php_gd_error("gd-jpeg: JPEG library reports unrecoverable error: ");
- (*cinfo->err->output_message) (cinfo);
+ php_gd_error("gd-jpeg: JPEG library reports unrecoverable error: ");
+ (*cinfo->err->output_message) (cinfo);
- jmpbufw = (jmpbuf_wrapper *) cinfo->client_data;
- jpeg_destroy (cinfo);
+ jmpbufw = (jmpbuf_wrapper *) cinfo->client_data;
+ jpeg_destroy (cinfo);
- if (jmpbufw != 0)
- {
- longjmp (jmpbufw->jmpbuf, 1);
- php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: longjmp"
- " returned control; terminating\n");
- }
- else
- {
- php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: jmpbuf"
- " unrecoverable; terminating\n");
- }
+ if (jmpbufw != 0) {
+ longjmp (jmpbufw->jmpbuf, 1);
+ php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: longjmp
+returned control; terminating");
+ } else {
+ php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: jmpbuf
+unrecoverable; terminating");
+ }
- exit (99);
+ exit (99);
}
/*
@@ -76,25 +73,27 @@
* represent higher quality but also larger image size. If QUALITY is
* negative, the IJG JPEG library's default quality is used (which
* should be near optimal for many applications). See the IJG JPEG
- * library documentation for more details. */
+ * library documentation for more details.
+ */
void
gdImageJpeg (gdImagePtr im, FILE * outFile, int quality)
{
- gdIOCtx *out = gdNewFileCtx (outFile);
- gdImageJpegCtx (im, out, quality);
- out->gd_free (out);
+ gdIOCtx *out = gdNewFileCtx (outFile);
+ gdImageJpegCtx (im, out, quality);
+ out->gd_free (out);
}
void *
gdImageJpegPtr (gdImagePtr im, int *size, int quality)
{
- void *rv;
- gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
- gdImageJpegCtx (im, out, quality);
- rv = gdDPExtractData (out, size);
- out->gd_free (out);
- return rv;
+ void *rv;
+ gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
+ gdImageJpegCtx (im, out, quality);
+ rv = gdDPExtractData (out, size);
+ out->gd_free (out);
+
+ return rv;
}
void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile);
@@ -102,168 +101,127 @@
void
gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
{
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- int i, j, jidx;
- /* volatile so we can gdFree it on return from longjmp */
- volatile JSAMPROW row = 0;
- JSAMPROW rowptr[1];
- jmpbuf_wrapper jmpbufw;
- JDIMENSION nlines;
- char comment[255];
-
-#ifdef JPEG_DEBUG
- printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
- printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
- JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
- if (!im->trueColor)
- {
- for (i = 0; i < im->colorsTotal; i++)
- {
- if (!im->open[i])
- printf ("gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i,
- im->red[i], im->green[i], im->blue[i]);
- }
- }
-#endif /* JPEG_DEBUG */
-
- memset (&cinfo, 0, sizeof (cinfo));
- memset (&jerr, 0, sizeof (jerr));
-
- cinfo.err = jpeg_std_error (&jerr);
- cinfo.client_data = &jmpbufw;
- if (setjmp (jmpbufw.jmpbuf) != 0)
- {
- /* we're here courtesy of longjmp */
- if (row)
- gdFree (row);
- return;
- }
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ int i, j, jidx;
+ /* volatile so we can gdFree it on return from longjmp */
+ volatile JSAMPROW row = 0;
+ JSAMPROW rowptr[1];
+ jmpbuf_wrapper jmpbufw;
+ JDIMENSION nlines;
+ char comment[255];
+
+ memset (&cinfo, 0, sizeof (cinfo));
+ memset (&jerr, 0, sizeof (jerr));
+
+ cinfo.err = jpeg_std_error (&jerr);
+ cinfo.client_data = &jmpbufw;
+ if (setjmp (jmpbufw.jmpbuf) != 0) {
+ /* we're here courtesy of longjmp */
+ if (row) {
+ gdFree (row);
+ }
+ return;
+ }
- cinfo.err->error_exit = fatal_jpeg_error;
+ cinfo.err->error_exit = fatal_jpeg_error;
- jpeg_create_compress (&cinfo);
+ jpeg_create_compress (&cinfo);
- cinfo.image_width = im->sx;
- cinfo.image_height = im->sy;
- cinfo.input_components = 3; /* # of color components per pixel */
- cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
- jpeg_set_defaults (&cinfo);
- if (quality >= 0)
- jpeg_set_quality (&cinfo, quality, TRUE);
-
- /* If user requests interlace, translate that to progressive JPEG */
- if (gdImageGetInterlaced (im))
- {
-#ifdef JPEG_DEBUG
- printf ("gd-jpeg: interlace set, outputting progressive"
- " JPEG image\n");
-#endif
- jpeg_simple_progression (&cinfo);
- }
+ cinfo.image_width = im->sx;
+ cinfo.image_height = im->sy;
+ cinfo.input_components = 3; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+ jpeg_set_defaults (&cinfo);
+ if (quality >= 0) {
+ jpeg_set_quality (&cinfo, quality, TRUE);
+ }
+
+ /* If user requests interlace, translate that to progressive JPEG */
+ if (gdImageGetInterlaced (im)) {
+ jpeg_simple_progression (&cinfo);
+ }
+
+ jpeg_gdIOCtx_dest (&cinfo, outfile);
- jpeg_gdIOCtx_dest (&cinfo, outfile);
+ row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components *
+sizeof (JSAMPLE));
+ rowptr[0] = row;
+
+ jpeg_start_compress (&cinfo, TRUE);
+
+ if (quality >= 0) {
+ snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG
+JPEG v%d), quality = %d\n", GD_JPEG_VERSION, JPEG_LIB_VERSION, quality);
+ } else {
+ snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG
+JPEG v%d), default quality\n", GD_JPEG_VERSION, JPEG_LIB_VERSION);
+ }
+ jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, (unsigned int)
+strlen (comment));
+ if (im->trueColor) {
- row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components
- * sizeof (JSAMPLE));
- if (row == 0)
- {
- php_gd_error("gd-jpeg: error: unable to allocate JPEG row "
- "structure: gdCalloc returns NULL\n");
- jpeg_destroy_compress (&cinfo);
- return;
- }
-
- rowptr[0] = row;
-
- jpeg_start_compress (&cinfo, TRUE);
-
- sprintf (comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),",
- GD_JPEG_VERSION, JPEG_LIB_VERSION);
- if (quality >= 0)
- sprintf (comment + strlen (comment), " quality = %d\n",
- quality);
- else
- strcat (comment + strlen (comment), " default quality\n");
- jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment,
- (unsigned int) strlen (comment));
- if (im->trueColor)
- {
#if BITS_IN_JSAMPLE == 12
- php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit\n"
- "precision. This is mostly useless, because JPEGs on the web are\n"
- "8-bit and such versions of the jpeg library won't read or write\n"
- "them. GD doesn't support these unusual images. Edit your\n"
- "jmorecfg.h file to specify the correct precision and completely\n"
- "'make clean' and 'make install' libjpeg again. Sorry.\n");
- goto error;
+ php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit
+precision. This is mostly useless, because JPEGs on the web are 8-bit and such
+versions of the jpeg library won't read or write them. GD doesn't support these
+unusual images. Edit your jmorecfg.h file to specify the correct precision and
+completely 'make clean' and 'make install' libjpeg again. Sorry");
+ goto error;
#endif /* BITS_IN_JSAMPLE == 12 */
- for (i = 0; i < im->sy; i++)
- {
- for (jidx = 0, j = 0; j < im->sx; j++)
- {
- int val = im->tpixels[i][j];
- row[jidx++] = gdTrueColorGetRed (val);
- row[jidx++] = gdTrueColorGetGreen (val);
- row[jidx++] = gdTrueColorGetBlue (val);
- }
-
- nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
- if (nlines != 1)
- php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines"
- " returns %u -- expected 1\n", nlines);
- }
- }
- else
- {
- for (i = 0; i < im->sy; i++)
- {
- for (jidx = 0, j = 0; j < im->sx; j++)
- {
- int idx = im->pixels[i][j];
-
- /*
- * NB: Although gd RGB values are ints, their max value is
- * 255 (see the documentation for gdImageColorAllocate())
- * -- perfect for 8-bit JPEG encoding (which is the norm)
- */
+
+ for (i = 0; i < im->sy; i++) {
+ for (jidx = 0, j = 0; j < im->sx; j++) {
+ int val = im->tpixels[i][j];
+
+ row[jidx++] = gdTrueColorGetRed (val);
+ row[jidx++] = gdTrueColorGetGreen (val);
+ row[jidx++] = gdTrueColorGetBlue (val);
+ }
+
+ nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
+ if (nlines != 1) {
+ php_gd_error_ex(E_WARNING, "gd_jpeg: warning:
+jpeg_write_scanlines returns %u -- expected 1\n", nlines);
+ }
+ }
+ } else {
+ for (i = 0; i < im->sy; i++) {
+ for (jidx = 0, j = 0; j < im->sx; j++) {
+ int idx = im->pixels[i][j];
+
+ /* NB: Although gd RGB values are ints, their max
+value is
+ * 255 (see the documentation for
+gdImageColorAllocate())
+ * -- perfect for 8-bit JPEG encoding (which is the
+norm)
+ */
#if BITS_IN_JSAMPLE == 8
- row[jidx++] = im->red[idx];
- row[jidx++] = im->green[idx];
- row[jidx++] = im->blue[idx];
+ row[jidx++] = im->red[idx];
+ row[jidx++] = im->green[idx];
+ row[jidx++] = im->blue[idx];
#elif BITS_IN_JSAMPLE == 12
- row[jidx++] = im->red[idx] << 4;
- row[jidx++] = im->green[idx] << 4;
- row[jidx++] = im->blue[idx] << 4;
+ row[jidx++] = im->red[idx] << 4;
+ row[jidx++] = im->green[idx] << 4;
+ row[jidx++] = im->blue[idx] << 4;
#else
#error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
#endif
- }
+ }
- nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
- if (nlines != 1)
- php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines"
- " returns %u -- expected 1\n", nlines);
- }
- }
- jpeg_finish_compress (&cinfo);
- jpeg_destroy_compress (&cinfo);
- gdFree (row);
+ nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
+ if (nlines != 1) {
+ php_gd_error_ex(E_WARNING, "gd_jpeg: warning:
+jpeg_write_scanlines returns %u -- expected 1\n", nlines);
+ }
+ }
+ }
+
+ jpeg_finish_compress (&cinfo);
+ jpeg_destroy_compress (&cinfo);
+ gdFree (row);
}
gdImagePtr
gdImageCreateFromJpeg (FILE * inFile)
{
- gdImagePtr im;
- gdIOCtx *in = gdNewFileCtx (inFile);
- im = gdImageCreateFromJpegCtx (in);
- in->gd_free (in);
- return im;
+ gdImagePtr im;
+ gdIOCtx *in = gdNewFileCtx (inFile);
+ im = gdImageCreateFromJpegCtx (in);
+ in->gd_free (in);
+
+ return im;
}
-void
- jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
- gdIOCtx * infile);
+void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
/*
* Create a gd-format image from the JPEG-format INFILE. Returns the
@@ -272,197 +230,122 @@
gdImagePtr
gdImageCreateFromJpegCtx (gdIOCtx * infile)
{
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- jmpbuf_wrapper jmpbufw;
- /* volatile so we can gdFree them after longjmp */
- volatile JSAMPROW row = 0;
- volatile gdImagePtr im = 0;
- JSAMPROW rowptr[1];
- unsigned int i, j;
- int retval;
- JDIMENSION nrows;
-
-#ifdef JPEG_DEBUG
- printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
- printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
- JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
-#endif
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ jmpbuf_wrapper jmpbufw;
+ /* volatile so we can gdFree them after longjmp */
+ volatile JSAMPROW row = 0;
+ volatile gdImagePtr im = 0;
+ JSAMPROW rowptr[1];
+ unsigned int i, j;
+ int retval;
+ JDIMENSION nrows;
+
+ memset (&cinfo, 0, sizeof (cinfo));
+ memset (&jerr, 0, sizeof (jerr));
+
+ cinfo.err = jpeg_std_error (&jerr);
+ cinfo.client_data = &jmpbufw;
+ if (setjmp (jmpbufw.jmpbuf) != 0) {
+ /* we're here courtesy of longjmp */
+ if (row) {
+ gdFree (row);
+ }
+ if (im) {
+ gdImageDestroy (im);
+ }
+ return 0;
+ }
- memset (&cinfo, 0, sizeof (cinfo));
- memset (&jerr, 0, sizeof (jerr));
+ cinfo.err->error_exit = fatal_jpeg_error;
- cinfo.err = jpeg_std_error (&jerr);
- cinfo.client_data = &jmpbufw;
- if (setjmp (jmpbufw.jmpbuf) != 0)
- {
- /* we're here courtesy of longjmp */
- if (row)
- gdFree (row);
- if (im)
- gdImageDestroy (im);
- return 0;
- }
-
- cinfo.err->error_exit = fatal_jpeg_error;
-
- jpeg_create_decompress (&cinfo);
-
- jpeg_gdIOCtx_src (&cinfo, infile);
-
- retval = jpeg_read_header (&cinfo, TRUE);
- if (retval != JPEG_HEADER_OK)
- php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header returns"
- " %d, expected %d\n", retval, JPEG_HEADER_OK);
-
- if (cinfo.image_height > INT_MAX)
- php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image height (%u) is"
- " greater than INT_MAX (%d) (and thus greater than"
- " gd can handle)", cinfo.image_height,
- INT_MAX);
-
- if (cinfo.image_width > INT_MAX)
- php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image width (%u) is"
- " greater than INT_MAX (%d) (and thus greater than"
- " gd can handle)\n", cinfo.image_width, INT_MAX);
-
- im = gdImageCreateTrueColor ((int) cinfo.image_width,
- (int) cinfo.image_height);
- if (im == 0)
- {
- php_gd_error("gd-jpeg error: cannot allocate gdImage"
- " struct\n");
- goto error;
- }
-
- /*
- * Force the image into RGB colorspace, but don't
- * reduce the number of colors anymore (GD 2.0)
- */
- cinfo.out_color_space = JCS_RGB;
-
- if (jpeg_start_decompress (&cinfo) != TRUE)
- php_gd_error("gd-jpeg: warning: jpeg_start_decompress"
- " reports suspended data source\n");
-
-#ifdef JPEG_DEBUG
- printf ("gd-jpeg: JPEG image information:");
- if (cinfo.saw_JFIF_marker)
- printf (" JFIF version %d.%.2d",
- (int) cinfo.JFIF_major_version,
- (int) cinfo.JFIF_minor_version);
- else if (cinfo.saw_Adobe_marker)
- printf (" Adobe format");
- else
- printf (" UNKNOWN format");
-
- printf (" %ux%u (raw) / %ux%u (scaled) %d-bit", cinfo.image_width,
- cinfo.image_height, cinfo.output_width,
- cinfo.output_height, cinfo.data_precision);
- printf (" %s", (cinfo.progressive_mode ? "progressive" :
- "baseline"));
- printf (" image, %d quantized colors, ",
- cinfo.actual_number_of_colors);
-
- switch (cinfo.jpeg_color_space)
- {
- case JCS_GRAYSCALE:
- printf ("grayscale");
- break;
-
- case JCS_RGB:
- printf ("RGB");
- break;
-
- case JCS_YCbCr:
- printf ("YCbCr (a.k.a. YUV)");
- break;
-
- case JCS_CMYK:
- printf ("CMYK");
- break;
-
- case JCS_YCCK:
- printf ("YCbCrK");
- break;
-
- default:
- printf ("UNKNOWN (value: %d)", (int) cinfo.jpeg_color_space);
- break;
- }
- printf (" colorspace\n");
- fflush (stdout);
-#endif /* JPEG_DEBUG */
-
- /* REMOVED by TBB 2/12/01. This field of the structure is
- documented as private, and sure enough it's gone in the
- latest libjpeg, replaced by something else. Unfortunately
- there is still no right way to find out if the file was
- progressive or not; just declare your intent before you
- write one by calling gdImageInterlace(im, 1) yourself.
- After all, we're not really supposed to rework JPEGs and
- write them out again anyway. Lossy compression, remember? */
+ jpeg_create_decompress (&cinfo);
+
+ jpeg_gdIOCtx_src (&cinfo, infile);
+
+ retval = jpeg_read_header (&cinfo, TRUE);
+ if (retval != JPEG_HEADER_OK) {
+ php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header
+returned %d, expected %d", retval, JPEG_HEADER_OK);
+ }
+
+ if (cinfo.image_height > INT_MAX) {
+ php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image height (%u)
+is greater than INT_MAX (%d) (and thus greater than gd can handle)",
+cinfo.image_height, INT_MAX);
+ }
+
+ if (cinfo.image_width > INT_MAX) {
+ php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image width (%u) is
+greater than INT_MAX (%d) (and thus greater than gd can handle)", cinfo.image_width,
+INT_MAX);
+ }
+
+ im = gdImageCreateTrueColor ((int) cinfo.image_width, (int)
+cinfo.image_height);
+ if (im == 0) {
+ php_gd_error("gd-jpeg error: cannot allocate gdImage struct");
+ goto error;
+ }
+
+ /* Force the image into RGB colorspace, but don't reduce the number of colors
+anymore (GD 2.0) */
+ cinfo.out_color_space = JCS_RGB;
+
+ if (jpeg_start_decompress (&cinfo) != TRUE) {
+ php_gd_error("gd-jpeg: warning: jpeg_start_decompress reports
+suspended data source");
+ }
+
+ /* REMOVED by TBB 2/12/01. This field of the structure is
+ * documented as private, and sure enough it's gone in the
+ * latest libjpeg, replaced by something else. Unfortunately
+ * there is still no right way to find out if the file was
+ * progressive or not; just declare your intent before you
+ * write one by calling gdImageInterlace(im, 1) yourself.
+ * After all, we're not really supposed to rework JPEGs and
+ * write them out again anyway. Lossy compression, remember?
+ */
#if 0
gdImageInterlace (im, cinfo.progressive_mode != 0);
#endif
- if (cinfo.output_components != 3)
- {
- php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization"
- " request resulted in output_components == %d"
- " (expected 3)\n", cinfo.output_components);
- goto error;
- }
+
+ if (cinfo.output_components != 3) {
+ php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization
+request resulted in output_components == %d (expected 3)", cinfo.output_components);
+ goto error;
+ }
#if BITS_IN_JSAMPLE == 12
- php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit\n"
- "precision. This is mostly useless, because JPEGs on the web are\n"
- "8-bit and such versions of the jpeg library won't read or write\n"
- "them. GD doesn't support these unusual images. Edit your\n"
- "jmorecfg.h file to specify the correct precision and completely\n"
- "'make clean' and 'make install' libjpeg again. Sorry.\n");
- goto error;
+ php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit precision.
+This is mostly useless, because JPEGs on the web are 8-bit and such versions of the
+jpeg library won't read or write them. GD doesn't support these unusual images. Edit
+your jmorecfg.h file to specify the correct precision and completely 'make clean' and
+'make install' libjpeg again. Sorry.");
+ goto error;
#endif /* BITS_IN_JSAMPLE == 12 */
- row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE));
- if (row == 0)
- {
- php_gd_error("gd-jpeg: error: unable to allocate row for"
- " JPEG scanline: gdCalloc returns NULL\n");
- goto error;
- }
- rowptr[0] = row;
-
- for (i = 0; i < cinfo.output_height; i++)
- {
- nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
- if (nrows != 1)
- {
- php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines"
- " 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]);
- }
-
- if (jpeg_finish_decompress (&cinfo) != TRUE)
- php_gd_error("gd-jpeg: warning: jpeg_finish_decompress"
- " reports suspended data source\n");
-
-
- jpeg_destroy_decompress (&cinfo);
- gdFree (row);
- return im;
+ row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE));
+ rowptr[0] = row;
+
+ 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) {
+ php_gd_error_ex(E_WARNING, "gd-jpeg: error:
+jpeg_read_scanlines returns %u, expected 1", 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) {
+ php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports
+suspended data source");
+ }
+
+ jpeg_destroy_decompress (&cinfo);
+ gdFree (row);
+
+ return im;
error:
- jpeg_destroy_decompress (&cinfo);
- if (row)
- gdFree (row);
- if (im)
- gdImageDestroy (im);
- return 0;
+ jpeg_destroy_decompress (&cinfo);
+ if (row) {
+ gdFree (row);
+ }
+ if (im) {
+ gdImageDestroy (im);
+ }
+ return 0;
}
/*
@@ -488,15 +371,13 @@
/* Expanded data source object for gdIOCtx input */
typedef struct
- {
- struct jpeg_source_mgr pub; /* public fields */
+{
+ struct jpeg_source_mgr pub; /* public fields */
- gdIOCtx *infile; /* source stream */
- unsigned char *buffer; /* start of buffer */
- safeboolean start_of_file; /* have we gotten any data yet? */
-
- }
-my_source_mgr;
+ 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;
@@ -510,13 +391,13 @@
void
init_source (j_decompress_ptr cinfo)
{
- my_src_ptr src = (my_src_ptr) cinfo->src;
+ my_src_ptr src = (my_src_ptr) cinfo->src;
- /* We reset the empty-input-file flag for each image,
- * but we don't clear the input buffer.
- * This is correct behavior for reading a series of images from one source.
- */
- src->start_of_file = TRUE;
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+ src->start_of_file = TRUE;
}
@@ -558,56 +439,42 @@
safeboolean
fill_input_buffer (j_decompress_ptr cinfo)
{
- my_src_ptr src = (my_src_ptr) cinfo->src;
- size_t nbytes = 0;
+ 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);
+ /* size_t got; */
+ /* char *s; */
+ memset (src->buffer, 0, INPUT_BUF_SIZE);
- while (nbytes < INPUT_BUF_SIZE)
- {
-
- int got = gdGetBuf (src->buffer + nbytes,
- INPUT_BUF_SIZE - nbytes,
- src->infile);
+ while (nbytes < INPUT_BUF_SIZE) {
+ int got = gdGetBuf (src->buffer + nbytes, INPUT_BUF_SIZE - nbytes,
+src->infile);
- if ((got == EOF) || (got == 0))
- {
-
- /* EOF or error. If we got any data, don't worry about it.
- If we didn't, then this is unexpected. */
- if (!nbytes)
- {
-
- nbytes = -1;
-
- }
-
- break;
-
+ if ((got == EOF) || (got == 0)) {
+ /* EOF or error. If we got any data, don't worry about it. If we
+didn't, then this is unexpected. */
+ if (!nbytes) {
+ nbytes = -1;
+ }
+ break;
+ }
+ nbytes += got;
}
-
- nbytes += got;
-
- }
- if (nbytes <= 0)
- {
- if (src->start_of_file) /* Treat empty input file as fatal error */
- ERREXIT (cinfo, JERR_INPUT_EMPTY);
- WARNMS (cinfo, JWRN_JPEG_EOF);
- /* Insert a fake EOI marker */
- src->buffer[0] = (unsigned char) 0xFF;
- src->buffer[1] = (unsigned char) JPEG_EOI;
- nbytes = 2;
- }
-
- src->pub.next_input_byte = src->buffer;
- src->pub.bytes_in_buffer = nbytes;
- src->start_of_file = FALSE;
+ if (nbytes <= 0) {
+ if (src->start_of_file) { /* Treat empty input file as fatal error */
+ ERREXIT (cinfo, JERR_INPUT_EMPTY);
+ }
+ WARNMS (cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (unsigned char) 0xFF;
+ src->buffer[1] = (unsigned char) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = FALSE;
- return TRUE;
+ return TRUE;
}
@@ -626,24 +493,22 @@
void
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
- my_src_ptr src = (my_src_ptr) cinfo->src;
+ my_src_ptr src = (my_src_ptr) cinfo->src;
- /* Just a dumb implementation for now. Not clear that being smart is worth
- * any trouble anyway --- large skips are infrequent.
- */
- if (num_bytes > 0)
- {
- while (num_bytes > (long) src->pub.bytes_in_buffer)
- {
- num_bytes -= (long) src->pub.bytes_in_buffer;
- (void) fill_input_buffer (cinfo);
- /* note we assume that fill_input_buffer will never return FALSE,
- * so suspension need not be handled.
- */
- }
- src->pub.next_input_byte += (size_t) num_bytes;
- src->pub.bytes_in_buffer -= (size_t) num_bytes;
- }
+ /* Just a dumb implementation for now. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+ if (num_bytes > 0) {
+ while (num_bytes > (long) src->pub.bytes_in_buffer) {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) fill_input_buffer (cinfo);
+ /* note we assume that fill_input_buffer will never return
+FALSE,
+ * so suspension need not be handled.
+ */
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
}
@@ -668,11 +533,9 @@
void
term_source (j_decompress_ptr cinfo)
{
-
#if 0
-/* never used */
- my_src_ptr src = (my_src_ptr) cinfo->src;
-
+ * never used */
+ my_src_ptr src = (my_src_ptr) cinfo->src;
#endif
}
@@ -684,50 +547,44 @@
*/
void
-jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
- gdIOCtx * infile)
+jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile)
{
- my_src_ptr src;
+ my_src_ptr src;
- /* The source object and input buffer are made permanent so that a series
- * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src
- * only before the first one. (If we discarded the buffer at the end of
- * one image, we'd likely lose the start of the next one.)
- * This makes it unsafe to use this manager and a different source
- * manager serially with the same JPEG object. Caveat programmer.
- */
- if (cinfo->src == NULL)
- { /* first time for this JPEG object? */
- cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof (my_source_mgr));
- src = (my_src_ptr) cinfo->src;
- src->buffer = (unsigned char *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- INPUT_BUF_SIZE * sizeof (unsigned char));
+ /* The source object and input buffer are made permanent so that a series
+ * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src
+ * only before the first one. (If we discarded the buffer at the end of
+ * one image, we'd likely lose the start of the next one.)
+ * This makes it unsafe to use this manager and a different source
+ * manager serially with the same JPEG object. Caveat programmer.
+ */
+ if (cinfo->src == NULL) { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+sizeof (my_source_mgr));
+ src = (my_src_ptr) cinfo->src;
+ src->buffer = (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;
- src->pub.fill_input_buffer = fill_input_buffer;
- src->pub.skip_input_data = skip_input_data;
- src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
- src->pub.term_source = term_source;
- src->infile = infile;
- src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
- src->pub.next_input_byte = NULL; /* until buffer loaded */
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method
+*/
+ src->pub.term_source = term_source;
+ src->infile = infile;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
}
/* Expanded data destination object for stdio output */
typedef struct
{
- struct jpeg_destination_mgr pub; /* public fields */
- gdIOCtx *outfile; /* target stream */
- unsigned char *buffer; /* start of buffer */
-}
-my_destination_mgr;
+ struct jpeg_destination_mgr pub; /* public fields */
+ gdIOCtx *outfile; /* target stream */
+ unsigned char *buffer; /* start of buffer */
+} my_destination_mgr;
typedef my_destination_mgr *my_dest_ptr;
@@ -741,15 +598,13 @@
void
init_destination (j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
- /* Allocate the output buffer --- it will be released when done with image */
- dest->buffer = (unsigned char *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- OUTPUT_BUF_SIZE * sizeof (unsigned char));
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr)
+cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof (unsigned char));
- dest->pub.next_output_byte = dest->buffer;
- dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
@@ -779,16 +634,16 @@
safeboolean
empty_output_buffer (j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
- if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) !=
- (size_t) OUTPUT_BUF_SIZE)
- ERREXIT (cinfo, JERR_FILE_WRITE);
+ if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t)
+OUTPUT_BUF_SIZE) {
+ ERREXIT (cinfo, JERR_FILE_WRITE);
+ }
- dest->pub.next_output_byte = dest->buffer;
- dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
- return TRUE;
+ return TRUE;
}
@@ -804,15 +659,13 @@
void
term_destination (j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
- size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
- /* Write any data remaining in the buffer */
- if (datacount > 0)
- {
- if ((size_t)gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount)
- ERREXIT (cinfo, JERR_FILE_WRITE);
- }
+ /* Write any data remaining in the buffer */
+ if (datacount > 0 && ((size_t)gdPutBuf (dest->buffer, datacount,
+dest->outfile) != datacount)) {
+ ERREXIT (cinfo, JERR_FILE_WRITE);
+ }
}
@@ -825,26 +678,23 @@
void
jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile)
{
- my_dest_ptr dest;
+ my_dest_ptr dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_stdio_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof
+(my_destination_mgr));
+ }
- /* The destination object is made permanent so that multiple JPEG images
- * can be written to the same file without re-executing jpeg_stdio_dest.
- * This makes it dangerous to use this manager and a different destination
- * manager serially with the same JPEG object, because their private object
- * sizes may be different. Caveat programmer.
- */
- if (cinfo->dest == NULL)
- { /* first time for this JPEG object? */
- cinfo->dest = (struct jpeg_destination_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof (my_destination_mgr));
- }
-
- dest = (my_dest_ptr) cinfo->dest;
- dest->pub.init_destination = init_destination;
- dest->pub.empty_output_buffer = empty_output_buffer;
- dest->pub.term_destination = term_destination;
- dest->outfile = outfile;
+ dest = (my_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = outfile;
}
#endif /* HAVE_JPEG */
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php