This source file includes following definitions.
- php_gd_error_ex
- php_gd_error
- gdImageCreate
- gdImageCreateTrueColor
- gdImageDestroy
- gdImageColorClosest
- gdImageColorClosestAlpha
- RGB_to_HWB
- HWB_Diff
- HWB_to_RGB
- gdImageColorClosestHWB
- gdImageColorExact
- gdImageColorExactAlpha
- gdImageColorAllocate
- gdImageColorAllocateAlpha
- gdImageColorResolve
- gdImageColorResolveAlpha
- gdImageColorDeallocate
- gdImageColorTransparent
- gdImagePaletteCopy
- clip_1d
- gdImageSetPixel
- gdImageGetTrueColorPixel
- gdImageBrushApply
- gdImageTileApply
- gdImageTileGet
- gdImageAntiAliasedApply
- gdImageGetPixel
- gdImageAABlend
- gdImageHLine
- gdImageVLine
- gdImageLine
- gdImageSetAAPixelColor
- gdImageAALine
- gdImageDashedLine
- dashedSet
- gdImageChar
- gdImageCharUp
- gdImageString
- gdImageStringUp
- gdImageString16
- gdImageStringUp16
- strlen16
- lsqrt
- gdImageArc
- gdImageFilledArc
- gdImageFillToBorder
- gdImageFill
- _gdImageFillTiled
- gdImageRectangle
- gdImageFilledRectangle
- gdImageCopy
- gdImageCopyMerge
- gdImageCopyMergeGray
- gdImageCopyResized
- gdImageCopyResampled
- gdImagePolygon
- gdImageFilledPolygon
- gdCompareInt
- gdImageSetStyle
- gdImageSetThickness
- gdImageSetBrush
- gdImageSetTile
- gdImageSetAntiAliased
- gdImageSetAntiAliasedDontBlend
- gdImageInterlace
- gdImageCompare
- gdAlphaBlendOld
- gdAlphaBlend
- gdImageAlphaBlending
- gdImageAntialias
- gdImageSaveAlpha
- gdLayerOverlay
- gdAlphaOverlayColor
- gdImageSetClip
- gdImageGetClip
- gdImagePaletteToTrueColor
1
2 #include <math.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "gd.h"
6 #include "gdhelpers.h"
7
8 #include "php.h"
9
10 #ifdef _MSC_VER
11 # if _MSC_VER >= 1300
12
13 # if !defined(_MSC_EXTENSIONS) && defined(__cplusplus)
14 # define HAVE_FABSF 1
15 extern float fabsf(float x);
16 # define HAVE_FLOORF 1
17 extern float floorf(float x);
18 # endif
19 # endif
20 #endif
21 #ifndef HAVE_FABSF
22 # define HAVE_FABSF 0
23 #endif
24 #ifndef HAVE_FLOORF
25 # define HAVE_FLOORF 0
26 #endif
27 #if HAVE_FABSF == 0
28
29 # ifndef fabsf
30 # define fabsf(x) ((float)(fabs(x)))
31 # endif
32 #endif
33 #if HAVE_FLOORF == 0
34 # ifndef floorf
35
36 # define floorf(x) ((float)(floor(x)))
37 # endif
38 #endif
39
40 #ifdef _OSD_POSIX
41 #define CHARSET_EBCDIC
42 #define __attribute__(any)
43 #endif
44
45
46 #ifndef CHARSET_EBCDIC
47 #define ASC(ch) ch
48 #else
49 #define ASC(ch) gd_toascii[(unsigned char)ch]
50 static const unsigned char gd_toascii[256] =
51 {
52 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f,
53 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
54 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97,
55 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f,
56 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b,
57 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
58 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
59 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
60 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
61 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
62 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
63 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f,
64 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
65 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
66
67 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
68 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
69 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
70 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,
71 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
72 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,
73 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
74 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae,
75 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
76 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7,
77 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
78 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
79 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
80 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff,
81 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
82 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,
83 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
84 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e
85 };
86 #endif
87
88
89 #define floor_cast(exp) ((long) exp)
90
91 extern int gdCosT[];
92 extern int gdSinT[];
93
94 static void gdImageBrushApply(gdImagePtr im, int x, int y);
95 static void gdImageTileApply(gdImagePtr im, int x, int y);
96 static void gdImageAntiAliasedApply(gdImagePtr im, int x, int y);
97 static int gdLayerOverlay(int dst, int src);
98 static int gdAlphaOverlayColor(int src, int dst, int max);
99 int gdImageGetTrueColorPixel(gdImagePtr im, int x, int y);
100
101 void php_gd_error_ex(int type, const char *format, ...)
102 {
103 va_list args;
104
105 TSRMLS_FETCH();
106
107 va_start(args, format);
108 php_verror(NULL, "", type, format, args TSRMLS_CC);
109 va_end(args);
110 }
111
112 void php_gd_error(const char *format, ...)
113 {
114 va_list args;
115
116 TSRMLS_FETCH();
117
118 va_start(args, format);
119 php_verror(NULL, "", E_WARNING, format, args TSRMLS_CC);
120 va_end(args);
121 }
122
123 gdImagePtr gdImageCreate (int sx, int sy)
124 {
125 int i;
126 gdImagePtr im;
127
128 if (overflow2(sx, sy)) {
129 return NULL;
130 }
131
132 if (overflow2(sizeof(unsigned char *), sy)) {
133 return NULL;
134 }
135
136 im = (gdImage *) gdCalloc(1, sizeof(gdImage));
137
138
139 im->pixels = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy);
140 im->AA_opacity = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy);
141 im->polyInts = 0;
142 im->polyAllocated = 0;
143 im->brush = 0;
144 im->tile = 0;
145 im->style = 0;
146 for (i = 0; i < sy; i++) {
147
148 im->pixels[i] = (unsigned char *) gdCalloc(sx, sizeof(unsigned char));
149 im->AA_opacity[i] = (unsigned char *) gdCalloc(sx, sizeof(unsigned char));
150 }
151 im->sx = sx;
152 im->sy = sy;
153 im->colorsTotal = 0;
154 im->transparent = (-1);
155 im->interlace = 0;
156 im->thick = 1;
157 im->AA = 0;
158 im->AA_polygon = 0;
159 for (i = 0; i < gdMaxColors; i++) {
160 im->open[i] = 1;
161 im->red[i] = 0;
162 im->green[i] = 0;
163 im->blue[i] = 0;
164 }
165 im->trueColor = 0;
166 im->tpixels = 0;
167 im->cx1 = 0;
168 im->cy1 = 0;
169 im->cx2 = im->sx - 1;
170 im->cy2 = im->sy - 1;
171 im->interpolation = NULL;
172 im->interpolation_id = GD_BILINEAR_FIXED;
173 return im;
174 }
175
176 gdImagePtr gdImageCreateTrueColor (int sx, int sy)
177 {
178 int i;
179 gdImagePtr im;
180
181 if (overflow2(sx, sy)) {
182 return NULL;
183 }
184
185 if (overflow2(sizeof(unsigned char *), sy)) {
186 return NULL;
187 }
188
189 if (overflow2(sizeof(int), sx)) {
190 return NULL;
191 }
192
193 im = (gdImage *) gdMalloc(sizeof(gdImage));
194 memset(im, 0, sizeof(gdImage));
195 im->tpixels = (int **) gdMalloc(sizeof(int *) * sy);
196 im->AA_opacity = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy);
197 im->polyInts = 0;
198 im->polyAllocated = 0;
199 im->brush = 0;
200 im->tile = 0;
201 im->style = 0;
202 for (i = 0; i < sy; i++) {
203 im->tpixels[i] = (int *) gdCalloc(sx, sizeof(int));
204 im->AA_opacity[i] = (unsigned char *) gdCalloc(sx, sizeof(unsigned char));
205 }
206 im->sx = sx;
207 im->sy = sy;
208 im->transparent = (-1);
209 im->interlace = 0;
210 im->trueColor = 1;
211
212
213
214
215
216
217 im->saveAlphaFlag = 0;
218 im->alphaBlendingFlag = 1;
219 im->thick = 1;
220 im->AA = 0;
221 im->AA_polygon = 0;
222 im->cx1 = 0;
223 im->cy1 = 0;
224 im->cx2 = im->sx - 1;
225 im->cy2 = im->sy - 1;
226 im->interpolation = NULL;
227 im->interpolation_id = GD_BILINEAR_FIXED;
228 return im;
229 }
230
231 void gdImageDestroy (gdImagePtr im)
232 {
233 int i;
234 if (im->pixels) {
235 for (i = 0; i < im->sy; i++) {
236 gdFree(im->pixels[i]);
237 }
238 gdFree(im->pixels);
239 }
240 if (im->tpixels) {
241 for (i = 0; i < im->sy; i++) {
242 gdFree(im->tpixels[i]);
243 }
244 gdFree(im->tpixels);
245 }
246 if (im->AA_opacity) {
247 for (i = 0; i < im->sy; i++) {
248 gdFree(im->AA_opacity[i]);
249 }
250 gdFree(im->AA_opacity);
251 }
252 if (im->polyInts) {
253 gdFree(im->polyInts);
254 }
255 if (im->style) {
256 gdFree(im->style);
257 }
258 gdFree(im);
259 }
260
261 int gdImageColorClosest (gdImagePtr im, int r, int g, int b)
262 {
263 return gdImageColorClosestAlpha (im, r, g, b, gdAlphaOpaque);
264 }
265
266 int gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, int a)
267 {
268 int i;
269 long rd, gd, bd, ad;
270 int ct = (-1);
271 int first = 1;
272 long mindist = 0;
273
274 if (im->trueColor) {
275 return gdTrueColorAlpha(r, g, b, a);
276 }
277 for (i = 0; i < im->colorsTotal; i++) {
278 long dist;
279 if (im->open[i]) {
280 continue;
281 }
282 rd = im->red[i] - r;
283 gd = im->green[i] - g;
284 bd = im->blue[i] - b;
285
286 ad = im->alpha[i] - a;
287 dist = rd * rd + gd * gd + bd * bd + ad * ad;
288 if (first || (dist < mindist)) {
289 mindist = dist;
290 ct = i;
291 first = 0;
292 }
293 }
294 return ct;
295 }
296
297
298
299
300
301
302 #define RETURN_HWB(h, w, b) {HWB->H = h; HWB->W = w; HWB->B = b; return HWB;}
303 #define RETURN_RGB(r, g, b) {RGB->R = r; RGB->G = g; RGB->B = b; return RGB;}
304 #define HWB_UNDEFINED -1
305 #define SETUP_RGB(s, r, g, b) {s.R = r/255.0f; s.G = g/255.0f; s.B = b/255.0f;}
306
307 #ifndef MIN
308 #define MIN(a,b) ((a)<(b)?(a):(b))
309 #endif
310 #define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c)))
311 #ifndef MAX
312 #define MAX(a,b) ((a)<(b)?(b):(a))
313 #endif
314 #define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c)))
315
316
317
318
319
320
321
322 typedef struct
323 {
324 float R, G, B;
325 }
326 RGBType;
327 typedef struct
328 {
329 float H, W, B;
330 }
331 HWBType;
332
333 static HWBType * RGB_to_HWB (RGBType RGB, HWBType * HWB)
334 {
335
336
337
338
339
340 float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f;
341 int i;
342
343 w = MIN3 (R, G, B);
344 v = MAX3 (R, G, B);
345 b = 1 - v;
346 if (v == w) {
347 RETURN_HWB(HWB_UNDEFINED, w, b);
348 }
349 f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
350 i = (R == w) ? 3 : ((G == w) ? 5 : 1);
351
352 RETURN_HWB(i - f / (v - w), w, b);
353 }
354
355 static float HWB_Diff (int r1, int g1, int b1, int r2, int g2, int b2)
356 {
357 RGBType RGB1, RGB2;
358 HWBType HWB1, HWB2;
359 float diff;
360
361 SETUP_RGB(RGB1, r1, g1, b1);
362 SETUP_RGB(RGB2, r2, g2, b2);
363
364 RGB_to_HWB(RGB1, &HWB1);
365 RGB_to_HWB(RGB2, &HWB2);
366
367
368
369
370
371
372 if ((HWB1.H == HWB_UNDEFINED) || (HWB2.H == HWB_UNDEFINED)) {
373 diff = 0.0f;
374 } else {
375 diff = fabsf(HWB1.H - HWB2.H);
376 if (diff > 3.0f) {
377 diff = 6.0f - diff;
378 }
379 }
380
381 diff = diff * diff + (HWB1.W - HWB2.W) * (HWB1.W - HWB2.W) + (HWB1.B - HWB2.B) * (HWB1.B - HWB2.B);
382
383 return diff;
384 }
385
386
387 #if 0
388
389
390
391
392 static RGBType * HWB_to_RGB (HWBType HWB, RGBType * RGB)
393 {
394
395
396
397
398
399 float h = HWB.H, w = HWB.W, b = HWB.B, v, n, f;
400 int i;
401
402 v = 1 - b;
403 if (h == HWB_UNDEFINED) {
404 RETURN_RGB(v, v, v);
405 }
406 i = floor(h);
407 f = h - i;
408 if (i & 1) {
409 f = 1 - f;
410 }
411 n = w + f * (v - w);
412 switch (i) {
413 case 6:
414 case 0:
415 RETURN_RGB(v, n, w);
416 case 1:
417 RETURN_RGB(n, v, w);
418 case 2:
419 RETURN_RGB(w, v, n);
420 case 3:
421 RETURN_RGB(w, n, v);
422 case 4:
423 RETURN_RGB(n, w, v);
424 case 5:
425 RETURN_RGB(v, w, n);
426 }
427
428 return RGB;
429 }
430 #endif
431
432 int gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b)
433 {
434 int i;
435
436 int ct = (-1);
437 int first = 1;
438 float mindist = 0;
439 if (im->trueColor) {
440 return gdTrueColor(r, g, b);
441 }
442 for (i = 0; i < im->colorsTotal; i++) {
443 float dist;
444 if (im->open[i]) {
445 continue;
446 }
447 dist = HWB_Diff(im->red[i], im->green[i], im->blue[i], r, g, b);
448 if (first || (dist < mindist)) {
449 mindist = dist;
450 ct = i;
451 first = 0;
452 }
453 }
454 return ct;
455 }
456
457 int gdImageColorExact (gdImagePtr im, int r, int g, int b)
458 {
459 return gdImageColorExactAlpha (im, r, g, b, gdAlphaOpaque);
460 }
461
462 int gdImageColorExactAlpha (gdImagePtr im, int r, int g, int b, int a)
463 {
464 int i;
465 if (im->trueColor) {
466 return gdTrueColorAlpha(r, g, b, a);
467 }
468 for (i = 0; i < im->colorsTotal; i++) {
469 if (im->open[i]) {
470 continue;
471 }
472 if ((im->red[i] == r) && (im->green[i] == g) && (im->blue[i] == b) && (im->alpha[i] == a)) {
473 return i;
474 }
475 }
476 return -1;
477 }
478
479 int gdImageColorAllocate (gdImagePtr im, int r, int g, int b)
480 {
481 return gdImageColorAllocateAlpha (im, r, g, b, gdAlphaOpaque);
482 }
483
484 int gdImageColorAllocateAlpha (gdImagePtr im, int r, int g, int b, int a)
485 {
486 int i;
487 int ct = (-1);
488 if (im->trueColor) {
489 return gdTrueColorAlpha(r, g, b, a);
490 }
491 for (i = 0; i < im->colorsTotal; i++) {
492 if (im->open[i]) {
493 ct = i;
494 break;
495 }
496 }
497 if (ct == (-1)) {
498 ct = im->colorsTotal;
499 if (ct == gdMaxColors) {
500 return -1;
501 }
502 im->colorsTotal++;
503 }
504 im->red[ct] = r;
505 im->green[ct] = g;
506 im->blue[ct] = b;
507 im->alpha[ct] = a;
508 im->open[ct] = 0;
509
510 return ct;
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524 int gdImageColorResolve (gdImagePtr im, int r, int g, int b)
525 {
526 return gdImageColorResolveAlpha(im, r, g, b, gdAlphaOpaque);
527 }
528
529 int gdImageColorResolveAlpha (gdImagePtr im, int r, int g, int b, int a)
530 {
531 int c;
532 int ct = -1;
533 int op = -1;
534 long rd, gd, bd, ad, dist;
535 long mindist = 4 * 255 * 255;
536 if (im->trueColor)
537 {
538 return gdTrueColorAlpha (r, g, b, a);
539 }
540
541 for (c = 0; c < im->colorsTotal; c++)
542 {
543 if (im->open[c])
544 {
545 op = c;
546 continue;
547 }
548 if (c == im->transparent)
549 {
550
551
552 continue;
553 }
554 rd = (long) (im->red[c] - r);
555 gd = (long) (im->green[c] - g);
556 bd = (long) (im->blue[c] - b);
557 ad = (long) (im->alpha[c] - a);
558 dist = rd * rd + gd * gd + bd * bd + ad * ad;
559 if (dist < mindist)
560 {
561 if (dist == 0)
562 {
563 return c;
564 }
565 mindist = dist;
566 ct = c;
567 }
568 }
569
570 if (op == -1)
571 {
572 op = im->colorsTotal;
573 if (op == gdMaxColors)
574 {
575 return ct;
576 }
577 im->colorsTotal++;
578 }
579 im->red[op] = r;
580 im->green[op] = g;
581 im->blue[op] = b;
582 im->alpha[op] = a;
583 im->open[op] = 0;
584 return op;
585 }
586
587 void gdImageColorDeallocate (gdImagePtr im, int color)
588 {
589 if (im->trueColor) {
590 return;
591 }
592
593 im->open[color] = 1;
594 }
595
596 void gdImageColorTransparent (gdImagePtr im, int color)
597 {
598 if (!im->trueColor) {
599 if (im->transparent != -1) {
600 im->alpha[im->transparent] = gdAlphaOpaque;
601 }
602 if (color > -1 && color < im->colorsTotal && color < gdMaxColors) {
603 im->alpha[color] = gdAlphaTransparent;
604 } else {
605 return;
606 }
607 }
608 im->transparent = color;
609 }
610
611 void gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
612 {
613 int i;
614 int x, y, p;
615 int xlate[256];
616 if (to->trueColor || from->trueColor) {
617 return;
618 }
619
620 for (i = 0; i < 256; i++) {
621 xlate[i] = -1;
622 }
623
624 for (y = 0; y < to->sy; y++) {
625 for (x = 0; x < to->sx; x++) {
626 p = gdImageGetPixel(to, x, y);
627 if (xlate[p] == -1) {
628
629 xlate[p] = gdImageColorClosestAlpha (from, to->red[p], to->green[p], to->blue[p], to->alpha[p]);
630 }
631 gdImageSetPixel(to, x, y, xlate[p]);
632 }
633 }
634
635 for (i = 0; i < from->colorsTotal; i++) {
636 to->red[i] = from->red[i];
637 to->blue[i] = from->blue[i];
638 to->green[i] = from->green[i];
639 to->alpha[i] = from->alpha[i];
640 to->open[i] = 0;
641 }
642
643 for (i = from->colorsTotal; i < to->colorsTotal; i++) {
644 to->open[i] = 1;
645 }
646
647 to->colorsTotal = from->colorsTotal;
648 }
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671 static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
672 double m;
673
674 if (*x0 < 0) {
675 if(*x1 < 0) {
676 return 0;
677 }
678 m = (*y1 - *y0)/(double)(*x1 - *x0);
679
680 *y0 -= (int)(m * *x0);
681 *x0 = 0;
682
683 if (*x1 > maxdim) {
684 *y1 += (int)(m * (maxdim - *x1));
685 *x1 = maxdim;
686 }
687 return 1;
688 }
689 if (*x0 > maxdim) {
690 if (*x1 > maxdim) {
691 return 0;
692 }
693 m = (*y1 - *y0)/(double)(*x1 - *x0);
694 *y0 += (int)(m * (maxdim - *x0));
695 *x0 = maxdim;
696
697 if (*x1 < 0) {
698 *y1 -= (int)(m * *x1);
699 *x1 = 0;
700 }
701 return 1;
702 }
703
704 if (*x1 > maxdim) {
705 m = (*y1 - *y0)/(double)(*x1 - *x0);
706 *y1 += (int)(m * (maxdim - *x1));
707 *x1 = maxdim;
708 return 1;
709 }
710 if (*x1 < 0) {
711 m = (*y1 - *y0)/(double)(*x1 - *x0);
712 *y1 -= (int)(m * *x1);
713 *x1 = 0;
714 return 1;
715 }
716
717 return 1;
718 }
719
720 void gdImageSetPixel (gdImagePtr im, int x, int y, int color)
721 {
722 int p;
723 switch (color) {
724 case gdStyled:
725 if (!im->style) {
726
727 return;
728 } else {
729 p = im->style[im->stylePos++];
730 }
731 if (p != gdTransparent) {
732 gdImageSetPixel(im, x, y, p);
733 }
734 im->stylePos = im->stylePos % im->styleLength;
735 break;
736 case gdStyledBrushed:
737 if (!im->style) {
738
739 return;
740 }
741 p = im->style[im->stylePos++];
742 if (p != gdTransparent && p != 0) {
743 gdImageSetPixel(im, x, y, gdBrushed);
744 }
745 im->stylePos = im->stylePos % im->styleLength;
746 break;
747 case gdBrushed:
748 gdImageBrushApply(im, x, y);
749 break;
750 case gdTiled:
751 gdImageTileApply(im, x, y);
752 break;
753 case gdAntiAliased:
754 gdImageAntiAliasedApply(im, x, y);
755 break;
756 default:
757 if (gdImageBoundsSafe(im, x, y)) {
758 if (im->trueColor) {
759 switch (im->alphaBlendingFlag) {
760 default:
761 case gdEffectReplace:
762 im->tpixels[y][x] = color;
763 break;
764 case gdEffectAlphaBlend:
765 im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color);
766 break;
767 case gdEffectNormal:
768 im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color);
769 break;
770 case gdEffectOverlay :
771 im->tpixels[y][x] = gdLayerOverlay(im->tpixels[y][x], color);
772 break;
773 }
774 } else {
775 im->pixels[y][x] = color;
776 }
777 }
778 break;
779 }
780 }
781
782 int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
783 {
784 int p = gdImageGetPixel(im, x, y);
785
786 if (!im->trueColor) {
787 return gdTrueColorAlpha(im->red[p], im->green[p], im->blue[p], (im->transparent == p) ? gdAlphaTransparent : im->alpha[p]);
788 } else {
789 return p;
790 }
791 }
792
793 static void gdImageBrushApply (gdImagePtr im, int x, int y)
794 {
795 int lx, ly;
796 int hy, hx;
797 int x1, y1, x2, y2;
798 int srcx, srcy;
799
800 if (!im->brush) {
801 return;
802 }
803
804 hy = gdImageSY(im->brush) / 2;
805 y1 = y - hy;
806 y2 = y1 + gdImageSY(im->brush);
807 hx = gdImageSX(im->brush) / 2;
808 x1 = x - hx;
809 x2 = x1 + gdImageSX(im->brush);
810 srcy = 0;
811
812 if (im->trueColor) {
813 if (im->brush->trueColor) {
814 for (ly = y1; ly < y2; ly++) {
815 srcx = 0;
816 for (lx = x1; (lx < x2); lx++) {
817 int p;
818 p = gdImageGetTrueColorPixel(im->brush, srcx, srcy);
819
820 if (p != gdImageGetTransparent(im->brush)) {
821 gdImageSetPixel(im, lx, ly, p);
822 }
823 srcx++;
824 }
825 srcy++;
826 }
827 } else {
828
829 for (ly = y1; ly < y2; ly++) {
830 srcx = 0;
831 for (lx = x1; lx < x2; lx++) {
832 int p, tc;
833 p = gdImageGetPixel(im->brush, srcx, srcy);
834 tc = gdImageGetTrueColorPixel(im->brush, srcx, srcy);
835
836 if (p != gdImageGetTransparent(im->brush)) {
837 gdImageSetPixel(im, lx, ly, tc);
838 }
839 srcx++;
840 }
841 srcy++;
842 }
843 }
844 } else {
845 for (ly = y1; ly < y2; ly++) {
846 srcx = 0;
847 for (lx = x1; lx < x2; lx++) {
848 int p;
849 p = gdImageGetPixel(im->brush, srcx, srcy);
850
851 if (p != gdImageGetTransparent(im->brush)) {
852
853 if (im->brush->trueColor) {
854 gdImageSetPixel(im, lx, ly, gdImageColorResolveAlpha(im, gdTrueColorGetRed(p),
855 gdTrueColorGetGreen(p),
856 gdTrueColorGetBlue(p),
857 gdTrueColorGetAlpha(p)));
858 } else {
859 gdImageSetPixel(im, lx, ly, im->brushColorMap[p]);
860 }
861 }
862 srcx++;
863 }
864 srcy++;
865 }
866 }
867 }
868
869 static void gdImageTileApply (gdImagePtr im, int x, int y)
870 {
871 gdImagePtr tile = im->tile;
872 int srcx, srcy;
873 int p;
874 if (!tile) {
875 return;
876 }
877 srcx = x % gdImageSX(tile);
878 srcy = y % gdImageSY(tile);
879 if (im->trueColor) {
880 p = gdImageGetPixel(tile, srcx, srcy);
881 if (p != gdImageGetTransparent (tile)) {
882 if (!tile->trueColor) {
883 p = gdTrueColorAlpha(tile->red[p], tile->green[p], tile->blue[p], tile->alpha[p]);
884 }
885 gdImageSetPixel(im, x, y, p);
886 }
887 } else {
888 p = gdImageGetPixel(tile, srcx, srcy);
889
890 if (p != gdImageGetTransparent(tile)) {
891 if (tile->trueColor) {
892
893 gdImageSetPixel(im, x, y, gdImageColorResolveAlpha(im,
894 gdTrueColorGetRed(p),
895 gdTrueColorGetGreen(p),
896 gdTrueColorGetBlue(p),
897 gdTrueColorGetAlpha(p)));
898 } else {
899 gdImageSetPixel(im, x, y, im->tileColorMap[p]);
900 }
901 }
902 }
903 }
904
905
906 static int gdImageTileGet (gdImagePtr im, int x, int y)
907 {
908 int srcx, srcy;
909 int tileColor,p;
910 if (!im->tile) {
911 return -1;
912 }
913 srcx = x % gdImageSX(im->tile);
914 srcy = y % gdImageSY(im->tile);
915 p = gdImageGetPixel(im->tile, srcx, srcy);
916
917 if (im->trueColor) {
918 if (im->tile->trueColor) {
919 tileColor = p;
920 } else {
921 tileColor = gdTrueColorAlpha( gdImageRed(im->tile,p), gdImageGreen(im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p));
922 }
923 } else {
924 if (im->tile->trueColor) {
925 tileColor = gdImageColorResolveAlpha(im, gdTrueColorGetRed (p), gdTrueColorGetGreen (p), gdTrueColorGetBlue (p), gdTrueColorGetAlpha (p));
926 } else {
927 tileColor = p;
928 tileColor = gdImageColorResolveAlpha(im, gdImageRed (im->tile,p), gdImageGreen (im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p));
929 }
930 }
931 return tileColor;
932 }
933
934
935 static void gdImageAntiAliasedApply (gdImagePtr im, int px, int py)
936 {
937 float p_dist, p_alpha;
938 unsigned char opacity;
939
940
941
942
943
944
945
946 int LAC_2, LBC_2;
947
948 int Ax_Cx = im->AAL_x1 - px;
949 int Ay_Cy = im->AAL_y1 - py;
950
951 int Bx_Cx = im->AAL_x2 - px;
952 int By_Cy = im->AAL_y2 - py;
953
954
955
956
957
958
959 if (!gdImageBoundsSafe(im, px, py)) {
960 return;
961 }
962
963
964 LAC_2 = (Ax_Cx * Ax_Cx) + (Ay_Cy * Ay_Cy);
965 LBC_2 = (Bx_Cx * Bx_Cx) + (By_Cy * By_Cy);
966
967 if (((im->AAL_LAB_2 + LAC_2) >= LBC_2) && ((im->AAL_LAB_2 + LBC_2) >= LAC_2)) {
968
969
970
971 p_dist = fabs ((float) ((Ay_Cy * im->AAL_Bx_Ax) - (Ax_Cx * im->AAL_By_Ay)) / im->AAL_LAB);
972 } else {
973
974
975
976
977 p_dist = -1;
978 }
979
980 if ((p_dist >= 0) && (p_dist <= (float) (im->thick))) {
981 p_alpha = pow (1.0 - (p_dist / 1.5), 2);
982
983 if (p_alpha > 0) {
984 if (p_alpha >= 1) {
985 opacity = 255;
986 } else {
987 opacity = (unsigned char) (p_alpha * 255.0);
988 }
989 if (!im->AA_polygon || (im->AA_opacity[py][px] < opacity)) {
990 im->AA_opacity[py][px] = opacity;
991 }
992 }
993 }
994 }
995
996
997 int gdImageGetPixel (gdImagePtr im, int x, int y)
998 {
999 if (gdImageBoundsSafe(im, x, y)) {
1000 if (im->trueColor) {
1001 return im->tpixels[y][x];
1002 } else {
1003 return im->pixels[y][x];
1004 }
1005 } else {
1006 return 0;
1007 }
1008 }
1009
1010 void gdImageAABlend (gdImagePtr im)
1011 {
1012 float p_alpha, old_alpha;
1013 int color = im->AA_color, color_red, color_green, color_blue;
1014 int old_color, old_red, old_green, old_blue;
1015 int p_color, p_red, p_green, p_blue;
1016 int px, py;
1017
1018 color_red = gdImageRed(im, color);
1019 color_green = gdImageGreen(im, color);
1020 color_blue = gdImageBlue(im, color);
1021
1022
1023 for (py = 0; py < im->sy; py++) {
1024 for (px = 0; px < im->sx; px++) {
1025 if (im->AA_opacity[py][px] != 0) {
1026 old_color = gdImageGetPixel(im, px, py);
1027
1028 if ((old_color != color) && ((old_color != im->AA_dont_blend) || (im->AA_opacity[py][px] == 255))) {
1029
1030 p_alpha = (float) (im->AA_opacity[py][px]) / 255.0;
1031 old_alpha = 1.0 - p_alpha;
1032
1033 if (p_alpha >= 1.0) {
1034 p_color = color;
1035 } else {
1036 old_red = gdImageRed(im, old_color);
1037 old_green = gdImageGreen(im, old_color);
1038 old_blue = gdImageBlue(im, old_color);
1039
1040 p_red = (int) (((float) color_red * p_alpha) + ((float) old_red * old_alpha));
1041 p_green = (int) (((float) color_green * p_alpha) + ((float) old_green * old_alpha));
1042 p_blue = (int) (((float) color_blue * p_alpha) + ((float) old_blue * old_alpha));
1043 p_color = gdImageColorResolve(im, p_red, p_green, p_blue);
1044 }
1045 gdImageSetPixel(im, px, py, p_color);
1046 }
1047 }
1048 }
1049
1050 memset(im->AA_opacity[py], 0, im->sx);
1051 }
1052 }
1053
1054 static void gdImageHLine(gdImagePtr im, int y, int x1, int x2, int col)
1055 {
1056 if (im->thick > 1) {
1057 int thickhalf = im->thick >> 1;
1058 gdImageFilledRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col);
1059 } else {
1060 if (x2 < x1) {
1061 int t = x2;
1062 x2 = x1;
1063 x1 = t;
1064 }
1065
1066 for (;x1 <= x2; x1++) {
1067 gdImageSetPixel(im, x1, y, col);
1068 }
1069 }
1070 return;
1071 }
1072
1073 static void gdImageVLine(gdImagePtr im, int x, int y1, int y2, int col)
1074 {
1075 if (im->thick > 1) {
1076 int thickhalf = im->thick >> 1;
1077 gdImageFilledRectangle(im, x - thickhalf, y1, x + im->thick - thickhalf - 1, y2, col);
1078 } else {
1079 if (y2 < y1) {
1080 int t = y1;
1081 y1 = y2;
1082 y2 = t;
1083 }
1084
1085 for (;y1 <= y2; y1++) {
1086 gdImageSetPixel(im, x, y1, col);
1087 }
1088 }
1089 return;
1090 }
1091
1092
1093 void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
1094 {
1095 int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
1096 int wid;
1097 int w, wstart;
1098 int thick = im->thick;
1099
1100 if (color == gdAntiAliased) {
1101
1102
1103
1104
1105
1106 gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
1107 return;
1108 }
1109
1110
1111 if (!clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) || !clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im))) {
1112 return;
1113 }
1114
1115 dx = abs (x2 - x1);
1116 dy = abs (y2 - y1);
1117
1118 if (dx == 0) {
1119 gdImageVLine(im, x1, y1, y2, color);
1120 return;
1121 } else if (dy == 0) {
1122 gdImageHLine(im, y1, x1, x2, color);
1123 return;
1124 }
1125
1126 if (dy <= dx) {
1127
1128
1129 if ((dx == 0) && (dy == 0)) {
1130 wid = 1;
1131 } else {
1132
1133
1134 double ac = cos (atan2 (dy, dx));
1135 if (ac != 0) {
1136 wid = thick / ac;
1137 } else {
1138 wid = 1;
1139 }
1140 if (wid == 0) {
1141 wid = 1;
1142 }
1143 }
1144 d = 2 * dy - dx;
1145 incr1 = 2 * dy;
1146 incr2 = 2 * (dy - dx);
1147 if (x1 > x2) {
1148 x = x2;
1149 y = y2;
1150 ydirflag = (-1);
1151 xend = x1;
1152 } else {
1153 x = x1;
1154 y = y1;
1155 ydirflag = 1;
1156 xend = x2;
1157 }
1158
1159
1160 wstart = y - wid / 2;
1161 for (w = wstart; w < wstart + wid; w++) {
1162 gdImageSetPixel(im, x, w, color);
1163 }
1164
1165 if (((y2 - y1) * ydirflag) > 0) {
1166 while (x < xend) {
1167 x++;
1168 if (d < 0) {
1169 d += incr1;
1170 } else {
1171 y++;
1172 d += incr2;
1173 }
1174 wstart = y - wid / 2;
1175 for (w = wstart; w < wstart + wid; w++) {
1176 gdImageSetPixel (im, x, w, color);
1177 }
1178 }
1179 } else {
1180 while (x < xend) {
1181 x++;
1182 if (d < 0) {
1183 d += incr1;
1184 } else {
1185 y--;
1186 d += incr2;
1187 }
1188 wstart = y - wid / 2;
1189 for (w = wstart; w < wstart + wid; w++) {
1190 gdImageSetPixel (im, x, w, color);
1191 }
1192 }
1193 }
1194 } else {
1195
1196
1197
1198 double as = sin (atan2 (dy, dx));
1199 if (as != 0) {
1200 wid = thick / as;
1201 } else {
1202 wid = 1;
1203 }
1204 if (wid == 0) {
1205 wid = 1;
1206 }
1207
1208 d = 2 * dx - dy;
1209 incr1 = 2 * dx;
1210 incr2 = 2 * (dx - dy);
1211 if (y1 > y2) {
1212 y = y2;
1213 x = x2;
1214 yend = y1;
1215 xdirflag = (-1);
1216 } else {
1217 y = y1;
1218 x = x1;
1219 yend = y2;
1220 xdirflag = 1;
1221 }
1222
1223
1224 wstart = x - wid / 2;
1225 for (w = wstart; w < wstart + wid; w++) {
1226 gdImageSetPixel (im, w, y, color);
1227 }
1228
1229 if (((x2 - x1) * xdirflag) > 0) {
1230 while (y < yend) {
1231 y++;
1232 if (d < 0) {
1233 d += incr1;
1234 } else {
1235 x++;
1236 d += incr2;
1237 }
1238 wstart = x - wid / 2;
1239 for (w = wstart; w < wstart + wid; w++) {
1240 gdImageSetPixel (im, w, y, color);
1241 }
1242 }
1243 } else {
1244 while (y < yend) {
1245 y++;
1246 if (d < 0) {
1247 d += incr1;
1248 } else {
1249 x--;
1250 d += incr2;
1251 }
1252 wstart = x - wid / 2;
1253 for (w = wstart; w < wstart + wid; w++) {
1254 gdImageSetPixel (im, w, y, color);
1255 }
1256 }
1257 }
1258 }
1259 }
1260
1261
1262
1263
1264
1265 #define BLEND_COLOR(a, nc, c, cc) \
1266 nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8);
1267
1268 inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t)
1269 {
1270 int dr,dg,db,p,r,g,b;
1271 dr = gdTrueColorGetRed(color);
1272 dg = gdTrueColorGetGreen(color);
1273 db = gdTrueColorGetBlue(color);
1274
1275 p = gdImageGetPixel(im,x,y);
1276 r = gdTrueColorGetRed(p);
1277 g = gdTrueColorGetGreen(p);
1278 b = gdTrueColorGetBlue(p);
1279
1280 BLEND_COLOR(t, dr, r, dr);
1281 BLEND_COLOR(t, dg, g, dg);
1282 BLEND_COLOR(t, db, b, db);
1283 im->tpixels[y][x]=gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque);
1284 }
1285
1286
1287
1288
1289 void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col)
1290 {
1291
1292 long x, y, inc;
1293 long dx, dy,tmp;
1294
1295 if (y1 < 0 && y2 < 0) {
1296 return;
1297 }
1298 if (y1 < 0) {
1299 x1 += (y1 * (x1 - x2)) / (y2 - y1);
1300 y1 = 0;
1301 }
1302 if (y2 < 0) {
1303 x2 += (y2 * (x1 - x2)) / (y2 - y1);
1304 y2 = 0;
1305 }
1306
1307
1308 if (y1 >= im->sy && y2 >= im->sy) {
1309 return;
1310 }
1311 if (y1 >= im->sy) {
1312 x1 -= ((im->sy - y1) * (x1 - x2)) / (y2 - y1);
1313 y1 = im->sy - 1;
1314 }
1315 if (y2 >= im->sy) {
1316 x2 -= ((im->sy - y2) * (x1 - x2)) / (y2 - y1);
1317 y2 = im->sy - 1;
1318 }
1319
1320
1321 if (x1 < 0 && x2 < 0) {
1322 return;
1323 }
1324 if (x1 < 0) {
1325 y1 += (x1 * (y1 - y2)) / (x2 - x1);
1326 x1 = 0;
1327 }
1328 if (x2 < 0) {
1329 y2 += (x2 * (y1 - y2)) / (x2 - x1);
1330 x2 = 0;
1331 }
1332
1333 if (x1 >= im->sx && x2 >= im->sx) {
1334 return;
1335 }
1336 if (x1 >= im->sx) {
1337 y1 -= ((im->sx - x1) * (y1 - y2)) / (x2 - x1);
1338 x1 = im->sx - 1;
1339 }
1340 if (x2 >= im->sx) {
1341 y2 -= ((im->sx - x2) * (y1 - y2)) / (x2 - x1);
1342 x2 = im->sx - 1;
1343 }
1344
1345 dx = x2 - x1;
1346 dy = y2 - y1;
1347
1348 if (dx == 0 && dy == 0) {
1349 return;
1350 }
1351 if (abs(dx) > abs(dy)) {
1352 if (dx < 0) {
1353 tmp = x1;
1354 x1 = x2;
1355 x2 = tmp;
1356 tmp = y1;
1357 y1 = y2;
1358 y2 = tmp;
1359 dx = x2 - x1;
1360 dy = y2 - y1;
1361 }
1362 x = x1 << 16;
1363 y = y1 << 16;
1364 inc = (dy * 65536) / dx;
1365 while ((x >> 16) <= x2) {
1366 gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (y >> 8) & 0xFF);
1367 if ((y >> 16) + 1 < im->sy) {
1368 gdImageSetAAPixelColor(im, x >> 16, (y >> 16) + 1,col, (~y >> 8) & 0xFF);
1369 }
1370 x += (1 << 16);
1371 y += inc;
1372 }
1373 } else {
1374 if (dy < 0) {
1375 tmp = x1;
1376 x1 = x2;
1377 x2 = tmp;
1378 tmp = y1;
1379 y1 = y2;
1380 y2 = tmp;
1381 dx = x2 - x1;
1382 dy = y2 - y1;
1383 }
1384 x = x1 << 16;
1385 y = y1 << 16;
1386 inc = (dx * 65536) / dy;
1387 while ((y>>16) <= y2) {
1388 gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (x >> 8) & 0xFF);
1389 if ((x >> 16) + 1 < im->sx) {
1390 gdImageSetAAPixelColor(im, (x >> 16) + 1, (y >> 16),col, (~x >> 8) & 0xFF);
1391 }
1392 x += inc;
1393 y += (1<<16);
1394 }
1395 }
1396 }
1397
1398 static void dashedSet (gdImagePtr im, int x, int y, int color, int *onP, int *dashStepP, int wid, int vert);
1399
1400 void gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
1401 {
1402 int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
1403 int dashStep = 0;
1404 int on = 1;
1405 int wid;
1406 int vert;
1407 int thick = im->thick;
1408
1409 dx = abs(x2 - x1);
1410 dy = abs(y2 - y1);
1411 if (dy <= dx) {
1412
1413
1414
1415 double as = sin(atan2(dy, dx));
1416 if (as != 0) {
1417 wid = thick / as;
1418 } else {
1419 wid = 1;
1420 }
1421 wid = (int)(thick * sin(atan2(dy, dx)));
1422 vert = 1;
1423
1424 d = 2 * dy - dx;
1425 incr1 = 2 * dy;
1426 incr2 = 2 * (dy - dx);
1427 if (x1 > x2) {
1428 x = x2;
1429 y = y2;
1430 ydirflag = (-1);
1431 xend = x1;
1432 } else {
1433 x = x1;
1434 y = y1;
1435 ydirflag = 1;
1436 xend = x2;
1437 }
1438 dashedSet(im, x, y, color, &on, &dashStep, wid, vert);
1439 if (((y2 - y1) * ydirflag) > 0) {
1440 while (x < xend) {
1441 x++;
1442 if (d < 0) {
1443 d += incr1;
1444 } else {
1445 y++;
1446 d += incr2;
1447 }
1448 dashedSet(im, x, y, color, &on, &dashStep, wid, vert);
1449 }
1450 } else {
1451 while (x < xend) {
1452 x++;
1453 if (d < 0) {
1454 d += incr1;
1455 } else {
1456 y--;
1457 d += incr2;
1458 }
1459 dashedSet(im, x, y, color, &on, &dashStep, wid, vert);
1460 }
1461 }
1462 } else {
1463
1464
1465 double as = sin (atan2 (dy, dx));
1466 if (as != 0) {
1467 wid = thick / as;
1468 } else {
1469 wid = 1;
1470 }
1471 vert = 0;
1472
1473 d = 2 * dx - dy;
1474 incr1 = 2 * dx;
1475 incr2 = 2 * (dx - dy);
1476 if (y1 > y2) {
1477 y = y2;
1478 x = x2;
1479 yend = y1;
1480 xdirflag = (-1);
1481 } else {
1482 y = y1;
1483 x = x1;
1484 yend = y2;
1485 xdirflag = 1;
1486 }
1487 dashedSet(im, x, y, color, &on, &dashStep, wid, vert);
1488 if (((x2 - x1) * xdirflag) > 0) {
1489 while (y < yend) {
1490 y++;
1491 if (d < 0) {
1492 d += incr1;
1493 } else {
1494 x++;
1495 d += incr2;
1496 }
1497 dashedSet(im, x, y, color, &on, &dashStep, wid, vert);
1498 }
1499 } else {
1500 while (y < yend) {
1501 y++;
1502 if (d < 0) {
1503 d += incr1;
1504 } else {
1505 x--;
1506 d += incr2;
1507 }
1508 dashedSet(im, x, y, color, &on, &dashStep, wid, vert);
1509 }
1510 }
1511 }
1512 }
1513
1514 static void dashedSet (gdImagePtr im, int x, int y, int color, int *onP, int *dashStepP, int wid, int vert)
1515 {
1516 int dashStep = *dashStepP;
1517 int on = *onP;
1518 int w, wstart;
1519
1520 dashStep++;
1521 if (dashStep == gdDashSize) {
1522 dashStep = 0;
1523 on = !on;
1524 }
1525 if (on) {
1526 if (vert) {
1527 wstart = y - wid / 2;
1528 for (w = wstart; w < wstart + wid; w++) {
1529 gdImageSetPixel(im, x, w, color);
1530 }
1531 } else {
1532 wstart = x - wid / 2;
1533 for (w = wstart; w < wstart + wid; w++) {
1534 gdImageSetPixel(im, w, y, color);
1535 }
1536 }
1537 }
1538 *dashStepP = dashStep;
1539 *onP = on;
1540 }
1541
1542 void gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
1543 {
1544 int cx, cy;
1545 int px, py;
1546 int fline;
1547 cx = 0;
1548 cy = 0;
1549 #ifdef CHARSET_EBCDIC
1550 c = ASC (c);
1551 #endif
1552 if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
1553 return;
1554 }
1555 fline = (c - f->offset) * f->h * f->w;
1556 for (py = y; (py < (y + f->h)); py++) {
1557 for (px = x; (px < (x + f->w)); px++) {
1558 if (f->data[fline + cy * f->w + cx]) {
1559 gdImageSetPixel(im, px, py, color);
1560 }
1561 cx++;
1562 }
1563 cx = 0;
1564 cy++;
1565 }
1566 }
1567
1568 void gdImageCharUp (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
1569 {
1570 int cx, cy;
1571 int px, py;
1572 int fline;
1573 cx = 0;
1574 cy = 0;
1575 #ifdef CHARSET_EBCDIC
1576 c = ASC (c);
1577 #endif
1578 if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
1579 return;
1580 }
1581 fline = (c - f->offset) * f->h * f->w;
1582 for (py = y; py > (y - f->w); py--) {
1583 for (px = x; px < (x + f->h); px++) {
1584 if (f->data[fline + cy * f->w + cx]) {
1585 gdImageSetPixel(im, px, py, color);
1586 }
1587 cy++;
1588 }
1589 cy = 0;
1590 cx++;
1591 }
1592 }
1593
1594 void gdImageString (gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color)
1595 {
1596 int i;
1597 int l;
1598 l = strlen ((char *) s);
1599 for (i = 0; (i < l); i++) {
1600 gdImageChar(im, f, x, y, s[i], color);
1601 x += f->w;
1602 }
1603 }
1604
1605 void gdImageStringUp (gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color)
1606 {
1607 int i;
1608 int l;
1609 l = strlen ((char *) s);
1610 for (i = 0; (i < l); i++) {
1611 gdImageCharUp(im, f, x, y, s[i], color);
1612 y -= f->w;
1613 }
1614 }
1615
1616 static int strlen16 (unsigned short *s);
1617
1618 void gdImageString16 (gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color)
1619 {
1620 int i;
1621 int l;
1622 l = strlen16(s);
1623 for (i = 0; (i < l); i++) {
1624 gdImageChar(im, f, x, y, s[i], color);
1625 x += f->w;
1626 }
1627 }
1628
1629 void gdImageStringUp16 (gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color)
1630 {
1631 int i;
1632 int l;
1633 l = strlen16(s);
1634 for (i = 0; i < l; i++) {
1635 gdImageCharUp(im, f, x, y, s[i], color);
1636 y -= f->w;
1637 }
1638 }
1639
1640 static int strlen16 (unsigned short *s)
1641 {
1642 int len = 0;
1643 while (*s) {
1644 s++;
1645 len++;
1646 }
1647 return len;
1648 }
1649
1650 #ifndef HAVE_LSQRT
1651
1652
1653
1654 long lsqrt (long n)
1655 {
1656 long result = (long) sqrt ((double) n);
1657 return result;
1658 }
1659 #endif
1660
1661
1662
1663
1664
1665
1666
1667
1668 void gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
1669 {
1670 if ((s % 360) == (e % 360)) {
1671 gdImageEllipse(im, cx, cy, w, h, color);
1672 } else {
1673 gdImageFilledArc(im, cx, cy, w, h, s, e, color, gdNoFill);
1674 }
1675 }
1676
1677 void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color, int style)
1678 {
1679 gdPoint pts[3];
1680 int i;
1681 int lx = 0, ly = 0;
1682 int fx = 0, fy = 0;
1683
1684
1685 if ((s % 360) == (e % 360)) {
1686 s = 0; e = 360;
1687 } else {
1688 if (s > 360) {
1689 s = s % 360;
1690 }
1691
1692 if (e > 360) {
1693 e = e % 360;
1694 }
1695
1696 while (s < 0) {
1697 s += 360;
1698 }
1699
1700 while (e < s) {
1701 e += 360;
1702 }
1703 if (s == e) {
1704 s = 0; e = 360;
1705 }
1706 }
1707
1708 for (i = s; i <= e; i++) {
1709 int x, y;
1710 x = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
1711 y = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
1712 if (i != s) {
1713 if (!(style & gdChord)) {
1714 if (style & gdNoFill) {
1715 gdImageLine(im, lx, ly, x, y, color);
1716 } else {
1717
1718 pts[0].x = lx;
1719 pts[0].y = ly;
1720 pts[1].x = x;
1721 pts[1].y = y;
1722 pts[2].x = cx;
1723 pts[2].y = cy;
1724 gdImageFilledPolygon(im, pts, 3, color);
1725 }
1726 }
1727 } else {
1728 fx = x;
1729 fy = y;
1730 }
1731 lx = x;
1732 ly = y;
1733 }
1734 if (style & gdChord) {
1735 if (style & gdNoFill) {
1736 if (style & gdEdged) {
1737 gdImageLine(im, cx, cy, lx, ly, color);
1738 gdImageLine(im, cx, cy, fx, fy, color);
1739 }
1740 gdImageLine(im, fx, fy, lx, ly, color);
1741 } else {
1742 pts[0].x = fx;
1743 pts[0].y = fy;
1744 pts[1].x = lx;
1745 pts[1].y = ly;
1746 pts[2].x = cx;
1747 pts[2].y = cy;
1748 gdImageFilledPolygon(im, pts, 3, color);
1749 }
1750 } else {
1751 if (style & gdNoFill) {
1752 if (style & gdEdged) {
1753 gdImageLine(im, cx, cy, lx, ly, color);
1754 gdImageLine(im, cx, cy, fx, fy, color);
1755 }
1756 }
1757 }
1758 }
1759
1760 void gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
1761 {
1762 int lastBorder;
1763
1764 int leftLimit = -1, rightLimit;
1765 int i, restoreAlphaBlending = 0;
1766
1767 if (border < 0) {
1768
1769 return;
1770 }
1771
1772 restoreAlphaBlending = im->alphaBlendingFlag;
1773 im->alphaBlendingFlag = 0;
1774
1775 if (x >= im->sx) {
1776 x = im->sx - 1;
1777 } else if (x < 0) {
1778 x = 0;
1779 }
1780 if (y >= im->sy) {
1781 y = im->sy - 1;
1782 } else if (y < 0) {
1783 y = 0;
1784 }
1785
1786 for (i = x; i >= 0; i--) {
1787 if (gdImageGetPixel(im, i, y) == border) {
1788 break;
1789 }
1790 gdImageSetPixel(im, i, y, color);
1791 leftLimit = i;
1792 }
1793 if (leftLimit == -1) {
1794 im->alphaBlendingFlag = restoreAlphaBlending;
1795 return;
1796 }
1797
1798 rightLimit = x;
1799 for (i = (x + 1); i < im->sx; i++) {
1800 if (gdImageGetPixel(im, i, y) == border) {
1801 break;
1802 }
1803 gdImageSetPixel(im, i, y, color);
1804 rightLimit = i;
1805 }
1806
1807
1808 if (y > 0) {
1809 lastBorder = 1;
1810 for (i = leftLimit; i <= rightLimit; i++) {
1811 int c = gdImageGetPixel(im, i, y - 1);
1812 if (lastBorder) {
1813 if ((c != border) && (c != color)) {
1814 gdImageFillToBorder(im, i, y - 1, border, color);
1815 lastBorder = 0;
1816 }
1817 } else if ((c == border) || (c == color)) {
1818 lastBorder = 1;
1819 }
1820 }
1821 }
1822
1823
1824 if (y < ((im->sy) - 1)) {
1825 lastBorder = 1;
1826 for (i = leftLimit; i <= rightLimit; i++) {
1827 int c = gdImageGetPixel(im, i, y + 1);
1828
1829 if (lastBorder) {
1830 if ((c != border) && (c != color)) {
1831 gdImageFillToBorder(im, i, y + 1, border, color);
1832 lastBorder = 0;
1833 }
1834 } else if ((c == border) || (c == color)) {
1835 lastBorder = 1;
1836 }
1837 }
1838 }
1839 im->alphaBlendingFlag = restoreAlphaBlending;
1840 }
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853 struct seg {int y, xl, xr, dy;};
1854
1855
1856 #define FILL_MAX ((int)(im->sy*im->sx)/4)
1857 #define FILL_PUSH(Y, XL, XR, DY) \
1858 if (sp<stack+FILL_MAX && Y+(DY)>=0 && Y+(DY)<wy2) \
1859 {sp->y = Y; sp->xl = XL; sp->xr = XR; sp->dy = DY; sp++;}
1860
1861 #define FILL_POP(Y, XL, XR, DY) \
1862 {sp--; Y = sp->y+(DY = sp->dy); XL = sp->xl; XR = sp->xr;}
1863
1864 static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc);
1865
1866 void gdImageFill(gdImagePtr im, int x, int y, int nc)
1867 {
1868 int l, x1, x2, dy;
1869 int oc;
1870 int wx2,wy2;
1871
1872 int alphablending_bak;
1873
1874
1875
1876 struct seg *stack = NULL;
1877 struct seg *sp;
1878
1879 if (!im->trueColor && nc > (im->colorsTotal -1)) {
1880 return;
1881 }
1882
1883 alphablending_bak = im->alphaBlendingFlag;
1884 im->alphaBlendingFlag = 0;
1885
1886 if (nc==gdTiled){
1887 _gdImageFillTiled(im,x,y,nc);
1888 im->alphaBlendingFlag = alphablending_bak;
1889 return;
1890 }
1891
1892 wx2=im->sx;wy2=im->sy;
1893 oc = gdImageGetPixel(im, x, y);
1894 if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) {
1895 im->alphaBlendingFlag = alphablending_bak;
1896 return;
1897 }
1898
1899
1900
1901
1902 if (im->sx < 4) {
1903 int ix = x, iy = y, c;
1904 do {
1905 do {
1906 c = gdImageGetPixel(im, ix, iy);
1907 if (c != oc) {
1908 goto done;
1909 }
1910 gdImageSetPixel(im, ix, iy, nc);
1911 } while(ix++ < (im->sx -1));
1912 ix = x;
1913 } while(iy++ < (im->sy -1));
1914 goto done;
1915 }
1916
1917 stack = (struct seg *)safe_emalloc(sizeof(struct seg), ((int)(im->sy*im->sx)/4), 1);
1918 sp = stack;
1919
1920
1921 FILL_PUSH(y,x,x,1);
1922
1923 FILL_PUSH(y+1, x, x, -1);
1924 while (sp>stack) {
1925 FILL_POP(y, x1, x2, dy);
1926
1927 for (x=x1; x>=0 && gdImageGetPixel(im,x, y)==oc; x--) {
1928 gdImageSetPixel(im,x, y, nc);
1929 }
1930 if (x>=x1) {
1931 goto skip;
1932 }
1933 l = x+1;
1934
1935
1936 if (l<x1) {
1937 FILL_PUSH(y, l, x1-1, -dy);
1938 }
1939 x = x1+1;
1940 do {
1941 for (; x<=wx2 && gdImageGetPixel(im,x, y)==oc; x++) {
1942 gdImageSetPixel(im, x, y, nc);
1943 }
1944 FILL_PUSH(y, l, x-1, dy);
1945
1946 if (x>x2+1) {
1947 FILL_PUSH(y, x2+1, x-1, -dy);
1948 }
1949 skip: for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++);
1950
1951 l = x;
1952 } while (x<=x2);
1953 }
1954
1955 efree(stack);
1956
1957 done:
1958 im->alphaBlendingFlag = alphablending_bak;
1959 }
1960
1961 static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc)
1962 {
1963 int i, l, x1, x2, dy;
1964 int oc;
1965 int wx2,wy2;
1966
1967 struct seg *stack;
1968 struct seg *sp;
1969 char **pts;
1970
1971 if (!im->tile) {
1972 return;
1973 }
1974
1975 wx2=im->sx;wy2=im->sy;
1976
1977 nc = gdImageTileGet(im,x,y);
1978
1979 pts = (char **) ecalloc(im->sy + 1, sizeof(char *));
1980 for (i = 0; i < im->sy + 1; i++) {
1981 pts[i] = (char *) ecalloc(im->sx + 1, sizeof(char));
1982 }
1983
1984 stack = (struct seg *)safe_emalloc(sizeof(struct seg), ((int)(im->sy*im->sx)/4), 1);
1985 sp = stack;
1986
1987 oc = gdImageGetPixel(im, x, y);
1988
1989
1990 FILL_PUSH(y,x,x,1);
1991
1992 FILL_PUSH(y+1, x, x, -1);
1993 while (sp>stack) {
1994 FILL_POP(y, x1, x2, dy);
1995 for (x=x1; x>=0 && (!pts[y][x] && gdImageGetPixel(im,x,y)==oc); x--) {
1996 nc = gdImageTileGet(im,x,y);
1997 pts[y][x] = 1;
1998 gdImageSetPixel(im,x, y, nc);
1999 }
2000 if (x>=x1) {
2001 goto skip;
2002 }
2003 l = x+1;
2004
2005
2006 if (l<x1) {
2007 FILL_PUSH(y, l, x1-1, -dy);
2008 }
2009 x = x1+1;
2010 do {
2011 for(; x<wx2 && (!pts[y][x] && gdImageGetPixel(im,x, y)==oc); x++) {
2012 nc = gdImageTileGet(im,x,y);
2013 pts[y][x] = 1;
2014 gdImageSetPixel(im, x, y, nc);
2015 }
2016 FILL_PUSH(y, l, x-1, dy);
2017
2018 if (x>x2+1) {
2019 FILL_PUSH(y, x2+1, x-1, -dy);
2020 }
2021 skip: for(x++; x<=x2 && (pts[y][x] || gdImageGetPixel(im,x, y)!=oc); x++);
2022 l = x;
2023 } while (x<=x2);
2024 }
2025
2026 for(i = 0; i < im->sy + 1; i++) {
2027 efree(pts[i]);
2028 }
2029
2030 efree(pts);
2031 efree(stack);
2032 }
2033
2034
2035
2036 void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
2037 {
2038 int x1h = x1, x1v = x1, y1h = y1, y1v = y1, x2h = x2, x2v = x2, y2h = y2, y2v = y2;
2039 int thick = im->thick;
2040 int t;
2041
2042 if (x1 == x2 && y1 == y2 && thick == 1) {
2043 gdImageSetPixel(im, x1, y1, color);
2044 return;
2045 }
2046
2047 if (y2 < y1) {
2048 t=y1;
2049 y1 = y2;
2050 y2 = t;
2051 }
2052
2053 if (x2 < x1) {
2054 t = x1;
2055 x1 = x2;
2056 x2 = t;
2057 }
2058
2059 x1h = x1; x1v = x1; y1h = y1; y1v = y1; x2h = x2; x2v = x2; y2h = y2; y2v = y2;
2060 if (thick > 1) {
2061 int cx, cy, x1ul, y1ul, x2lr, y2lr;
2062 int half = thick >> 1;
2063
2064 x1ul = x1 - half;
2065 y1ul = y1 - half;
2066
2067 x2lr = x2 + half;
2068 y2lr = y2 + half;
2069
2070 cy = y1ul + thick;
2071 while (cy-- > y1ul) {
2072 cx = x1ul - 1;
2073 while (cx++ < x2lr) {
2074 gdImageSetPixel(im, cx, cy, color);
2075 }
2076 }
2077
2078 cy = y2lr - thick;
2079 while (cy++ < y2lr) {
2080 cx = x1ul - 1;
2081 while (cx++ < x2lr) {
2082 gdImageSetPixel(im, cx, cy, color);
2083 }
2084 }
2085
2086 cy = y1ul + thick - 1;
2087 while (cy++ < y2lr -thick) {
2088 cx = x1ul - 1;
2089 while (cx++ < x1ul + thick) {
2090 gdImageSetPixel(im, cx, cy, color);
2091 }
2092 }
2093
2094 cy = y1ul + thick - 1;
2095 while (cy++ < y2lr -thick) {
2096 cx = x2lr - thick - 1;
2097 while (cx++ < x2lr) {
2098 gdImageSetPixel(im, cx, cy, color);
2099 }
2100 }
2101
2102 return;
2103 } else {
2104 if (x1 == x2 || y1 == y2) {
2105 gdImageLine(im, x1, y1, x2, y2, color);
2106 } else {
2107 y1v = y1h + 1;
2108 y2v = y2h - 1;
2109 gdImageLine(im, x1h, y1h, x2h, y1h, color);
2110 gdImageLine(im, x1h, y2h, x2h, y2h, color);
2111 gdImageLine(im, x1v, y1v, x1v, y2v, color);
2112 gdImageLine(im, x2v, y1v, x2v, y2v, color);
2113 }
2114 }
2115 }
2116
2117 void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
2118 {
2119 int x, y;
2120
2121
2122 if (x1 == x2 && y1 == y2) {
2123 gdImageSetPixel(im, x1, y1, color);
2124 return;
2125 }
2126
2127 if (x1 > x2) {
2128 x = x1;
2129 x1 = x2;
2130 x2 = x;
2131 }
2132
2133 if (y1 > y2) {
2134 y = y1;
2135 y1 = y2;
2136 y2 = y;
2137 }
2138
2139 if (x1 < 0) {
2140 x1 = 0;
2141 }
2142
2143 if (x2 >= gdImageSX(im)) {
2144 x2 = gdImageSX(im) - 1;
2145 }
2146
2147 if (y1 < 0) {
2148 y1 = 0;
2149 }
2150
2151 if (y2 >= gdImageSY(im)) {
2152 y2 = gdImageSY(im) - 1;
2153 }
2154
2155 for (y = y1; (y <= y2); y++) {
2156 for (x = x1; (x <= x2); x++) {
2157 gdImageSetPixel (im, x, y, color);
2158 }
2159 }
2160 }
2161
2162 void gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
2163 {
2164 int c;
2165 int x, y;
2166 int tox, toy;
2167 int i;
2168 int colorMap[gdMaxColors];
2169
2170 if (dst->trueColor) {
2171
2172
2173
2174
2175
2176 if (src->trueColor) {
2177 for (y = 0; (y < h); y++) {
2178 for (x = 0; (x < w); x++) {
2179 int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y);
2180 gdImageSetPixel (dst, dstX + x, dstY + y, c);
2181 }
2182 }
2183 } else {
2184
2185 for (y = 0; (y < h); y++) {
2186 for (x = 0; (x < w); x++) {
2187 int c = gdImageGetPixel (src, srcX + x, srcY + y);
2188 if (c != src->transparent) {
2189 gdImageSetPixel(dst, dstX + x, dstY + y, gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]));
2190 }
2191 }
2192 }
2193 }
2194 return;
2195 }
2196
2197
2198 if (src->trueColor) {
2199 toy = dstY;
2200 for (y = srcY; (y < (srcY + h)); y++) {
2201 tox = dstX;
2202 for (x = srcX; x < (srcX + w); x++) {
2203 int nc;
2204 c = gdImageGetPixel (src, x, y);
2205
2206
2207 nc = gdImageColorResolveAlpha(dst, gdTrueColorGetRed(c), gdTrueColorGetGreen(c), gdTrueColorGetBlue(c), gdTrueColorGetAlpha(c));
2208
2209 gdImageSetPixel(dst, tox, toy, nc);
2210 tox++;
2211 }
2212 toy++;
2213 }
2214 return;
2215 }
2216
2217
2218 for (i = 0; i < gdMaxColors; i++) {
2219 colorMap[i] = (-1);
2220 }
2221 toy = dstY;
2222 for (y = srcY; y < (srcY + h); y++) {
2223 tox = dstX;
2224 for (x = srcX; x < (srcX + w); x++) {
2225 int nc;
2226 int mapTo;
2227 c = gdImageGetPixel (src, x, y);
2228
2229 if (gdImageGetTransparent (src) == c) {
2230 tox++;
2231 continue;
2232 }
2233
2234 if (src->trueColor) {
2235
2236
2237
2238 mapTo = gdImageColorResolveAlpha (dst, gdTrueColorGetRed (c), gdTrueColorGetGreen (c), gdTrueColorGetBlue (c), gdTrueColorGetAlpha (c));
2239 } else if (colorMap[c] == (-1)) {
2240
2241 if (dst == src) {
2242 nc = c;
2243 } else {
2244
2245 nc = gdImageColorResolveAlpha (dst, src->red[c], src->green[c], src->blue[c], src->alpha[c]);
2246 }
2247 colorMap[c] = nc;
2248 mapTo = colorMap[c];
2249 } else {
2250 mapTo = colorMap[c];
2251 }
2252 gdImageSetPixel (dst, tox, toy, mapTo);
2253 tox++;
2254 }
2255 toy++;
2256 }
2257 }
2258
2259
2260
2261 void gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct)
2262 {
2263 int c, dc;
2264 int x, y;
2265 int tox, toy;
2266 int ncR, ncG, ncB;
2267 toy = dstY;
2268
2269 for (y = srcY; y < (srcY + h); y++) {
2270 tox = dstX;
2271 for (x = srcX; x < (srcX + w); x++) {
2272 int nc;
2273 c = gdImageGetPixel(src, x, y);
2274
2275 if (gdImageGetTransparent(src) == c) {
2276 tox++;
2277 continue;
2278 }
2279
2280 if (dst == src) {
2281 nc = c;
2282 } else {
2283 dc = gdImageGetPixel(dst, tox, toy);
2284
2285 ncR = (int)(gdImageRed (src, c) * (pct / 100.0) + gdImageRed (dst, dc) * ((100 - pct) / 100.0));
2286 ncG = (int)(gdImageGreen (src, c) * (pct / 100.0) + gdImageGreen (dst, dc) * ((100 - pct) / 100.0));
2287 ncB = (int)(gdImageBlue (src, c) * (pct / 100.0) + gdImageBlue (dst, dc) * ((100 - pct) / 100.0));
2288
2289
2290 nc = gdImageColorResolve (dst, ncR, ncG, ncB);
2291 }
2292 gdImageSetPixel (dst, tox, toy, nc);
2293 tox++;
2294 }
2295 toy++;
2296 }
2297 }
2298
2299
2300
2301 void gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct)
2302 {
2303 int c, dc;
2304 int x, y;
2305 int tox, toy;
2306 int ncR, ncG, ncB;
2307 float g;
2308 toy = dstY;
2309
2310 for (y = srcY; (y < (srcY + h)); y++) {
2311 tox = dstX;
2312 for (x = srcX; (x < (srcX + w)); x++) {
2313 int nc;
2314 c = gdImageGetPixel (src, x, y);
2315
2316 if (gdImageGetTransparent(src) == c) {
2317 tox++;
2318 continue;
2319 }
2320
2321
2322
2323
2324
2325
2326 if (dst == src && pct == 100) {
2327 nc = c;
2328 } else {
2329 dc = gdImageGetPixel(dst, tox, toy);
2330 g = (0.29900f * gdImageRed(dst, dc)) + (0.58700f * gdImageGreen(dst, dc)) + (0.11400f * gdImageBlue(dst, dc));
2331
2332 ncR = (int)(gdImageRed (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0));
2333 ncG = (int)(gdImageGreen (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0));
2334 ncB = (int)(gdImageBlue (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0));
2335
2336
2337
2338 nc = gdImageColorExact(dst, ncR, ncG, ncB);
2339 if (nc == (-1)) {
2340
2341 nc = gdImageColorAllocate(dst, ncR, ncG, ncB);
2342
2343 if (nc == (-1)) {
2344 nc = gdImageColorClosest(dst, ncR, ncG, ncB);
2345 }
2346 }
2347 }
2348 gdImageSetPixel(dst, tox, toy, nc);
2349 tox++;
2350 }
2351 toy++;
2352 }
2353 }
2354
2355 void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
2356 {
2357 int c;
2358 int x, y;
2359 int tox, toy;
2360 int ydest;
2361 int i;
2362 int colorMap[gdMaxColors];
2363
2364 int *stx, *sty;
2365
2366 if (overflow2(sizeof(int), srcW)) {
2367 return;
2368 }
2369 if (overflow2(sizeof(int), srcH)) {
2370 return;
2371 }
2372
2373 stx = (int *) gdMalloc (sizeof (int) * srcW);
2374 sty = (int *) gdMalloc (sizeof (int) * srcH);
2375
2376
2377 for (i = 0; (i < srcW); i++) {
2378 stx[i] = dstW * (i+1) / srcW - dstW * i / srcW ;
2379 }
2380 for (i = 0; (i < srcH); i++) {
2381 sty[i] = dstH * (i+1) / srcH - dstH * i / srcH ;
2382 }
2383 for (i = 0; (i < gdMaxColors); i++) {
2384 colorMap[i] = (-1);
2385 }
2386 toy = dstY;
2387 for (y = srcY; (y < (srcY + srcH)); y++) {
2388 for (ydest = 0; (ydest < sty[y - srcY]); ydest++) {
2389 tox = dstX;
2390 for (x = srcX; (x < (srcX + srcW)); x++) {
2391 int nc = 0;
2392 int mapTo;
2393 if (!stx[x - srcX]) {
2394 continue;
2395 }
2396 if (dst->trueColor) {
2397
2398 if (!src->trueColor) {
2399 int tmp = gdImageGetPixel (src, x, y);
2400 mapTo = gdImageGetTrueColorPixel (src, x, y);
2401 if (gdImageGetTransparent (src) == tmp) {
2402
2403 tox += stx[x - srcX];
2404 continue;
2405 }
2406 } else {
2407
2408 mapTo = gdImageGetTrueColorPixel (src, x, y);
2409
2410 if (gdImageGetTransparent (src) == mapTo) {
2411
2412 tox += stx[x - srcX];
2413 continue;
2414 }
2415 }
2416 } else {
2417 c = gdImageGetPixel (src, x, y);
2418
2419 if (gdImageGetTransparent (src) == c) {
2420 tox += stx[x - srcX];
2421 continue;
2422 }
2423 if (src->trueColor) {
2424
2425 mapTo = gdImageColorResolveAlpha(dst, gdTrueColorGetRed(c),
2426 gdTrueColorGetGreen(c),
2427 gdTrueColorGetBlue(c),
2428 gdTrueColorGetAlpha (c));
2429 } else {
2430
2431 if (colorMap[c] == (-1)) {
2432
2433 if (dst == src) {
2434 nc = c;
2435 } else {
2436
2437
2438 nc = gdImageColorResolveAlpha(dst, gdImageRed(src, c),
2439 gdImageGreen(src, c),
2440 gdImageBlue(src, c),
2441 gdImageAlpha(src, c));
2442 }
2443 colorMap[c] = nc;
2444 }
2445 mapTo = colorMap[c];
2446 }
2447 }
2448 for (i = 0; (i < stx[x - srcX]); i++) {
2449 gdImageSetPixel (dst, tox, toy, mapTo);
2450 tox++;
2451 }
2452 }
2453 toy++;
2454 }
2455 }
2456 gdFree (stx);
2457 gdFree (sty);
2458 }
2459
2460
2461
2462
2463
2464
2465 void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
2466 {
2467 int x, y;
2468 double sy1, sy2, sx1, sx2;
2469
2470 if (!dst->trueColor) {
2471 gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
2472 return;
2473 }
2474 for (y = dstY; (y < dstY + dstH); y++) {
2475 sy1 = ((double) y - (double) dstY) * (double) srcH / (double) dstH;
2476 sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH / (double) dstH;
2477 for (x = dstX; (x < dstX + dstW); x++) {
2478 double sx, sy;
2479 double spixels = 0;
2480 double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
2481 double alpha_factor, alpha_sum = 0.0, contrib_sum = 0.0;
2482 sx1 = ((double) x - (double) dstX) * (double) srcW / dstW;
2483 sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / dstW;
2484 sy = sy1;
2485 do {
2486 double yportion;
2487 if (floor_cast(sy) == floor_cast(sy1)) {
2488 yportion = 1.0f - (sy - floor_cast(sy));
2489 if (yportion > sy2 - sy1) {
2490 yportion = sy2 - sy1;
2491 }
2492 sy = floor_cast(sy);
2493 } else if (sy == floorf(sy2)) {
2494 yportion = sy2 - floor_cast(sy2);
2495 } else {
2496 yportion = 1.0f;
2497 }
2498 sx = sx1;
2499 do {
2500 double xportion;
2501 double pcontribution;
2502 int p;
2503 if (floorf(sx) == floor_cast(sx1)) {
2504 xportion = 1.0f - (sx - floor_cast(sx));
2505 if (xportion > sx2 - sx1) {
2506 xportion = sx2 - sx1;
2507 }
2508 sx = floor_cast(sx);
2509 } else if (sx == floorf(sx2)) {
2510 xportion = sx2 - floor_cast(sx2);
2511 } else {
2512 xportion = 1.0f;
2513 }
2514 pcontribution = xportion * yportion;
2515 p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY);
2516
2517 alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution;
2518 red += gdTrueColorGetRed (p) * alpha_factor;
2519 green += gdTrueColorGetGreen (p) * alpha_factor;
2520 blue += gdTrueColorGetBlue (p) * alpha_factor;
2521 alpha += gdTrueColorGetAlpha (p) * pcontribution;
2522 alpha_sum += alpha_factor;
2523 contrib_sum += pcontribution;
2524 spixels += xportion * yportion;
2525 sx += 1.0f;
2526 }
2527 while (sx < sx2);
2528
2529 sy += 1.0f;
2530 }
2531
2532 while (sy < sy2);
2533
2534 if (spixels != 0.0f) {
2535 red /= spixels;
2536 green /= spixels;
2537 blue /= spixels;
2538 alpha /= spixels;
2539 alpha += 0.5;
2540 }
2541 if ( alpha_sum != 0.0f) {
2542 if( contrib_sum != 0.0f) {
2543 alpha_sum /= contrib_sum;
2544 }
2545 red /= alpha_sum;
2546 green /= alpha_sum;
2547 blue /= alpha_sum;
2548 }
2549
2550 if (red > 255.0f) {
2551 red = 255.0f;
2552 }
2553 if (green > 255.0f) {
2554 green = 255.0f;
2555 }
2556 if (blue > 255.0f) {
2557 blue = 255.0f;
2558 }
2559 if (alpha > gdAlphaMax) {
2560 alpha = gdAlphaMax;
2561 }
2562 gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha));
2563 }
2564 }
2565 }
2566
2567 void gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
2568 {
2569 int i;
2570 int lx, ly;
2571 typedef void (*image_line)(gdImagePtr im, int x1, int y1, int x2, int y2, int color);
2572 image_line draw_line;
2573
2574 if (n <= 0) {
2575 return;
2576 }
2577
2578
2579
2580
2581 if (c == gdAntiAliased) {
2582 im->AA_polygon = 1;
2583 }
2584
2585 if ( im->antialias) {
2586 draw_line = gdImageAALine;
2587 } else {
2588 draw_line = gdImageLine;
2589 }
2590 lx = p->x;
2591 ly = p->y;
2592 draw_line(im, lx, ly, p[n - 1].x, p[n - 1].y, c);
2593 for (i = 1; i < n; i++) {
2594 p++;
2595 draw_line(im, lx, ly, p->x, p->y, c);
2596 lx = p->x;
2597 ly = p->y;
2598 }
2599
2600 if (c == gdAntiAliased) {
2601 im->AA_polygon = 0;
2602 gdImageAABlend(im);
2603 }
2604 }
2605
2606 int gdCompareInt (const void *a, const void *b);
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616 void gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
2617 {
2618 int i;
2619 int y;
2620 int miny, maxy, pmaxy;
2621 int x1, y1;
2622 int x2, y2;
2623 int ind1, ind2;
2624 int ints;
2625 int fill_color;
2626
2627 if (n <= 0) {
2628 return;
2629 }
2630
2631 if (overflow2(sizeof(int), n)) {
2632 return;
2633 }
2634
2635 if (c == gdAntiAliased) {
2636 fill_color = im->AA_color;
2637 } else {
2638 fill_color = c;
2639 }
2640
2641 if (!im->polyAllocated) {
2642 im->polyInts = (int *) gdMalloc(sizeof(int) * n);
2643 im->polyAllocated = n;
2644 }
2645 if (im->polyAllocated < n) {
2646 while (im->polyAllocated < n) {
2647 im->polyAllocated *= 2;
2648 }
2649 if (overflow2(sizeof(int), im->polyAllocated)) {
2650 return;
2651 }
2652 im->polyInts = (int *) gdRealloc(im->polyInts, sizeof(int) * im->polyAllocated);
2653 }
2654 miny = p[0].y;
2655 maxy = p[0].y;
2656 for (i = 1; i < n; i++) {
2657 if (p[i].y < miny) {
2658 miny = p[i].y;
2659 }
2660 if (p[i].y > maxy) {
2661 maxy = p[i].y;
2662 }
2663 }
2664 pmaxy = maxy;
2665
2666 if (miny < 0) {
2667 miny = 0;
2668 }
2669 if (maxy >= gdImageSY(im)) {
2670 maxy = gdImageSY(im) - 1;
2671 }
2672
2673
2674 for (y = miny; y <= maxy; y++) {
2675
2676
2677
2678 ints = 0;
2679 for (i = 0; i < n; i++) {
2680 if (!i) {
2681 ind1 = n - 1;
2682 ind2 = 0;
2683 } else {
2684 ind1 = i - 1;
2685 ind2 = i;
2686 }
2687 y1 = p[ind1].y;
2688 y2 = p[ind2].y;
2689 if (y1 < y2) {
2690 x1 = p[ind1].x;
2691 x2 = p[ind2].x;
2692 } else if (y1 > y2) {
2693 y2 = p[ind1].y;
2694 y1 = p[ind2].y;
2695 x2 = p[ind1].x;
2696 x1 = p[ind2].x;
2697 } else {
2698 continue;
2699 }
2700
2701
2702
2703
2704 if (y >= y1 && y < y2) {
2705 im->polyInts[ints++] = (float) ((y - y1) * (x2 - x1)) / (float) (y2 - y1) + 0.5 + x1;
2706 } else if (y == pmaxy && y == y2) {
2707 im->polyInts[ints++] = x2;
2708 }
2709 }
2710 qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
2711
2712 for (i = 0; i < ints - 1; i += 2) {
2713 gdImageLine(im, im->polyInts[i], y, im->polyInts[i + 1], y, fill_color);
2714 }
2715 }
2716
2717
2718 if (c == gdAntiAliased) {
2719 gdImagePolygon(im, p, n, c);
2720 }
2721 }
2722
2723 int gdCompareInt (const void *a, const void *b)
2724 {
2725 return (*(const int *) a) - (*(const int *) b);
2726 }
2727
2728 void gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
2729 {
2730 if (im->style) {
2731 gdFree(im->style);
2732 }
2733 im->style = (int *) gdMalloc(sizeof(int) * noOfPixels);
2734 memcpy(im->style, style, sizeof(int) * noOfPixels);
2735 im->styleLength = noOfPixels;
2736 im->stylePos = 0;
2737 }
2738
2739 void gdImageSetThickness (gdImagePtr im, int thickness)
2740 {
2741 im->thick = thickness;
2742 }
2743
2744 void gdImageSetBrush (gdImagePtr im, gdImagePtr brush)
2745 {
2746 int i;
2747 im->brush = brush;
2748 if (!im->trueColor && !im->brush->trueColor) {
2749 for (i = 0; i < gdImageColorsTotal(brush); i++) {
2750 int index;
2751 index = gdImageColorResolveAlpha(im, gdImageRed(brush, i), gdImageGreen(brush, i), gdImageBlue(brush, i), gdImageAlpha(brush, i));
2752 im->brushColorMap[i] = index;
2753 }
2754 }
2755 }
2756
2757 void gdImageSetTile (gdImagePtr im, gdImagePtr tile)
2758 {
2759 int i;
2760 im->tile = tile;
2761 if (!im->trueColor && !im->tile->trueColor) {
2762 for (i = 0; i < gdImageColorsTotal(tile); i++) {
2763 int index;
2764 index = gdImageColorResolveAlpha(im, gdImageRed(tile, i), gdImageGreen(tile, i), gdImageBlue(tile, i), gdImageAlpha(tile, i));
2765 im->tileColorMap[i] = index;
2766 }
2767 }
2768 }
2769
2770 void gdImageSetAntiAliased (gdImagePtr im, int c)
2771 {
2772 im->AA = 1;
2773 im->AA_color = c;
2774 im->AA_dont_blend = -1;
2775 }
2776
2777 void gdImageSetAntiAliasedDontBlend (gdImagePtr im, int c, int dont_blend)
2778 {
2779 im->AA = 1;
2780 im->AA_color = c;
2781 im->AA_dont_blend = dont_blend;
2782 }
2783
2784
2785 void gdImageInterlace (gdImagePtr im, int interlaceArg)
2786 {
2787 im->interlace = interlaceArg;
2788 }
2789
2790 int gdImageCompare (gdImagePtr im1, gdImagePtr im2)
2791 {
2792 int x, y;
2793 int p1, p2;
2794 int cmpStatus = 0;
2795 int sx, sy;
2796
2797 if (im1->interlace != im2->interlace) {
2798 cmpStatus |= GD_CMP_INTERLACE;
2799 }
2800
2801 if (im1->transparent != im2->transparent) {
2802 cmpStatus |= GD_CMP_TRANSPARENT;
2803 }
2804
2805 if (im1->trueColor != im2->trueColor) {
2806 cmpStatus |= GD_CMP_TRUECOLOR;
2807 }
2808
2809 sx = im1->sx;
2810 if (im1->sx != im2->sx) {
2811 cmpStatus |= GD_CMP_SIZE_X + GD_CMP_IMAGE;
2812 if (im2->sx < im1->sx) {
2813 sx = im2->sx;
2814 }
2815 }
2816
2817 sy = im1->sy;
2818 if (im1->sy != im2->sy) {
2819 cmpStatus |= GD_CMP_SIZE_Y + GD_CMP_IMAGE;
2820 if (im2->sy < im1->sy) {
2821 sy = im2->sy;
2822 }
2823 }
2824
2825 if (im1->colorsTotal != im2->colorsTotal) {
2826 cmpStatus |= GD_CMP_NUM_COLORS;
2827 }
2828
2829 for (y = 0; y < sy; y++) {
2830 for (x = 0; x < sx; x++) {
2831 p1 = im1->trueColor ? gdImageTrueColorPixel(im1, x, y) : gdImagePalettePixel(im1, x, y);
2832 p2 = im2->trueColor ? gdImageTrueColorPixel(im2, x, y) : gdImagePalettePixel(im2, x, y);
2833
2834 if (gdImageRed(im1, p1) != gdImageRed(im2, p2)) {
2835 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
2836 break;
2837 }
2838 if (gdImageGreen(im1, p1) != gdImageGreen(im2, p2)) {
2839 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
2840 break;
2841 }
2842 if (gdImageBlue(im1, p1) != gdImageBlue(im2, p2)) {
2843 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
2844 break;
2845 }
2846 #if 0
2847
2848 if (gdImageAlpha(im1, p1) != gdImageAlpha(im2, p2)) {
2849 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
2850 break;
2851 }
2852 #endif
2853 }
2854 if (cmpStatus & GD_CMP_COLOR) {
2855 break;
2856 }
2857 }
2858
2859 return cmpStatus;
2860 }
2861
2862 int
2863 gdAlphaBlendOld (int dst, int src)
2864 {
2865
2866
2867
2868
2869 return ((((gdTrueColorGetAlpha (src) *
2870 gdTrueColorGetAlpha (dst)) / gdAlphaMax) << 24) +
2871 ((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
2872 gdTrueColorGetRed (src) / gdAlphaMax) +
2873 (gdTrueColorGetAlpha (src) *
2874 gdTrueColorGetRed (dst)) / gdAlphaMax) << 16) +
2875 ((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
2876 gdTrueColorGetGreen (src) / gdAlphaMax) +
2877 (gdTrueColorGetAlpha (src) *
2878 gdTrueColorGetGreen (dst)) / gdAlphaMax) << 8) +
2879 (((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
2880 gdTrueColorGetBlue (src) / gdAlphaMax) +
2881 (gdTrueColorGetAlpha (src) *
2882 gdTrueColorGetBlue (dst)) / gdAlphaMax));
2883 }
2884
2885 int gdAlphaBlend (int dst, int src) {
2886 int src_alpha = gdTrueColorGetAlpha(src);
2887 int dst_alpha, alpha, red, green, blue;
2888 int src_weight, dst_weight, tot_weight;
2889
2890
2891
2892
2893 if( src_alpha == gdAlphaOpaque )
2894 return src;
2895
2896 dst_alpha = gdTrueColorGetAlpha(dst);
2897 if( src_alpha == gdAlphaTransparent )
2898 return dst;
2899 if( dst_alpha == gdAlphaTransparent )
2900 return src;
2901
2902
2903
2904
2905
2906
2907 src_weight = gdAlphaTransparent - src_alpha;
2908 dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax;
2909 tot_weight = src_weight + dst_weight;
2910
2911
2912
2913
2914 alpha = src_alpha * dst_alpha / gdAlphaMax;
2915
2916 red = (gdTrueColorGetRed(src) * src_weight
2917 + gdTrueColorGetRed(dst) * dst_weight) / tot_weight;
2918 green = (gdTrueColorGetGreen(src) * src_weight
2919 + gdTrueColorGetGreen(dst) * dst_weight) / tot_weight;
2920 blue = (gdTrueColorGetBlue(src) * src_weight
2921 + gdTrueColorGetBlue(dst) * dst_weight) / tot_weight;
2922
2923
2924
2925
2926 return ((alpha << 24) + (red << 16) + (green << 8) + blue);
2927
2928 }
2929
2930 void gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg)
2931 {
2932 im->alphaBlendingFlag = alphaBlendingArg;
2933 }
2934
2935 void gdImageAntialias (gdImagePtr im, int antialias)
2936 {
2937 if (im->trueColor){
2938 im->antialias = antialias;
2939 }
2940 }
2941
2942 void gdImageSaveAlpha (gdImagePtr im, int saveAlphaArg)
2943 {
2944 im->saveAlphaFlag = saveAlphaArg;
2945 }
2946
2947 static int gdLayerOverlay (int dst, int src)
2948 {
2949 int a1, a2;
2950 a1 = gdAlphaMax - gdTrueColorGetAlpha(dst);
2951 a2 = gdAlphaMax - gdTrueColorGetAlpha(src);
2952 return ( ((gdAlphaMax - a1*a2/gdAlphaMax) << 24) +
2953 (gdAlphaOverlayColor( gdTrueColorGetRed(src), gdTrueColorGetRed(dst), gdRedMax ) << 16) +
2954 (gdAlphaOverlayColor( gdTrueColorGetGreen(src), gdTrueColorGetGreen(dst), gdGreenMax ) << 8) +
2955 (gdAlphaOverlayColor( gdTrueColorGetBlue(src), gdTrueColorGetBlue(dst), gdBlueMax ))
2956 );
2957 }
2958
2959 static int gdAlphaOverlayColor (int src, int dst, int max )
2960 {
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970 dst = dst << 1;
2971 if( dst > max ) {
2972
2973 return dst + (src << 1) - (dst * src / max) - max;
2974 } else {
2975
2976 return dst * src / max;
2977 }
2978 }
2979
2980 void gdImageSetClip (gdImagePtr im, int x1, int y1, int x2, int y2)
2981 {
2982 if (x1 < 0) {
2983 x1 = 0;
2984 }
2985 if (x1 >= im->sx) {
2986 x1 = im->sx - 1;
2987 }
2988 if (x2 < 0) {
2989 x2 = 0;
2990 }
2991 if (x2 >= im->sx) {
2992 x2 = im->sx - 1;
2993 }
2994 if (y1 < 0) {
2995 y1 = 0;
2996 }
2997 if (y1 >= im->sy) {
2998 y1 = im->sy - 1;
2999 }
3000 if (y2 < 0) {
3001 y2 = 0;
3002 }
3003 if (y2 >= im->sy) {
3004 y2 = im->sy - 1;
3005 }
3006 im->cx1 = x1;
3007 im->cy1 = y1;
3008 im->cx2 = x2;
3009 im->cy2 = y2;
3010 }
3011
3012 void gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P)
3013 {
3014 *x1P = im->cx1;
3015 *y1P = im->cy1;
3016 *x2P = im->cx2;
3017 *y2P = im->cy2;
3018 }
3019
3020
3021 int gdImagePaletteToTrueColor(gdImagePtr src)
3022 {
3023 unsigned int y;
3024 unsigned int yy;
3025
3026 if (src == NULL) {
3027 return 0;
3028 }
3029
3030 if (src->trueColor == 1) {
3031 return 1;
3032 } else {
3033 unsigned int x;
3034 const unsigned int sy = gdImageSY(src);
3035 const unsigned int sx = gdImageSX(src);
3036
3037 src->tpixels = (int **) gdMalloc(sizeof(int *) * sy);
3038 if (src->tpixels == NULL) {
3039 return 0;
3040 }
3041
3042 for (y = 0; y < sy; y++) {
3043 const unsigned char *src_row = src->pixels[y];
3044 int * dst_row;
3045
3046
3047 src->tpixels[y] = (int *) gdMalloc(sx * sizeof(int));
3048 if (src->tpixels[y] == NULL) {
3049 goto clean_on_error;
3050 }
3051
3052 dst_row = src->tpixels[y];
3053 for (x = 0; x < sx; x++) {
3054 const unsigned char c = *(src_row + x);
3055 if (c == src->transparent) {
3056 *(dst_row + x) = gdTrueColorAlpha(0, 0, 0, 127);
3057 } else {
3058 *(dst_row + x) = gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
3059 }
3060 }
3061 }
3062 }
3063
3064
3065 for (yy = 0; yy < y; yy++) {
3066 gdFree(src->pixels[yy]);
3067 }
3068 gdFree(src->pixels);
3069 src->trueColor = 1;
3070 src->pixels = NULL;
3071 src->alphaBlendingFlag = 0;
3072 src->saveAlphaFlag = 1;
3073
3074 if (src->transparent >= 0) {
3075 const unsigned char c = src->transparent;
3076 src->transparent = gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
3077 }
3078
3079 return 1;
3080
3081 clean_on_error:
3082 if (y > 0) {
3083
3084 for (yy = y; yy >= yy - 1; y--) {
3085 gdFree(src->tpixels[y]);
3086 }
3087 gdFree(src->tpixels);
3088 }
3089 return 0;
3090 }
3091