Skip to content

Commit 8b07907

Browse files
author
Ilia Alshanetsky
committed
Synchronized bundled GD library with GD 2.0.22.
1 parent c29e927 commit 8b07907

20 files changed

+216
-42
lines changed

ext/gd/gd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ PHP_RSHUTDOWN_FUNCTION(gd)
453453
/* }}} */
454454

455455
#if HAVE_GD_BUNDLED
456-
#define PHP_GD_VERSION_STRING "bundled (2.0.17 compatible)"
456+
#define PHP_GD_VERSION_STRING "bundled (2.0.22 compatible)"
457457
#elif HAVE_LIBGD20
458458
#define PHP_GD_VERSION_STRING "2.0 or higher"
459459
#elif HAVE_GDIMAGECOLORRESOLVE

ext/gd/libgd/gd.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,15 +2300,17 @@ void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int
23002300
int tmp = gdImageGetPixel (src, x, y);
23012301
mapTo = gdImageGetTrueColorPixel (src, x, y);
23022302
if (gdImageGetTransparent (src) == tmp) {
2303-
tox++;
2303+
/* 2.0.21, TK: not tox++ */
2304+
tox += stx[x - srcX];
23042305
continue;
23052306
}
23062307
} else {
23072308
/* TK: old code follows */
23082309
mapTo = gdImageGetTrueColorPixel (src, x, y);
23092310
/* Added 7/24/95: support transparent copies */
23102311
if (gdImageGetTransparent (src) == mapTo) {
2311-
tox++;
2312+
/* 2.0.21, TK: not tox++ */
2313+
tox += stx[x - srcX];
23122314
continue;
23132315
}
23142316
}
@@ -2364,22 +2366,24 @@ void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int
23642366
void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
23652367
{
23662368
int x, y;
2369+
double sy1, sy2, sx1, sx2;
23672370
if (!dst->trueColor) {
23682371
gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
23692372
return;
23702373
}
23712374
for (y = dstY; (y < dstY + dstH); y++) {
2375+
sy1 = ((double) y - (double) dstY) * (double) srcH / (double) dstH;
2376+
sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH / (double) dstH;
23722377
for (x = dstX; (x < dstX + dstW); x++) {
2373-
float sy1, sy2, sx1, sx2;
2374-
float sx, sy;
2375-
float spixels = 0.0f;
2376-
float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f;
2377-
float alpha_factor, alpha_sum = 0.0f, contrib_sum = 0.0f;
2378-
sy1 = ((float)(y - dstY)) * (float)srcH / (float)dstH;
2379-
sy2 = ((float)(y + 1 - dstY)) * (float) srcH / (float) dstH;
2378+
double sx, sy;
2379+
double spixels = 0;
2380+
double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
2381+
double alpha_factor, alpha_sum = 0.0, contrib_sum = 0.0;
2382+
sx1 = ((double) x - (double) dstX) * (double) srcW / dstW;
2383+
sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / dstW;
23802384
sy = sy1;
23812385
do {
2382-
float yportion;
2386+
double yportion;
23832387
if (floor_cast(sy) == floor_cast(sy1)) {
23842388
yportion = 1.0f - (sy - floor_cast(sy));
23852389
if (yportion > sy2 - sy1) {
@@ -2391,12 +2395,10 @@ void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, i
23912395
} else {
23922396
yportion = 1.0f;
23932397
}
2394-
sx1 = ((float)(x - dstX)) * (float) srcW / dstW;
2395-
sx2 = ((float)(x + 1 - dstX)) * (float) srcW / dstW;
23962398
sx = sx1;
23972399
do {
2398-
float xportion;
2399-
float pcontribution;
2400+
double xportion;
2401+
double pcontribution;
24002402
int p;
24012403
if (floorf(sx) == floor_cast(sx1)) {
24022404
xportion = 1.0f - (sx - floor_cast(sx));

ext/gd/libgd/gd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ void gdImageSaveAlpha(gdImagePtr im, int saveAlphaArg);
579579

580580
gdIOCtx* gdNewFileCtx(FILE*);
581581
gdIOCtx* gdNewDynamicCtx(int, void*);
582+
gdIOCtx *gdNewDynamicCtxEx(int size, void *data, int freeFlag);
582583
gdIOCtx* gdNewSSCtx(gdSourcePtr in, gdSinkPtr out);
583584
void* gdDPExtractData(struct gdIOCtx* ctx, int *size);
584585

ext/gd/libgd/gd_gd.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,16 @@ gdImagePtr gdImageCreateFromGd (FILE * inFile)
146146
return im;
147147
}
148148

149+
gdImagePtr gdImageCreateFromGdPtr (int size, void *data)
150+
{
151+
gdImagePtr im;
152+
gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
153+
im = gdImageCreateFromGdCtx(in);
154+
in->gd_free(in);
155+
156+
return im;
157+
}
158+
149159
gdImagePtr gdImageCreateFromGdCtx (gdIOCtxPtr in)
150160
{
151161
int sx, sy;

ext/gd/libgd/gd_gd2.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,16 @@ gdImagePtr gdImageCreateFromGd2 (FILE * inFile)
236236
return im;
237237
}
238238

239+
gdImagePtr gdImageCreateFromGd2Ptr (int size, void *data)
240+
{
241+
gdImagePtr im;
242+
gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
243+
im = gdImageCreateFromGd2Ctx(in);
244+
in->gd_free(in);
245+
246+
return im;
247+
}
248+
239249
gdImagePtr gdImageCreateFromGd2Ctx (gdIOCtxPtr in)
240250
{
241251
int sx, sy;
@@ -377,6 +387,16 @@ gdImagePtr gdImageCreateFromGd2Ctx (gdIOCtxPtr in)
377387
return 0;
378388
}
379389

390+
gdImagePtr gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w, int h)
391+
{
392+
gdImagePtr im;
393+
gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
394+
im = gdImageCreateFromGd2PartCtx(in, srcx, srcy, w, h);
395+
in->gd_free(in);
396+
397+
return im;
398+
}
399+
380400
gdImagePtr gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h)
381401
{
382402
gdImagePtr im;

ext/gd/libgd/gd_io_dp.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ typedef struct dpStruct
3333
int realSize;
3434
int dataGood;
3535
int pos;
36+
int freeOK;
3637
} dynamicPtr;
3738

3839
typedef struct dpIOCtx
@@ -49,7 +50,7 @@ static int appendDynamic (dynamicPtr * dp, const void *src, int size);
4950
static int gdReallocDynamic (dynamicPtr * dp, int required);
5051
static int trimDynamic (dynamicPtr * dp);
5152
static void gdFreeDynamicCtx (struct gdIOCtx *ctx);
52-
static dynamicPtr *newDynamic (int initialSize, void *data);
53+
static dynamicPtr *newDynamic (int initialSize, void *data, int freeOKFlag);
5354

5455
static int dynamicPutbuf (struct gdIOCtx *, const void *, int);
5556
static void dynamicPutchar (struct gdIOCtx *, int a);
@@ -62,13 +63,18 @@ static long dynamicTell (struct gdIOCtx *);
6263

6364
/* return data as a dynamic pointer */
6465
gdIOCtx * gdNewDynamicCtx (int initialSize, void *data)
66+
{
67+
return gdNewDynamicCtxEx(initialSize, data, 1);
68+
}
69+
70+
gdIOCtx * gdNewDynamicCtxEx (int initialSize, void *data, int freeOKFlag)
6571
{
6672
dpIOCtx *ctx;
6773
dynamicPtr *dp;
6874

6975
ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx));
7076

71-
dp = newDynamic(initialSize, data);
77+
dp = newDynamic(initialSize, data, freeOKFlag);
7278

7379
ctx->dp = dp;
7480

@@ -103,7 +109,7 @@ void * gdDPExtractData (struct gdIOCtx *ctx, int *size)
103109
} else {
104110
*size = 0;
105111
data = NULL;
106-
if (dp->data != NULL) {
112+
if (dp->data != NULL && dp->freeOK) {
107113
gdFree(dp->data);
108114
}
109115
}
@@ -155,6 +161,10 @@ static int dynamicSeek (struct gdIOCtx *ctx, const int pos)
155161

156162
bytesNeeded = pos;
157163
if (bytesNeeded > dp->realSize) {
164+
/* 2.0.21 */
165+
if (!dp->freeOK) {
166+
return FALSE;
167+
}
158168
gdReallocDynamic (dp, dp->realSize * 2);
159169
}
160170

@@ -171,14 +181,15 @@ static int dynamicSeek (struct gdIOCtx *ctx, const int pos)
171181
}
172182

173183
/* return data as a dynamic pointer */
174-
static dynamicPtr * newDynamic (int initialSize, void *data)
184+
static dynamicPtr * newDynamic (int initialSize, void *data, int freeOKFlag)
175185
{
176186
dynamicPtr *dp;
177187
dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr));
178188

179189
allocDynamic (dp, initialSize, data);
180190

181191
dp->pos = 0;
192+
dp->freeOK = freeOKFlag;
182193

183194
return dp;
184195
}
@@ -292,6 +303,10 @@ static int appendDynamic (dynamicPtr * dp, const void *src, int size)
292303
bytesNeeded = dp->pos + size;
293304

294305
if (bytesNeeded > dp->realSize) {
306+
/* 2.0.21 */
307+
if (!dp->freeOK) {
308+
return FALSE;
309+
}
295310
gdReallocDynamic(dp, bytesNeeded * 2);
296311
}
297312

@@ -337,5 +352,9 @@ static int gdReallocDynamic (dynamicPtr * dp, int required)
337352
/* trim pointer so that its real and logical sizes match */
338353
static int trimDynamic (dynamicPtr * dp)
339354
{
355+
/* 2.0.21: we don't reallocate memory we don't own */
356+
if (!dp->freeOK) {
357+
return FALSE;
358+
}
340359
return gdReallocDynamic(dp, dp->logicalSize);
341360
}

ext/gd/libgd/gd_jpeg.c

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,20 @@ gdImagePtr gdImageCreateFromJpeg (FILE * inFile)
217217
return im;
218218
}
219219

220+
gdImagePtr gdImageCreateFromJpegPtr (int size, void *data)
221+
{
222+
gdImagePtr im;
223+
gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
224+
im = gdImageCreateFromJpegCtx(in);
225+
in->gd_free(in);
226+
227+
return im;
228+
}
229+
220230
void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
221231

232+
static int CMYKToRGB(int c, int m, int y, int k, int inverted);
233+
222234
/*
223235
* Create a gd-format image from the JPEG-format INFILE. Returns the
224236
* image, or NULL upon error.
@@ -235,6 +247,8 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
235247
unsigned int i, j;
236248
int retval;
237249
JDIMENSION nrows;
250+
int channels = 3;
251+
int inverted = 0;
238252

239253
memset (&cinfo, 0, sizeof (cinfo));
240254
memset (&jerr, 0, sizeof (jerr));
@@ -258,6 +272,9 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
258272

259273
jpeg_gdIOCtx_src (&cinfo, infile);
260274

275+
/* 2.0.22: save the APP14 marker to check for Adobe Photoshop CMYK files with inverted components. */
276+
jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256);
277+
261278
retval = jpeg_read_header (&cinfo, TRUE);
262279
if (retval != JPEG_HEADER_OK) {
263280
php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header returned %d, expected %d", retval, JPEG_HEADER_OK);
@@ -277,8 +294,14 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
277294
goto error;
278295
}
279296

280-
/* Force the image into RGB colorspace, but don't reduce the number of colors anymore (GD 2.0) */
281-
cinfo.out_color_space = JCS_RGB;
297+
/* 2.0.22: very basic support for reading CMYK colorspace files. Nice for
298+
* thumbnails but there's no support for fussy adjustment of the
299+
* assumed properties of inks and paper. */
300+
if ((cinfo.jpeg_color_space == JCS_CMYK) || (cinfo.jpeg_color_space == JCS_YCCK)) {
301+
cinfo.out_color_space = JCS_CMYK;
302+
} else {
303+
cinfo.out_color_space = JCS_RGB;
304+
}
282305

283306
if (jpeg_start_decompress (&cinfo) != TRUE) {
284307
php_gd_error("gd-jpeg: warning: jpeg_start_decompress reports suspended data source");
@@ -297,8 +320,29 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
297320
gdImageInterlace (im, cinfo.progressive_mode != 0);
298321
#endif
299322

300-
if (cinfo.output_components != 3) {
301-
php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization request resulted in output_components == %d (expected 3)", cinfo.output_components);
323+
if (cinfo.out_color_space == JCS_RGB) {
324+
if (cinfo.output_components != 3) {
325+
php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization request resulted in output_components == %d (expected 3 for RGB)", cinfo.output_components);
326+
goto error;
327+
}
328+
channels = 3;
329+
} else if (cinfo.out_color_space == JCS_CMYK) {
330+
jpeg_saved_marker_ptr marker;
331+
if (cinfo.output_components != 4) {
332+
php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization request resulted in output_components == %d (expected 4 for CMYK)", cinfo.output_components);
333+
goto error;
334+
}
335+
channels = 4;
336+
marker = cinfo.marker_list;
337+
while (marker) {
338+
if ((marker->marker == (JPEG_APP0 + 14)) && (marker->data_length >= 12) && (!strncmp((const char *) marker->data, "Adobe", 5))) {
339+
inverted = 1;
340+
break;
341+
}
342+
marker = marker->next;
343+
}
344+
} else {
345+
php_gd_error_ex(E_WARNING, "gd-jpeg: error: unexpected colorspace.");
302346
goto error;
303347
}
304348

@@ -307,22 +351,37 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
307351
goto error;
308352
#endif /* BITS_IN_JSAMPLE == 12 */
309353

310-
row = safe_emalloc(cinfo.output_width * 3, sizeof(JSAMPLE), 0);
311-
memset(row, 0, cinfo.output_width * 3 * sizeof(JSAMPLE));
354+
row = safe_emalloc(cinfo.output_width * channels, sizeof(JSAMPLE), 0);
355+
memset(row, 0, cinfo.output_width * channels * sizeof(JSAMPLE));
312356
rowptr[0] = row;
313357

314-
for (i = 0; i < cinfo.output_height; i++) {
315-
register JSAMPROW currow = row;
316-
register int *tpix = im->tpixels[i];
317-
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
318-
if (nrows != 1) {
319-
php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows);
320-
goto error;
358+
if (cinfo.out_color_space == JCS_CMYK) {
359+
for (i = 0; i < cinfo.output_height; i++) {
360+
register JSAMPROW currow = row;
361+
register int *tpix = im->tpixels[i];
362+
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
363+
if (nrows != 1) {
364+
php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows);
365+
goto error;
366+
}
367+
for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++) {
368+
*tpix = CMYKToRGB (currow[0], currow[1], currow[2], currow[3], inverted);
369+
}
321370
}
322-
for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) {
323-
*tpix = gdTrueColor (currow[0], currow[1], currow[2]);
371+
} else {
372+
for (i = 0; i < cinfo.output_height; i++) {
373+
register JSAMPROW currow = row;
374+
register int *tpix = im->tpixels[i];
375+
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
376+
if (nrows != 1) {
377+
php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows);
378+
goto error;
379+
}
380+
for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) {
381+
*tpix = gdTrueColor (currow[0], currow[1], currow[2]);
382+
}
324383
}
325-
}
384+
}
326385

327386
if (jpeg_finish_decompress (&cinfo) != TRUE) {
328387
php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source");
@@ -349,8 +408,19 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
349408
return 0;
350409
}
351410

352-
/*
411+
/* A very basic conversion approach, TBB */
412+
static int CMYKToRGB(int c, int m, int y, int k, int inverted)
413+
{
414+
if (inverted) {
415+
c = 255 - c;
416+
m = 255 - m;
417+
y = 255 - y;
418+
k = 255 - k;
419+
}
420+
return gdTrueColor((255 - c) * (255 - k) / 255, (255 - m) * (255 - k) / 255, (255 - y) * (255 - k) / 255);
421+
}
353422

423+
/*
354424
* gdIOCtx JPEG data sources and sinks, T. Boutell
355425
* almost a simple global replace from T. Lane's stdio versions.
356426
*

0 commit comments

Comments
 (0)