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