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