1 #if HAVE_GD_BUNDLED
2 # include "gd.h"
3 #else
4 # include <gd.h>
5 #endif
6
7 #include "gd_intern.h"
8
9 /* Filters function added on 2003/12
10 * by Pierre-Alain Joye (pierre@php.net)
11 **/
12 /* Begin filters function */
13 #define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel)
14
15 /* invert src image */
gdImageNegate(gdImagePtr src)16 int gdImageNegate(gdImagePtr src)
17 {
18 int x, y;
19 int r,g,b,a;
20 int new_pxl, pxl;
21 typedef int (*FuncPtr)(gdImagePtr, int, int);
22 FuncPtr f;
23
24 if (src==NULL) {
25 return 0;
26 }
27
28 f = GET_PIXEL_FUNCTION(src);
29
30 for (y=0; y<src->sy; ++y) {
31 for (x=0; x<src->sx; ++x) {
32 pxl = f (src, x, y);
33 r = gdImageRed(src, pxl);
34 g = gdImageGreen(src, pxl);
35 b = gdImageBlue(src, pxl);
36 a = gdImageAlpha(src, pxl);
37
38 new_pxl = gdImageColorAllocateAlpha(src, 255-r, 255-g, 255-b, a);
39 if (new_pxl == -1) {
40 new_pxl = gdImageColorClosestAlpha(src, 255-r, 255-g, 255-b, a);
41 }
42 gdImageSetPixel (src, x, y, new_pxl);
43 }
44 }
45 return 1;
46 }
47
48 /* Convert the image src to a grayscale image */
gdImageGrayScale(gdImagePtr src)49 int gdImageGrayScale(gdImagePtr src)
50 {
51 int x, y;
52 int r,g,b,a;
53 int new_pxl, pxl;
54 typedef int (*FuncPtr)(gdImagePtr, int, int);
55 FuncPtr f;
56 int alpha_blending;
57
58 f = GET_PIXEL_FUNCTION(src);
59
60 if (src==NULL) {
61 return 0;
62 }
63
64 alpha_blending = src->alphaBlendingFlag;
65 gdImageAlphaBlending(src, gdEffectReplace);
66
67 for (y=0; y<src->sy; ++y) {
68 for (x=0; x<src->sx; ++x) {
69 pxl = f (src, x, y);
70 r = gdImageRed(src, pxl);
71 g = gdImageGreen(src, pxl);
72 b = gdImageBlue(src, pxl);
73 a = gdImageAlpha(src, pxl);
74 r = g = b = (int) (.299 * r + .587 * g + .114 * b);
75
76 new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a);
77 if (new_pxl == -1) {
78 new_pxl = gdImageColorClosestAlpha(src, r, g, b, a);
79 }
80 gdImageSetPixel (src, x, y, new_pxl);
81 }
82 }
83 gdImageAlphaBlending(src, alpha_blending);
84
85 return 1;
86 }
87
88 /* Set the brightness level <level> for the image src */
gdImageBrightness(gdImagePtr src,int brightness)89 int gdImageBrightness(gdImagePtr src, int brightness)
90 {
91 int x, y;
92 int r,g,b,a;
93 int new_pxl, pxl;
94 typedef int (*FuncPtr)(gdImagePtr, int, int);
95 FuncPtr f;
96 f = GET_PIXEL_FUNCTION(src);
97
98 if (src==NULL || (brightness < -255 || brightness>255)) {
99 return 0;
100 }
101
102 if (brightness==0) {
103 return 1;
104 }
105
106 for (y=0; y<src->sy; ++y) {
107 for (x=0; x<src->sx; ++x) {
108 pxl = f (src, x, y);
109
110 r = gdImageRed(src, pxl);
111 g = gdImageGreen(src, pxl);
112 b = gdImageBlue(src, pxl);
113 a = gdImageAlpha(src, pxl);
114
115 r = r + brightness;
116 g = g + brightness;
117 b = b + brightness;
118
119 r = (r > 255)? 255 : ((r < 0)? 0:r);
120 g = (g > 255)? 255 : ((g < 0)? 0:g);
121 b = (b > 255)? 255 : ((b < 0)? 0:b);
122
123 new_pxl = gdImageColorAllocateAlpha(src, (int)r, (int)g, (int)b, a);
124 if (new_pxl == -1) {
125 new_pxl = gdImageColorClosestAlpha(src, (int)r, (int)g, (int)b, a);
126 }
127 gdImageSetPixel (src, x, y, new_pxl);
128 }
129 }
130 return 1;
131 }
132
133
gdImageContrast(gdImagePtr src,double contrast)134 int gdImageContrast(gdImagePtr src, double contrast)
135 {
136 int x, y;
137 int r,g,b,a;
138 double rf,gf,bf;
139 int new_pxl, pxl;
140 typedef int (*FuncPtr)(gdImagePtr, int, int);
141
142 FuncPtr f;
143 f = GET_PIXEL_FUNCTION(src);
144
145 if (src==NULL) {
146 return 0;
147 }
148
149 contrast = (double)(100.0-contrast)/100.0;
150 contrast = contrast*contrast;
151
152 for (y=0; y<src->sy; ++y) {
153 for (x=0; x<src->sx; ++x) {
154 pxl = f(src, x, y);
155
156 r = gdImageRed(src, pxl);
157 g = gdImageGreen(src, pxl);
158 b = gdImageBlue(src, pxl);
159 a = gdImageAlpha(src, pxl);
160
161 rf = (double)r/255.0;
162 rf = rf-0.5;
163 rf = rf*contrast;
164 rf = rf+0.5;
165 rf = rf*255.0;
166
167 bf = (double)b/255.0;
168 bf = bf-0.5;
169 bf = bf*contrast;
170 bf = bf+0.5;
171 bf = bf*255.0;
172
173 gf = (double)g/255.0;
174 gf = gf-0.5;
175 gf = gf*contrast;
176 gf = gf+0.5;
177 gf = gf*255.0;
178
179 rf = (rf > 255.0)? 255.0 : ((rf < 0.0)? 0.0:rf);
180 gf = (gf > 255.0)? 255.0 : ((gf < 0.0)? 0.0:gf);
181 bf = (bf > 255.0)? 255.0 : ((bf < 0.0)? 0.0:bf);
182
183 new_pxl = gdImageColorAllocateAlpha(src, (int)rf, (int)gf, (int)bf, a);
184 if (new_pxl == -1) {
185 new_pxl = gdImageColorClosestAlpha(src, (int)rf, (int)gf, (int)bf, a);
186 }
187 gdImageSetPixel (src, x, y, new_pxl);
188 }
189 }
190 return 1;
191 }
192
193
gdImageColor(gdImagePtr src,const int red,const int green,const int blue,const int alpha)194 int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha)
195 {
196 int x, y;
197 int new_pxl, pxl;
198 typedef int (*FuncPtr)(gdImagePtr, int, int);
199 FuncPtr f;
200
201 if (src == NULL) {
202 return 0;
203 }
204
205 f = GET_PIXEL_FUNCTION(src);
206
207 for (y=0; y<src->sy; ++y) {
208 for (x=0; x<src->sx; ++x) {
209 int r,g,b,a;
210
211 pxl = f(src, x, y);
212 r = gdImageRed(src, pxl);
213 g = gdImageGreen(src, pxl);
214 b = gdImageBlue(src, pxl);
215 a = gdImageAlpha(src, pxl);
216
217 r = r + red;
218 g = g + green;
219 b = b + blue;
220 a = a + alpha;
221
222 r = (r > 255)? 255 : ((r < 0)? 0 : r);
223 g = (g > 255)? 255 : ((g < 0)? 0 : g);
224 b = (b > 255)? 255 : ((b < 0)? 0 : b);
225 a = (a > 127)? 127 : ((a < 0)? 0 : a);
226
227 new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a);
228 if (new_pxl == -1) {
229 new_pxl = gdImageColorClosestAlpha(src, r, g, b, a);
230 }
231 gdImageSetPixel (src, x, y, new_pxl);
232 }
233 }
234 return 1;
235 }
236
gdImageConvolution(gdImagePtr src,float filter[3][3],float filter_div,float offset)237 int gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset)
238 {
239 int x, y, i, j, new_a;
240 float new_r, new_g, new_b;
241 int new_pxl, pxl=0;
242 gdImagePtr srcback;
243 typedef int (*FuncPtr)(gdImagePtr, int, int);
244 FuncPtr f;
245
246 if (src==NULL) {
247 return 0;
248 }
249
250 /* We need the orinal image with each safe neoghb. pixel */
251 srcback = gdImageCreateTrueColor (src->sx, src->sy);
252 if (srcback==NULL) {
253 return 0;
254 }
255
256 gdImageSaveAlpha(srcback, 1);
257 new_pxl = gdImageColorAllocateAlpha(srcback, 0, 0, 0, 127);
258 gdImageFill(srcback, 0, 0, new_pxl);
259
260 gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy);
261
262 f = GET_PIXEL_FUNCTION(src);
263
264 for ( y=0; y<src->sy; y++) {
265 for(x=0; x<src->sx; x++) {
266 new_r = new_g = new_b = 0;
267 pxl = f(srcback, x, y);
268 new_a = gdImageAlpha(srcback, pxl);
269
270 for (j=0; j<3; j++) {
271 int yv = MIN(MAX(y - 1 + j, 0), src->sy - 1);
272 for (i=0; i<3; i++) {
273 pxl = f(srcback, MIN(MAX(x - 1 + i, 0), src->sx - 1), yv);
274 new_r += (float)gdImageRed(srcback, pxl) * filter[j][i];
275 new_g += (float)gdImageGreen(srcback, pxl) * filter[j][i];
276 new_b += (float)gdImageBlue(srcback, pxl) * filter[j][i];
277 }
278 }
279
280 new_r = (new_r/filter_div)+offset;
281 new_g = (new_g/filter_div)+offset;
282 new_b = (new_b/filter_div)+offset;
283
284 new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r);
285 new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g);
286 new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b);
287
288 new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
289 if (new_pxl == -1) {
290 new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
291 }
292 gdImageSetPixel (src, x, y, new_pxl);
293 }
294 }
295 gdImageDestroy(srcback);
296 return 1;
297 }
298
gdImageSelectiveBlur(gdImagePtr src)299 int gdImageSelectiveBlur( gdImagePtr src)
300 {
301 int x, y, i, j;
302 float new_r, new_g, new_b;
303 int new_pxl, cpxl, pxl, new_a=0;
304 float flt_r [3][3];
305 float flt_g [3][3];
306 float flt_b [3][3];
307 float flt_r_sum, flt_g_sum, flt_b_sum;
308
309 gdImagePtr srcback;
310 typedef int (*FuncPtr)(gdImagePtr, int, int);
311 FuncPtr f;
312
313 if (src==NULL) {
314 return 0;
315 }
316
317 /* We need the orinal image with each safe neoghb. pixel */
318 srcback = gdImageCreateTrueColor (src->sx, src->sy);
319 if (srcback==NULL) {
320 return 0;
321 }
322 gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy);
323
324 f = GET_PIXEL_FUNCTION(src);
325
326 for(y = 0; y<src->sy; y++) {
327 for (x=0; x<src->sx; x++) {
328 flt_r_sum = flt_g_sum = flt_b_sum = 0.0;
329 cpxl = f(src, x, y);
330
331 for (j=0; j<3; j++) {
332 for (i=0; i<3; i++) {
333 if ((j == 1) && (i == 1)) {
334 flt_r[1][1] = flt_g[1][1] = flt_b[1][1] = 0.5;
335 } else {
336 pxl = f(src, x-(3>>1)+i, y-(3>>1)+j);
337 new_a = gdImageAlpha(srcback, pxl);
338
339 new_r = ((float)gdImageRed(srcback, cpxl)) - ((float)gdImageRed (srcback, pxl));
340
341 if (new_r < 0.0f) {
342 new_r = -new_r;
343 }
344 if (new_r != 0) {
345 flt_r[j][i] = 1.0f/new_r;
346 } else {
347 flt_r[j][i] = 1.0f;
348 }
349
350 new_g = ((float)gdImageGreen(srcback, cpxl)) - ((float)gdImageGreen(srcback, pxl));
351
352 if (new_g < 0.0f) {
353 new_g = -new_g;
354 }
355 if (new_g != 0) {
356 flt_g[j][i] = 1.0f/new_g;
357 } else {
358 flt_g[j][i] = 1.0f;
359 }
360
361 new_b = ((float)gdImageBlue(srcback, cpxl)) - ((float)gdImageBlue(srcback, pxl));
362
363 if (new_b < 0.0f) {
364 new_b = -new_b;
365 }
366 if (new_b != 0) {
367 flt_b[j][i] = 1.0f/new_b;
368 } else {
369 flt_b[j][i] = 1.0f;
370 }
371 }
372
373 flt_r_sum += flt_r[j][i];
374 flt_g_sum += flt_g[j][i];
375 flt_b_sum += flt_b [j][i];
376 }
377 }
378
379 for (j=0; j<3; j++) {
380 for (i=0; i<3; i++) {
381 if (flt_r_sum != 0.0) {
382 flt_r[j][i] /= flt_r_sum;
383 }
384 if (flt_g_sum != 0.0) {
385 flt_g[j][i] /= flt_g_sum;
386 }
387 if (flt_b_sum != 0.0) {
388 flt_b [j][i] /= flt_b_sum;
389 }
390 }
391 }
392
393 new_r = new_g = new_b = 0.0;
394
395 for (j=0; j<3; j++) {
396 for (i=0; i<3; i++) {
397 pxl = f(src, x-(3>>1)+i, y-(3>>1)+j);
398 new_r += (float)gdImageRed(srcback, pxl) * flt_r[j][i];
399 new_g += (float)gdImageGreen(srcback, pxl) * flt_g[j][i];
400 new_b += (float)gdImageBlue(srcback, pxl) * flt_b[j][i];
401 }
402 }
403
404 new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r);
405 new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g);
406 new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b);
407 new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
408 if (new_pxl == -1) {
409 new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
410 }
411 gdImageSetPixel (src, x, y, new_pxl);
412 }
413 }
414 gdImageDestroy(srcback);
415 return 1;
416 }
417
gdImageEdgeDetectQuick(gdImagePtr src)418 int gdImageEdgeDetectQuick(gdImagePtr src)
419 {
420 float filter[3][3] = {{-1.0,0.0,-1.0},
421 {0.0,4.0,0.0},
422 {-1.0,0.0,-1.0}};
423
424 return gdImageConvolution(src, filter, 1, 127);
425 }
426
gdImageGaussianBlur(gdImagePtr im)427 int gdImageGaussianBlur(gdImagePtr im)
428 {
429 float filter[3][3] = {{1.0,2.0,1.0},
430 {2.0,4.0,2.0},
431 {1.0,2.0,1.0}};
432
433 return gdImageConvolution(im, filter, 16, 0);
434 }
435
gdImageEmboss(gdImagePtr im)436 int gdImageEmboss(gdImagePtr im)
437 {
438 /*
439 float filter[3][3] = {{1.0,1.0,1.0},
440 {0.0,0.0,0.0},
441 {-1.0,-1.0,-1.0}};
442 */
443 float filter[3][3] = {{ 1.5, 0.0, 0.0},
444 { 0.0, 0.0, 0.0},
445 { 0.0, 0.0,-1.5}};
446
447 return gdImageConvolution(im, filter, 1, 127);
448 }
449
gdImageMeanRemoval(gdImagePtr im)450 int gdImageMeanRemoval(gdImagePtr im)
451 {
452 float filter[3][3] = {{-1.0,-1.0,-1.0},
453 {-1.0,9.0,-1.0},
454 {-1.0,-1.0,-1.0}};
455
456 return gdImageConvolution(im, filter, 1, 0);
457 }
458
gdImageSmooth(gdImagePtr im,float weight)459 int gdImageSmooth(gdImagePtr im, float weight)
460 {
461 float filter[3][3] = {{1.0,1.0,1.0},
462 {1.0,0.0,1.0},
463 {1.0,1.0,1.0}};
464
465 filter[1][1] = weight;
466
467 return gdImageConvolution(im, filter, weight+8, 0);
468 }
469 /* End filters function */
470