Browse Source
- MFB: [DOC] always enable imagefilter and imageconvolution, even when built against system's gd
experimental/first_unicode_implementation
- MFB: [DOC] always enable imagefilter and imageconvolution, even when built against system's gd
experimental/first_unicode_implementation
6 changed files with 540 additions and 31 deletions
-
4ext/gd/config.m4
-
43ext/gd/gd.c
-
1ext/gd/libgd/gd.h
-
49ext/gd/libgd/gd_compat.h
-
461ext/gd/libgd/gd_filter.c
-
13ext/gd/libgd/gd_intern.h
@ -1,5 +1,54 @@ |
|||
#ifndef GD_COMPAT_H |
|||
#define GD_COMPAT_H 1 |
|||
|
|||
#if HAVE_GD_BUNDLED |
|||
# include "gd.h" |
|||
#else |
|||
# include <gd.h> |
|||
#endif |
|||
|
|||
|
|||
|
|||
const char * gdPngGetVersionString(); |
|||
int gdJpegGetVersionString(); |
|||
int gdJpegGetVersionInt(); |
|||
int overflow2(int a, int b); |
|||
|
|||
/* filters section |
|||
* |
|||
* Negate the imag src, white becomes black, |
|||
* The red, green, and blue intensities of an image are negated. |
|||
* White becomes black, yellow becomes blue, etc. |
|||
*/ |
|||
int gdImageNegate(gdImagePtr src); |
|||
|
|||
/* Convert the image src to a grayscale image */ |
|||
int gdImageGrayScale(gdImagePtr src); |
|||
|
|||
/* Set the brightness level <brightness> for the image src */ |
|||
int gdImageBrightness(gdImagePtr src, int brightness); |
|||
|
|||
/* Set the contrast level <contrast> for the image <src> */ |
|||
int gdImageContrast(gdImagePtr src, double contrast); |
|||
|
|||
/* Simply adds or substracts respectively red, green or blue to a pixel */ |
|||
int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha); |
|||
|
|||
/* Image convolution by a 3x3 custom matrix */ |
|||
int gdImageConvolution(gdImagePtr src, float ft[3][3], float filter_div, float offset); |
|||
int gdImageEdgeDetectQuick(gdImagePtr src); |
|||
int gdImageGaussianBlur(gdImagePtr im); |
|||
int gdImageSelectiveBlur( gdImagePtr src); |
|||
int gdImageEmboss(gdImagePtr im); |
|||
int gdImageMeanRemoval(gdImagePtr im); |
|||
int gdImageSmooth(gdImagePtr im, float weight); |
|||
enum gdPixelateMode { |
|||
GD_PIXELATE_UPPERLEFT, |
|||
GD_PIXELATE_AVERAGE |
|||
}; |
|||
|
|||
int gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode); |
|||
|
|||
|
|||
#endif |
|||
|
|||
@ -0,0 +1,461 @@ |
|||
#if HAVE_GD_BUNDLED |
|||
# include "gd.h" |
|||
#else |
|||
# include <gd.h> |
|||
#endif |
|||
|
|||
#include "gd_intern.h" |
|||
|
|||
/* Filters function added on 2003/12 |
|||
* by Pierre-Alain Joye (pierre@php.net) |
|||
**/ |
|||
/* Begin filters function */ |
|||
#define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel) |
|||
|
|||
/* invert src image */ |
|||
int gdImageNegate(gdImagePtr src) |
|||
{ |
|||
int x, y; |
|||
int r,g,b,a; |
|||
int new_pxl, pxl; |
|||
typedef int (*FuncPtr)(gdImagePtr, int, int); |
|||
FuncPtr f; |
|||
|
|||
if (src==NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
f = GET_PIXEL_FUNCTION(src); |
|||
|
|||
for (y=0; y<src->sy; ++y) { |
|||
for (x=0; x<src->sx; ++x) { |
|||
pxl = f (src, x, y); |
|||
r = gdImageRed(src, pxl); |
|||
g = gdImageGreen(src, pxl); |
|||
b = gdImageBlue(src, pxl); |
|||
a = gdImageAlpha(src, pxl); |
|||
|
|||
new_pxl = gdImageColorAllocateAlpha(src, 255-r, 255-g, 255-b, a); |
|||
if (new_pxl == -1) { |
|||
new_pxl = gdImageColorClosestAlpha(src, 255-r, 255-g, 255-b, a); |
|||
} |
|||
gdImageSetPixel (src, x, y, new_pxl); |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
/* Convert the image src to a grayscale image */ |
|||
int gdImageGrayScale(gdImagePtr src) |
|||
{ |
|||
int x, y; |
|||
int r,g,b,a; |
|||
int new_pxl, pxl; |
|||
typedef int (*FuncPtr)(gdImagePtr, int, int); |
|||
FuncPtr f; |
|||
f = GET_PIXEL_FUNCTION(src); |
|||
|
|||
if (src==NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
for (y=0; y<src->sy; ++y) { |
|||
for (x=0; x<src->sx; ++x) { |
|||
pxl = f (src, x, y); |
|||
r = gdImageRed(src, pxl); |
|||
g = gdImageGreen(src, pxl); |
|||
b = gdImageBlue(src, pxl); |
|||
a = gdImageAlpha(src, pxl); |
|||
r = g = b = (int) (.299 * r + .587 * g + .114 * b); |
|||
|
|||
new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); |
|||
if (new_pxl == -1) { |
|||
new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); |
|||
} |
|||
gdImageSetPixel (src, x, y, new_pxl); |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
/* Set the brightness level <level> for the image src */ |
|||
int gdImageBrightness(gdImagePtr src, int brightness) |
|||
{ |
|||
int x, y; |
|||
int r,g,b,a; |
|||
int new_pxl, pxl; |
|||
typedef int (*FuncPtr)(gdImagePtr, int, int); |
|||
FuncPtr f; |
|||
f = GET_PIXEL_FUNCTION(src); |
|||
|
|||
if (src==NULL || (brightness < -255 || brightness>255)) { |
|||
return 0; |
|||
} |
|||
|
|||
if (brightness==0) { |
|||
return 1; |
|||
} |
|||
|
|||
for (y=0; y<src->sy; ++y) { |
|||
for (x=0; x<src->sx; ++x) { |
|||
pxl = f (src, x, y); |
|||
|
|||
r = gdImageRed(src, pxl); |
|||
g = gdImageGreen(src, pxl); |
|||
b = gdImageBlue(src, pxl); |
|||
a = gdImageAlpha(src, pxl); |
|||
|
|||
r = r + brightness; |
|||
g = g + brightness; |
|||
b = b + brightness; |
|||
|
|||
r = (r > 255)? 255 : ((r < 0)? 0:r); |
|||
g = (g > 255)? 255 : ((g < 0)? 0:g); |
|||
b = (b > 255)? 255 : ((b < 0)? 0:b); |
|||
|
|||
new_pxl = gdImageColorAllocateAlpha(src, (int)r, (int)g, (int)b, a); |
|||
if (new_pxl == -1) { |
|||
new_pxl = gdImageColorClosestAlpha(src, (int)r, (int)g, (int)b, a); |
|||
} |
|||
gdImageSetPixel (src, x, y, new_pxl); |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
|
|||
int gdImageContrast(gdImagePtr src, double contrast) |
|||
{ |
|||
int x, y; |
|||
int r,g,b,a; |
|||
double rf,gf,bf; |
|||
int new_pxl, pxl; |
|||
typedef int (*FuncPtr)(gdImagePtr, int, int); |
|||
|
|||
FuncPtr f; |
|||
f = GET_PIXEL_FUNCTION(src); |
|||
|
|||
if (src==NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
contrast = (double)(100.0-contrast)/100.0; |
|||
contrast = contrast*contrast; |
|||
|
|||
for (y=0; y<src->sy; ++y) { |
|||
for (x=0; x<src->sx; ++x) { |
|||
pxl = f(src, x, y); |
|||
|
|||
r = gdImageRed(src, pxl); |
|||
g = gdImageGreen(src, pxl); |
|||
b = gdImageBlue(src, pxl); |
|||
a = gdImageAlpha(src, pxl); |
|||
|
|||
rf = (double)r/255.0; |
|||
rf = rf-0.5; |
|||
rf = rf*contrast; |
|||
rf = rf+0.5; |
|||
rf = rf*255.0; |
|||
|
|||
bf = (double)b/255.0; |
|||
bf = bf-0.5; |
|||
bf = bf*contrast; |
|||
bf = bf+0.5; |
|||
bf = bf*255.0; |
|||
|
|||
gf = (double)g/255.0; |
|||
gf = gf-0.5; |
|||
gf = gf*contrast; |
|||
gf = gf+0.5; |
|||
gf = gf*255.0; |
|||
|
|||
rf = (rf > 255.0)? 255.0 : ((rf < 0.0)? 0.0:rf); |
|||
gf = (gf > 255.0)? 255.0 : ((gf < 0.0)? 0.0:gf); |
|||
bf = (bf > 255.0)? 255.0 : ((bf < 0.0)? 0.0:bf); |
|||
|
|||
new_pxl = gdImageColorAllocateAlpha(src, (int)rf, (int)gf, (int)bf, a); |
|||
if (new_pxl == -1) { |
|||
new_pxl = gdImageColorClosestAlpha(src, (int)rf, (int)gf, (int)bf, a); |
|||
} |
|||
gdImageSetPixel (src, x, y, new_pxl); |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
|
|||
int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha) |
|||
{ |
|||
int x, y; |
|||
int new_pxl, pxl; |
|||
typedef int (*FuncPtr)(gdImagePtr, int, int); |
|||
FuncPtr f; |
|||
|
|||
if (src == NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
f = GET_PIXEL_FUNCTION(src); |
|||
|
|||
for (y=0; y<src->sy; ++y) { |
|||
for (x=0; x<src->sx; ++x) { |
|||
int r,g,b,a; |
|||
|
|||
pxl = f(src, x, y); |
|||
r = gdImageRed(src, pxl); |
|||
g = gdImageGreen(src, pxl); |
|||
b = gdImageBlue(src, pxl); |
|||
a = gdImageAlpha(src, pxl); |
|||
|
|||
r = r + red; |
|||
g = g + green; |
|||
b = b + blue; |
|||
a = a + alpha; |
|||
|
|||
r = (r > 255)? 255 : ((r < 0)? 0 : r); |
|||
g = (g > 255)? 255 : ((g < 0)? 0 : g); |
|||
b = (b > 255)? 255 : ((b < 0)? 0 : b); |
|||
a = (a > 127)? 127 : ((a < 0)? 0 : a); |
|||
|
|||
new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); |
|||
if (new_pxl == -1) { |
|||
new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); |
|||
} |
|||
gdImageSetPixel (src, x, y, new_pxl); |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
int gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset) |
|||
{ |
|||
int x, y, i, j, new_a; |
|||
float new_r, new_g, new_b; |
|||
int new_pxl, pxl=0; |
|||
gdImagePtr srcback; |
|||
typedef int (*FuncPtr)(gdImagePtr, int, int); |
|||
FuncPtr f; |
|||
|
|||
if (src==NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
/* We need the orinal image with each safe neoghb. pixel */ |
|||
srcback = gdImageCreateTrueColor (src->sx, src->sy); |
|||
if (srcback==NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
gdImageSaveAlpha(srcback, 1); |
|||
new_pxl = gdImageColorAllocateAlpha(srcback, 0, 0, 0, 127); |
|||
gdImageFill(srcback, 0, 0, new_pxl); |
|||
|
|||
gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); |
|||
|
|||
f = GET_PIXEL_FUNCTION(src); |
|||
|
|||
for ( y=0; y<src->sy; y++) { |
|||
for(x=0; x<src->sx; x++) { |
|||
new_r = new_g = new_b = 0; |
|||
new_a = gdImageAlpha(srcback, pxl); |
|||
|
|||
for (j=0; j<3; j++) { |
|||
int yv = MIN(MAX(y - 1 + j, 0), src->sy - 1); |
|||
for (i=0; i<3; i++) { |
|||
pxl = f(srcback, MIN(MAX(x - 1 + i, 0), src->sx - 1), yv); |
|||
new_r += (float)gdImageRed(srcback, pxl) * filter[j][i]; |
|||
new_g += (float)gdImageGreen(srcback, pxl) * filter[j][i]; |
|||
new_b += (float)gdImageBlue(srcback, pxl) * filter[j][i]; |
|||
} |
|||
} |
|||
|
|||
new_r = (new_r/filter_div)+offset; |
|||
new_g = (new_g/filter_div)+offset; |
|||
new_b = (new_b/filter_div)+offset; |
|||
|
|||
new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); |
|||
new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); |
|||
new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); |
|||
|
|||
new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); |
|||
if (new_pxl == -1) { |
|||
new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); |
|||
} |
|||
gdImageSetPixel (src, x, y, new_pxl); |
|||
} |
|||
} |
|||
gdImageDestroy(srcback); |
|||
return 1; |
|||
} |
|||
|
|||
int gdImageSelectiveBlur( gdImagePtr src) |
|||
{ |
|||
int x, y, i, j; |
|||
float new_r, new_g, new_b; |
|||
int new_pxl, cpxl, pxl, new_a=0; |
|||
float flt_r [3][3]; |
|||
float flt_g [3][3]; |
|||
float flt_b [3][3]; |
|||
float flt_r_sum, flt_g_sum, flt_b_sum; |
|||
|
|||
gdImagePtr srcback; |
|||
typedef int (*FuncPtr)(gdImagePtr, int, int); |
|||
FuncPtr f; |
|||
|
|||
if (src==NULL) { |
|||
return 0; |
|||
} |
|||
|
|||
/* We need the orinal image with each safe neoghb. pixel */ |
|||
srcback = gdImageCreateTrueColor (src->sx, src->sy); |
|||
if (srcback==NULL) { |
|||
return 0; |
|||
} |
|||
gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); |
|||
|
|||
f = GET_PIXEL_FUNCTION(src); |
|||
|
|||
for(y = 0; y<src->sy; y++) { |
|||
for (x=0; x<src->sx; x++) { |
|||
flt_r_sum = flt_g_sum = flt_b_sum = 0.0; |
|||
cpxl = f(src, x, y); |
|||
|
|||
for (j=0; j<3; j++) { |
|||
for (i=0; i<3; i++) { |
|||
if ((j == 1) && (i == 1)) { |
|||
flt_r[1][1] = flt_g[1][1] = flt_b[1][1] = 0.5; |
|||
} else { |
|||
pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); |
|||
new_a = gdImageAlpha(srcback, pxl); |
|||
|
|||
new_r = ((float)gdImageRed(srcback, cpxl)) - ((float)gdImageRed (srcback, pxl)); |
|||
|
|||
if (new_r < 0.0f) { |
|||
new_r = -new_r; |
|||
} |
|||
if (new_r != 0) { |
|||
flt_r[j][i] = 1.0f/new_r; |
|||
} else { |
|||
flt_r[j][i] = 1.0f; |
|||
} |
|||
|
|||
new_g = ((float)gdImageGreen(srcback, cpxl)) - ((float)gdImageGreen(srcback, pxl)); |
|||
|
|||
if (new_g < 0.0f) { |
|||
new_g = -new_g; |
|||
} |
|||
if (new_g != 0) { |
|||
flt_g[j][i] = 1.0f/new_g; |
|||
} else { |
|||
flt_g[j][i] = 1.0f; |
|||
} |
|||
|
|||
new_b = ((float)gdImageBlue(srcback, cpxl)) - ((float)gdImageBlue(srcback, pxl)); |
|||
|
|||
if (new_b < 0.0f) { |
|||
new_b = -new_b; |
|||
} |
|||
if (new_b != 0) { |
|||
flt_b[j][i] = 1.0f/new_b; |
|||
} else { |
|||
flt_b[j][i] = 1.0f; |
|||
} |
|||
} |
|||
|
|||
flt_r_sum += flt_r[j][i]; |
|||
flt_g_sum += flt_g[j][i]; |
|||
flt_b_sum += flt_b [j][i]; |
|||
} |
|||
} |
|||
|
|||
for (j=0; j<3; j++) { |
|||
for (i=0; i<3; i++) { |
|||
if (flt_r_sum != 0.0) { |
|||
flt_r[j][i] /= flt_r_sum; |
|||
} |
|||
if (flt_g_sum != 0.0) { |
|||
flt_g[j][i] /= flt_g_sum; |
|||
} |
|||
if (flt_b_sum != 0.0) { |
|||
flt_b [j][i] /= flt_b_sum; |
|||
} |
|||
} |
|||
} |
|||
|
|||
new_r = new_g = new_b = 0.0; |
|||
|
|||
for (j=0; j<3; j++) { |
|||
for (i=0; i<3; i++) { |
|||
pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); |
|||
new_r += (float)gdImageRed(srcback, pxl) * flt_r[j][i]; |
|||
new_g += (float)gdImageGreen(srcback, pxl) * flt_g[j][i]; |
|||
new_b += (float)gdImageBlue(srcback, pxl) * flt_b[j][i]; |
|||
} |
|||
} |
|||
|
|||
new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); |
|||
new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); |
|||
new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); |
|||
new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); |
|||
if (new_pxl == -1) { |
|||
new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); |
|||
} |
|||
gdImageSetPixel (src, x, y, new_pxl); |
|||
} |
|||
} |
|||
gdImageDestroy(srcback); |
|||
return 1; |
|||
} |
|||
|
|||
int gdImageEdgeDetectQuick(gdImagePtr src) |
|||
{ |
|||
float filter[3][3] = {{-1.0,0.0,-1.0}, |
|||
{0.0,4.0,0.0}, |
|||
{-1.0,0.0,-1.0}}; |
|||
|
|||
return gdImageConvolution(src, filter, 1, 127); |
|||
} |
|||
|
|||
int gdImageGaussianBlur(gdImagePtr im) |
|||
{ |
|||
float filter[3][3] = {{1.0,2.0,1.0}, |
|||
{2.0,4.0,2.0}, |
|||
{1.0,2.0,1.0}}; |
|||
|
|||
return gdImageConvolution(im, filter, 16, 0); |
|||
} |
|||
|
|||
int gdImageEmboss(gdImagePtr im) |
|||
{ |
|||
/* |
|||
float filter[3][3] = {{1.0,1.0,1.0}, |
|||
{0.0,0.0,0.0}, |
|||
{-1.0,-1.0,-1.0}}; |
|||
*/ |
|||
float filter[3][3] = {{ 1.5, 0.0, 0.0}, |
|||
{ 0.0, 0.0, 0.0}, |
|||
{ 0.0, 0.0,-1.5}}; |
|||
|
|||
return gdImageConvolution(im, filter, 1, 127); |
|||
} |
|||
|
|||
int gdImageMeanRemoval(gdImagePtr im) |
|||
{ |
|||
float filter[3][3] = {{-1.0,-1.0,-1.0}, |
|||
{-1.0,9.0,-1.0}, |
|||
{-1.0,-1.0,-1.0}}; |
|||
|
|||
return gdImageConvolution(im, filter, 1, 0); |
|||
} |
|||
|
|||
int gdImageSmooth(gdImagePtr im, float weight) |
|||
{ |
|||
float filter[3][3] = {{1.0,1.0,1.0}, |
|||
{1.0,0.0,1.0}, |
|||
{1.0,1.0,1.0}}; |
|||
|
|||
filter[1][1] = weight; |
|||
|
|||
return gdImageConvolution(im, filter, weight+8, 0); |
|||
} |
|||
/* End filters function */ |
|||
@ -0,0 +1,13 @@ |
|||
#ifndef GD_INTERN_H |
|||
#define GD_INTERN_H |
|||
#ifndef MIN |
|||
#define MIN(a,b) ((a)<(b)?(a):(b)) |
|||
#endif |
|||
#define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c))) |
|||
#ifndef MAX |
|||
#define MAX(a,b) ((a)<(b)?(b):(a)) |
|||
#endif |
|||
#define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c))) |
|||
|
|||
#endif |
|||
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue