summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Joye <pierre.php@gmail.com>2013-04-05 01:05:36 +0200
committerPierre Joye <pierre.php@gmail.com>2013-04-05 01:05:36 +0200
commitd8e19af742615f3071d5c001c25fe6155e911271 (patch)
tree224686dfac43e63ee90a143c868cea1e33adc7e6
parent0c21e2cfc1391d1ef564f0cfd8bdec02899c3666 (diff)
downloadlibgd-d8e19af742615f3071d5c001c25fe6155e911271.tar.gz
backport php's gd filter
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/gd.h26
-rw-r--r--src/gd_filter.c459
-rw-r--r--src/gd_rotate.c12
5 files changed, 484 insertions, 17 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 405a6f7..b8f0b75 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -163,7 +163,7 @@ else (USE_EXT_GD)
if (WIN32)
SET(GD_LIB bgd)
- ADD_DEFINITIONS( -DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32 -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600)
+ ADD_DEFINITIONS( -DWIN32 -D_WIN32 -DBGDWIN32 -DMSWIN32 -DBGDWIN32 -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600)
if(NOT MINGW AND MSVC_VERSION GREATER 1399)
ADD_DEFINITIONS("/D_CRT_SECURE_NO_DEPRECATE")
@@ -191,7 +191,6 @@ endif (USE_EXT_GD)
add_subdirectory(tests)
add_subdirectory(examples)
-
SET(CPACK_PACKAGE_NAME "libgd")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "libGD, powerful and easy to use graphic library")
SET(CPACK_PACKAGE_VENDOR "http://www.libgd.org")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ae09d33..bd1c4b8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -69,6 +69,7 @@ add_library(${GD_LIB_STATIC} STATIC ${LIBGD_SRC_FILES})
if (WIN32 AND NOT MINGW AND NOT MSYS)
# SET_TARGET_PROPERTIES(${GD_LIB} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:msvcrt.lib")
+SET_PROPERTY(TARGET ${GD_LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS NONDLL=1)
ENDIF(WIN32 AND NOT MINGW AND NOT MSYS)
if (MINGW OR MSYS)
diff --git a/src/gd.h b/src/gd.h
index b5cef0b..11f0180 100644
--- a/src/gd.h
+++ b/src/gd.h
@@ -30,14 +30,13 @@ extern "C" {
#endif /* WIN32 */
#ifdef NONDLL
-#define BGD_DECLARE(rt) extern rt
+# define BGD_DECLARE(rt) extern rt
#else
-#ifdef BGDWIN32
-
-#define BGD_DECLARE(rt) __declspec(dllexport) rt __stdcall
-#else
-#define BGD_DECLARE(rt) __declspec(dllimport) rt _stdcall
-#endif /* BGDWIN32 */
+# ifdef BGDWIN32
+# define BGD_DECLARE(rt) __declspec(dllexport) rt __stdcall
+# else
+# define BGD_DECLARE(rt) __declspec(dllimport) rt _stdcall
+# endif /* BGDWIN32 */
#endif /* NONDLL */
/* 2.0.20: for actual storage of exported data, functions don't need this,
@@ -907,6 +906,19 @@ typedef struct {
BGD_DECLARE(int) gdImageScatter(gdImagePtr im, int sub, int plus);
BGD_DECLARE(int) gdImageScatterColor(gdImagePtr im, int sub, int plus, int colors[], unsigned int num_colors);
BGD_DECLARE(int) gdImageScatterEx(gdImagePtr im, gdScatterPtr s);
+BGD_DECLARE(int) gdImageSmooth(gdImagePtr im, float weight);
+BGD_DECLARE(int) gdImageMeanRemoval(gdImagePtr im);
+BGD_DECLARE(int) gdImageEmboss(gdImagePtr im);
+BGD_DECLARE(int) gdImageGaussianBlur(gdImagePtr im);
+BGD_DECLARE(int) gdImageEdgeDetectQuick(gdImagePtr src);
+BGD_DECLARE(int) gdImageSelectiveBlur( gdImagePtr src);
+BGD_DECLARE(int) gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset);
+BGD_DECLARE(int) gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha);
+BGD_DECLARE(int) gdImageContrast(gdImagePtr src, double contrast);
+BGD_DECLARE(int) gdImageBrightness(gdImagePtr src, int brightness);
+BGD_DECLARE(int) gdImageGrayScale(gdImagePtr src);
+BGD_DECLARE(int) gdImageNegate(gdImagePtr src);
+
/* Macros to access information about images. */
diff --git a/src/gd_filter.c b/src/gd_filter.c
index 14a3c62..f306551 100644
--- a/src/gd_filter.c
+++ b/src/gd_filter.c
@@ -8,6 +8,25 @@
#include <stdlib.h>
#include <time.h>
+#ifdef NONDLL
+typedef int (*FuncPtr)(gdImagePtr, int, int);
+#else
+# ifdef BGDWIN32
+//typedef int (__stdcall *FuncPtr)(gdImagePtr, int, int);
+typedef int (__stdcall *FuncPtr)(gdImagePtr, int, int);
+/*
+#define BGD_DECLARE(rt) __declspec(dllexport) rt __stdcall
+*/
+# else
+typedef int (__stdcall *FuncPtr)(gdImagePtr, int, int);
+/* #define BGD_DECLARE(rt) __declspec(dllimport) rt _stdcall */
+# endif /* BGDWIN32 */
+#endif /* NONDLL */
+
+#define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel)
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)<(b)?(b):(a))
+
#ifdef WIN32
# define GD_SCATTER_SEED() (unsigned int)(time(0) * GetCurrentProcessId())
#else
@@ -95,3 +114,443 @@ BGD_DECLARE(int) gdImageScatterEx(gdImagePtr im, gdScatterPtr scatter)
return 1;
}
+
+/* invert src image */
+BGD_DECLARE(int) gdImageNegate(gdImagePtr src)
+{
+ int x, y;
+ int r,g,b,a;
+ int new_pxl, pxl;
+ 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 */
+BGD_DECLARE(int) gdImageGrayScale(gdImagePtr src)
+{
+ int x, y;
+ int r,g,b,a;
+ int new_pxl, pxl;
+ 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 */
+BGD_DECLARE(int) gdImageBrightness(gdImagePtr src, int brightness)
+{
+ int x, y;
+ int r,g,b,a;
+ int new_pxl, pxl;
+ 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;
+}
+
+
+BGD_DECLARE(int) gdImageContrast(gdImagePtr src, double contrast)
+{
+ int x, y;
+ int r,g,b,a;
+ double rf,gf,bf;
+ int new_pxl, pxl;
+
+ 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;
+}
+
+
+BGD_DECLARE(int) gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha)
+{
+ int x, y;
+ int new_pxl, pxl;
+ 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;
+}
+
+BGD_DECLARE(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;
+ 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;
+}
+
+BGD_DECLARE(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;
+ 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;
+}
+
+BGD_DECLARE(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);
+}
+
+BGD_DECLARE(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);
+}
+
+BGD_DECLARE(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);
+}
+
+BGD_DECLARE(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);
+}
+
+BGD_DECLARE(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);
+}
diff --git a/src/gd_rotate.c b/src/gd_rotate.c
index fd6bc8e..0add1b4 100644
--- a/src/gd_rotate.c
+++ b/src/gd_rotate.c
@@ -17,17 +17,13 @@
#endif /* ROTATE_PI */
#ifdef NONDLL
-#define BGD_DECLARE(rt) extern rt
+# define BGD_DECLARE(rt) extern rt
#else
-#ifdef BGDWIN32
+# ifdef BGDWIN32
typedef int (__stdcall *FuncPtr)(gdImagePtr, int, int);
-/*
-#define BGD_DECLARE(rt) __declspec(dllexport) rt __stdcall
-*/
-#else
+# else
typedef int (__stdcall *FuncPtr)(gdImagePtr, int, int);
-/* #define BGD_DECLARE(rt) __declspec(dllimport) rt _stdcall */
-#endif /* BGDWIN32 */
+# endif /* BGDWIN32 */
#endif /* NONDLL */
#define ROTATE_DEG2RAD 3.1415926535897932384626433832795/180