root/ext/gd/libgd/gd_filter.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gdImageNegate
  2. gdImageGrayScale
  3. gdImageBrightness
  4. gdImageContrast
  5. gdImageColor
  6. gdImageConvolution
  7. gdImageSelectiveBlur
  8. gdImageEdgeDetectQuick
  9. gdImageGaussianBlur
  10. gdImageEmboss
  11. gdImageMeanRemoval
  12. gdImageSmooth

   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 */
  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 */
  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 */
  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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 */

/* [<][>][^][v][top][bottom][index][help] */