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 new_a = gdImageAlpha(srcback, pxl);
268
269 for (j=0; j<3; j++) {
270 int yv = MIN(MAX(y - 1 + j, 0), src->sy - 1);
271 for (i=0; i<3; i++) {
272 pxl = f(srcback, MIN(MAX(x - 1 + i, 0), src->sx - 1), yv);
273 new_r += (float)gdImageRed(srcback, pxl) * filter[j][i];
274 new_g += (float)gdImageGreen(srcback, pxl) * filter[j][i];
275 new_b += (float)gdImageBlue(srcback, pxl) * filter[j][i];
276 }
277 }
278
279 new_r = (new_r/filter_div)+offset;
280 new_g = (new_g/filter_div)+offset;
281 new_b = (new_b/filter_div)+offset;
282
283 new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r);
284 new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g);
285 new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b);
286
287 new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
288 if (new_pxl == -1) {
289 new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
290 }
291 gdImageSetPixel (src, x, y, new_pxl);
292 }
293 }
294 gdImageDestroy(srcback);
295 return 1;
296 }
297
gdImageSelectiveBlur(gdImagePtr src)298 int gdImageSelectiveBlur( gdImagePtr src)
299 {
300 int x, y, i, j;
301 float new_r, new_g, new_b;
302 int new_pxl, cpxl, pxl, new_a=0;
303 float flt_r [3][3];
304 float flt_g [3][3];
305 float flt_b [3][3];
306 float flt_r_sum, flt_g_sum, flt_b_sum;
307
308 gdImagePtr srcback;
309 typedef int (*FuncPtr)(gdImagePtr, int, int);
310 FuncPtr f;
311
312 if (src==NULL) {
313 return 0;
314 }
315
316 /* We need the orinal image with each safe neoghb. pixel */
317 srcback = gdImageCreateTrueColor (src->sx, src->sy);
318 if (srcback==NULL) {
319 return 0;
320 }
321 gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy);
322
323 f = GET_PIXEL_FUNCTION(src);
324
325 for(y = 0; y<src->sy; y++) {
326 for (x=0; x<src->sx; x++) {
327 flt_r_sum = flt_g_sum = flt_b_sum = 0.0;
328 cpxl = f(src, x, y);
329
330 for (j=0; j<3; j++) {
331 for (i=0; i<3; i++) {
332 if ((j == 1) && (i == 1)) {
333 flt_r[1][1] = flt_g[1][1] = flt_b[1][1] = 0.5;
334 } else {
335 pxl = f(src, x-(3>>1)+i, y-(3>>1)+j);
336 new_a = gdImageAlpha(srcback, pxl);
337
338 new_r = ((float)gdImageRed(srcback, cpxl)) - ((float)gdImageRed (srcback, pxl));
339
340 if (new_r < 0.0f) {
341 new_r = -new_r;
342 }
343 if (new_r != 0) {
344 flt_r[j][i] = 1.0f/new_r;
345 } else {
346 flt_r[j][i] = 1.0f;
347 }
348
349 new_g = ((float)gdImageGreen(srcback, cpxl)) - ((float)gdImageGreen(srcback, pxl));
350
351 if (new_g < 0.0f) {
352 new_g = -new_g;
353 }
354 if (new_g != 0) {
355 flt_g[j][i] = 1.0f/new_g;
356 } else {
357 flt_g[j][i] = 1.0f;
358 }
359
360 new_b = ((float)gdImageBlue(srcback, cpxl)) - ((float)gdImageBlue(srcback, pxl));
361
362 if (new_b < 0.0f) {
363 new_b = -new_b;
364 }
365 if (new_b != 0) {
366 flt_b[j][i] = 1.0f/new_b;
367 } else {
368 flt_b[j][i] = 1.0f;
369 }
370 }
371
372 flt_r_sum += flt_r[j][i];
373 flt_g_sum += flt_g[j][i];
374 flt_b_sum += flt_b [j][i];
375 }
376 }
377
378 for (j=0; j<3; j++) {
379 for (i=0; i<3; i++) {
380 if (flt_r_sum != 0.0) {
381 flt_r[j][i] /= flt_r_sum;
382 }
383 if (flt_g_sum != 0.0) {
384 flt_g[j][i] /= flt_g_sum;
385 }
386 if (flt_b_sum != 0.0) {
387 flt_b [j][i] /= flt_b_sum;
388 }
389 }
390 }
391
392 new_r = new_g = new_b = 0.0;
393
394 for (j=0; j<3; j++) {
395 for (i=0; i<3; i++) {
396 pxl = f(src, x-(3>>1)+i, y-(3>>1)+j);
397 new_r += (float)gdImageRed(srcback, pxl) * flt_r[j][i];
398 new_g += (float)gdImageGreen(srcback, pxl) * flt_g[j][i];
399 new_b += (float)gdImageBlue(srcback, pxl) * flt_b[j][i];
400 }
401 }
402
403 new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r);
404 new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g);
405 new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b);
406 new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
407 if (new_pxl == -1) {
408 new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
409 }
410 gdImageSetPixel (src, x, y, new_pxl);
411 }
412 }
413 gdImageDestroy(srcback);
414 return 1;
415 }
416
gdImageEdgeDetectQuick(gdImagePtr src)417 int gdImageEdgeDetectQuick(gdImagePtr src)
418 {
419 float filter[3][3] = {{-1.0,0.0,-1.0},
420 {0.0,4.0,0.0},
421 {-1.0,0.0,-1.0}};
422
423 return gdImageConvolution(src, filter, 1, 127);
424 }
425
gdImageGaussianBlur(gdImagePtr im)426 int gdImageGaussianBlur(gdImagePtr im)
427 {
428 float filter[3][3] = {{1.0,2.0,1.0},
429 {2.0,4.0,2.0},
430 {1.0,2.0,1.0}};
431
432 return gdImageConvolution(im, filter, 16, 0);
433 }
434
gdImageEmboss(gdImagePtr im)435 int gdImageEmboss(gdImagePtr im)
436 {
437 /*
438 float filter[3][3] = {{1.0,1.0,1.0},
439 {0.0,0.0,0.0},
440 {-1.0,-1.0,-1.0}};
441 */
442 float filter[3][3] = {{ 1.5, 0.0, 0.0},
443 { 0.0, 0.0, 0.0},
444 { 0.0, 0.0,-1.5}};
445
446 return gdImageConvolution(im, filter, 1, 127);
447 }
448
gdImageMeanRemoval(gdImagePtr im)449 int gdImageMeanRemoval(gdImagePtr im)
450 {
451 float filter[3][3] = {{-1.0,-1.0,-1.0},
452 {-1.0,9.0,-1.0},
453 {-1.0,-1.0,-1.0}};
454
455 return gdImageConvolution(im, filter, 1, 0);
456 }
457
gdImageSmooth(gdImagePtr im,float weight)458 int gdImageSmooth(gdImagePtr im, float weight)
459 {
460 float filter[3][3] = {{1.0,1.0,1.0},
461 {1.0,0.0,1.0},
462 {1.0,1.0,1.0}};
463
464 filter[1][1] = weight;
465
466 return gdImageConvolution(im, filter, weight+8, 0);
467 }
468 /* End filters function */
469