|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* File: Image Filters
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
ed3af9 |
#include "config.h"
|
|
Packit |
ed3af9 |
#endif
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
#include "gd.h"
|
|
Packit |
ed3af9 |
#include "gdhelpers.h"
|
|
Packit |
ed3af9 |
#include "gd_intern.h"
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
#ifdef _WIN32
|
|
Packit |
ed3af9 |
# include <windows.h>
|
|
Packit |
ed3af9 |
#else
|
|
Packit |
ed3af9 |
# include <unistd.h>
|
|
Packit |
ed3af9 |
#endif
|
|
Packit |
ed3af9 |
#include <stdlib.h>
|
|
Packit |
ed3af9 |
#include <time.h>
|
|
Packit |
ed3af9 |
#include <math.h>
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
#undef NDEBUG
|
|
Packit |
ed3af9 |
/* Comment out this line to enable asserts.
|
|
Packit |
ed3af9 |
* TODO: This logic really belongs in cmake and configure.
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
#define NDEBUG 1
|
|
Packit |
ed3af9 |
#include <assert.h>
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
typedef int (BGD_STDCALL *FuncPtr)(gdImagePtr, int, int);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
#define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel)
|
|
Packit |
ed3af9 |
#define MIN(a,b) ((a)<(b)?(a):(b))
|
|
Packit |
ed3af9 |
#define MAX(a,b) ((a)<(b)?(b):(a))
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
#ifdef _WIN32
|
|
Packit |
ed3af9 |
# define GD_SCATTER_SEED() (unsigned int)(time(0) * GetCurrentProcessId())
|
|
Packit |
ed3af9 |
#else
|
|
Packit |
ed3af9 |
# define GD_SCATTER_SEED() (unsigned int)(time(0) * getpid())
|
|
Packit |
ed3af9 |
#endif
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
Function: gdImageScatter
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageScatter(gdImagePtr im, int sub, int plus)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
gdScatter s;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
s.sub = sub;
|
|
Packit |
ed3af9 |
s.plus = plus;
|
|
Packit |
ed3af9 |
s.num_colors = 0;
|
|
Packit |
ed3af9 |
s.seed = GD_SCATTER_SEED();
|
|
Packit |
ed3af9 |
return gdImageScatterEx(im, &s);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
Function: gdImageScatterColor
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageScatterColor(gdImagePtr im, int sub, int plus, int colors[], unsigned int num_colors)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
gdScatter s;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
s.sub = sub;
|
|
Packit |
ed3af9 |
s.plus = plus;
|
|
Packit |
ed3af9 |
s.colors = colors;
|
|
Packit |
ed3af9 |
s.num_colors = num_colors;
|
|
Packit |
ed3af9 |
s.seed = GD_SCATTER_SEED();
|
|
Packit |
ed3af9 |
return gdImageScatterEx(im, &s);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
Function: gdImageScatterEx
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageScatterEx(gdImagePtr im, gdScatterPtr scatter)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
register int x, y;
|
|
Packit |
ed3af9 |
int dest_x, dest_y;
|
|
Packit |
ed3af9 |
int pxl, new_pxl;
|
|
Packit |
ed3af9 |
unsigned int n;
|
|
Packit |
ed3af9 |
int sub = scatter->sub, plus = scatter->plus;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (plus == 0 && sub == 0) {
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
} else if (sub >= plus) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
(void)srand(scatter->seed);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (scatter->num_colors) {
|
|
Packit |
ed3af9 |
for (y = 0; y < im->sy; y++) {
|
|
Packit |
ed3af9 |
for (x = 0; x < im->sx; x++) {
|
|
Packit |
ed3af9 |
dest_x = (int) (x + ((rand() % (plus - sub)) + sub));
|
|
Packit |
ed3af9 |
dest_y = (int) (y + ((rand() % (plus - sub)) + sub));
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (!gdImageBoundsSafe(im, dest_x, dest_y)) {
|
|
Packit |
ed3af9 |
continue;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
pxl = gdImageGetPixel(im, x, y);
|
|
Packit |
ed3af9 |
new_pxl = gdImageGetPixel(im, dest_x, dest_y);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (n = 0; n < scatter->num_colors; n++) {
|
|
Packit |
ed3af9 |
if (pxl == scatter->colors[n]) {
|
|
Packit |
ed3af9 |
gdImageSetPixel(im, dest_x, dest_y, pxl);
|
|
Packit |
ed3af9 |
gdImageSetPixel(im, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
} else {
|
|
Packit |
ed3af9 |
for (y = 0; y < im->sy; y++) {
|
|
Packit |
ed3af9 |
for (x = 0; x < im->sx; x++) {
|
|
Packit |
ed3af9 |
dest_x = (int) (x + ((rand() % (plus - sub)) + sub));
|
|
Packit |
ed3af9 |
dest_y = (int) (y + ((rand() % (plus - sub)) + sub));
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (!gdImageBoundsSafe(im, dest_x, dest_y)) {
|
|
Packit |
ed3af9 |
continue;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
pxl = gdImageGetPixel(im, x, y);
|
|
Packit |
ed3af9 |
new_pxl = gdImageGetPixel(im, dest_x, dest_y);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
gdImageSetPixel(im, dest_x, dest_y, pxl);
|
|
Packit |
ed3af9 |
gdImageSetPixel(im, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
Function: gdImagePixelate
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (block_size <= 0) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
} else if (block_size == 1) {
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
switch (mode) {
|
|
Packit |
ed3af9 |
case GD_PIXELATE_UPPERLEFT:
|
|
Packit |
ed3af9 |
for (y = 0; y < im->sy; y += block_size) {
|
|
Packit |
ed3af9 |
for (x = 0; x < im->sx; x += block_size) {
|
|
Packit |
ed3af9 |
if (gdImageBoundsSafe(im, x, y)) {
|
|
Packit |
ed3af9 |
int c = gdImageGetPixel(im, x, y);
|
|
Packit |
ed3af9 |
gdImageFilledRectangle(im, x, y, x + block_size - 1, y + block_size - 1, c);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
break;
|
|
Packit |
ed3af9 |
case GD_PIXELATE_AVERAGE:
|
|
Packit |
ed3af9 |
for (y = 0; y < im->sy; y += block_size) {
|
|
Packit |
ed3af9 |
for (x = 0; x < im->sx; x += block_size) {
|
|
Packit |
ed3af9 |
int a, r, g, b, c;
|
|
Packit |
ed3af9 |
int total;
|
|
Packit |
ed3af9 |
int cx, cy;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
a = r = g = b = c = total = 0;
|
|
Packit |
ed3af9 |
/* sampling */
|
|
Packit |
ed3af9 |
for (cy = 0; cy < block_size; cy++) {
|
|
Packit |
ed3af9 |
for (cx = 0; cx < block_size; cx++) {
|
|
Packit |
ed3af9 |
if (!gdImageBoundsSafe(im, x + cx, y + cy)) {
|
|
Packit |
ed3af9 |
continue;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
c = gdImageGetPixel(im, x + cx, y + cy);
|
|
Packit |
ed3af9 |
a += gdImageAlpha(im, c);
|
|
Packit |
ed3af9 |
r += gdImageRed(im, c);
|
|
Packit |
ed3af9 |
g += gdImageGreen(im, c);
|
|
Packit |
ed3af9 |
b += gdImageBlue(im, c);
|
|
Packit |
ed3af9 |
total++;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
/* drawing */
|
|
Packit |
ed3af9 |
if (total > 0) {
|
|
Packit |
ed3af9 |
c = gdImageColorResolveAlpha(im, r / total, g / total, b / total, a / total);
|
|
Packit |
ed3af9 |
gdImageFilledRectangle(im, x, y, x + block_size - 1, y + block_size - 1, c);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
break;
|
|
Packit |
ed3af9 |
default:
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageNegate
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Invert an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* src - The image.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageNegate(gdImagePtr src)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y;
|
|
Packit |
ed3af9 |
int r,g,b,a;
|
|
Packit |
ed3af9 |
int new_pxl, pxl;
|
|
Packit |
ed3af9 |
FuncPtr f;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (src==NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
f = GET_PIXEL_FUNCTION(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (y=0; y<src->sy; ++y) {
|
|
Packit |
ed3af9 |
for (x=0; x<src->sx; ++x) {
|
|
Packit |
ed3af9 |
pxl = f (src, x, y);
|
|
Packit |
ed3af9 |
r = gdImageRed(src, pxl);
|
|
Packit |
ed3af9 |
g = gdImageGreen(src, pxl);
|
|
Packit |
ed3af9 |
b = gdImageBlue(src, pxl);
|
|
Packit |
ed3af9 |
a = gdImageAlpha(src, pxl);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(src, 255-r, 255-g, 255-b, a);
|
|
Packit |
ed3af9 |
if (new_pxl == -1) {
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorClosestAlpha(src, 255-r, 255-g, 255-b, a);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageSetPixel (src, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageGrayScale
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Convert an image to grayscale
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* The red, green and blue components of each pixel are replaced by their
|
|
Packit |
ed3af9 |
* weighted sum using the same coefficients as the REC.601 luma (Y')
|
|
Packit |
ed3af9 |
* calculation. The alpha components are retained.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* For palette images the result may differ due to palette limitations.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* src - The image.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageGrayScale(gdImagePtr src)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y;
|
|
Packit |
ed3af9 |
int r,g,b,a;
|
|
Packit |
ed3af9 |
int new_pxl, pxl;
|
|
Packit |
ed3af9 |
FuncPtr f;
|
|
Packit |
ed3af9 |
int alpha_blending;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (src==NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
alpha_blending = src->alphaBlendingFlag;
|
|
Packit |
ed3af9 |
gdImageAlphaBlending(src, gdEffectReplace);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
f = GET_PIXEL_FUNCTION(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (y=0; y<src->sy; ++y) {
|
|
Packit |
ed3af9 |
for (x=0; x<src->sx; ++x) {
|
|
Packit |
ed3af9 |
pxl = f (src, x, y);
|
|
Packit |
ed3af9 |
r = gdImageRed(src, pxl);
|
|
Packit |
ed3af9 |
g = gdImageGreen(src, pxl);
|
|
Packit |
ed3af9 |
b = gdImageBlue(src, pxl);
|
|
Packit |
ed3af9 |
a = gdImageAlpha(src, pxl);
|
|
Packit |
ed3af9 |
r = g = b = (int) (.299 * r + .587 * g + .114 * b);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a);
|
|
Packit |
ed3af9 |
if (new_pxl == -1) {
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorClosestAlpha(src, r, g, b, a);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageSetPixel (src, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageAlphaBlending(src, alpha_blending);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageBrightness
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Change the brightness of an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* src - The image.
|
|
Packit |
ed3af9 |
* brightness - The value to add to the color channels of all pixels.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageContrast>
|
|
Packit |
ed3af9 |
* - <gdImageColor>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageBrightness(gdImagePtr src, int brightness)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y;
|
|
Packit |
ed3af9 |
int r,g,b,a;
|
|
Packit |
ed3af9 |
int new_pxl, pxl;
|
|
Packit |
ed3af9 |
FuncPtr f;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (src==NULL || (brightness < -255 || brightness > 255)) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (brightness==0) {
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
f = GET_PIXEL_FUNCTION(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (y=0; y<src->sy; ++y) {
|
|
Packit |
ed3af9 |
for (x=0; x<src->sx; ++x) {
|
|
Packit |
ed3af9 |
pxl = f (src, x, y);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
r = gdImageRed(src, pxl);
|
|
Packit |
ed3af9 |
g = gdImageGreen(src, pxl);
|
|
Packit |
ed3af9 |
b = gdImageBlue(src, pxl);
|
|
Packit |
ed3af9 |
a = gdImageAlpha(src, pxl);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
r = r + brightness;
|
|
Packit |
ed3af9 |
g = g + brightness;
|
|
Packit |
ed3af9 |
b = b + brightness;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
r = (r > 255)? 255 : ((r < 0)? 0:r);
|
|
Packit |
ed3af9 |
g = (g > 255)? 255 : ((g < 0)? 0:g);
|
|
Packit |
ed3af9 |
b = (b > 255)? 255 : ((b < 0)? 0:b);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(src, (int)r, (int)g, (int)b, a);
|
|
Packit |
ed3af9 |
if (new_pxl == -1) {
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorClosestAlpha(src, (int)r, (int)g, (int)b, a);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageSetPixel (src, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageContrast
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Change the contrast of an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* src - The image.
|
|
Packit |
ed3af9 |
* contrast - The contrast adjustment value. Negative values increase, postive
|
|
Packit |
ed3af9 |
* values decrease the contrast. The larger the absolute value, the
|
|
Packit |
ed3af9 |
* stronger the effect.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageBrightness>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageContrast(gdImagePtr src, double contrast)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y;
|
|
Packit |
ed3af9 |
int r,g,b,a;
|
|
Packit |
ed3af9 |
double rf,gf,bf;
|
|
Packit |
ed3af9 |
int new_pxl, pxl;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
FuncPtr f;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (src==NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
f = GET_PIXEL_FUNCTION(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
contrast = (double)(100.0-contrast)/100.0;
|
|
Packit |
ed3af9 |
contrast = contrast*contrast;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (y=0; y<src->sy; ++y) {
|
|
Packit |
ed3af9 |
for (x=0; x<src->sx; ++x) {
|
|
Packit |
ed3af9 |
pxl = f(src, x, y);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
r = gdImageRed(src, pxl);
|
|
Packit |
ed3af9 |
g = gdImageGreen(src, pxl);
|
|
Packit |
ed3af9 |
b = gdImageBlue(src, pxl);
|
|
Packit |
ed3af9 |
a = gdImageAlpha(src, pxl);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
rf = (double)r/255.0;
|
|
Packit |
ed3af9 |
rf = rf-0.5;
|
|
Packit |
ed3af9 |
rf = rf*contrast;
|
|
Packit |
ed3af9 |
rf = rf+0.5;
|
|
Packit |
ed3af9 |
rf = rf*255.0;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
bf = (double)b/255.0;
|
|
Packit |
ed3af9 |
bf = bf-0.5;
|
|
Packit |
ed3af9 |
bf = bf*contrast;
|
|
Packit |
ed3af9 |
bf = bf+0.5;
|
|
Packit |
ed3af9 |
bf = bf*255.0;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
gf = (double)g/255.0;
|
|
Packit |
ed3af9 |
gf = gf-0.5;
|
|
Packit |
ed3af9 |
gf = gf*contrast;
|
|
Packit |
ed3af9 |
gf = gf+0.5;
|
|
Packit |
ed3af9 |
gf = gf*255.0;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
rf = (rf > 255.0)? 255.0 : ((rf < 0.0)? 0.0:rf);
|
|
Packit |
ed3af9 |
gf = (gf > 255.0)? 255.0 : ((gf < 0.0)? 0.0:gf);
|
|
Packit |
ed3af9 |
bf = (bf > 255.0)? 255.0 : ((bf < 0.0)? 0.0:bf);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(src, (int)rf, (int)gf, (int)bf, a);
|
|
Packit |
ed3af9 |
if (new_pxl == -1) {
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorClosestAlpha(src, (int)rf, (int)gf, (int)bf, a);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageSetPixel (src, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageColor
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Change channel values of an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* src - The image.
|
|
Packit |
ed3af9 |
* red - The value to add to the red channel of all pixels.
|
|
Packit |
ed3af9 |
* green - The value to add to the green channel of all pixels.
|
|
Packit |
ed3af9 |
* blue - The value to add to the blue channel of all pixels.
|
|
Packit |
ed3af9 |
* alpha - The value to add to the alpha channel of all pixels.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageBrightness>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y;
|
|
Packit |
ed3af9 |
int new_pxl, pxl;
|
|
Packit |
ed3af9 |
FuncPtr f;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (src == NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
f = GET_PIXEL_FUNCTION(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (y=0; y<src->sy; ++y) {
|
|
Packit |
ed3af9 |
for (x=0; x<src->sx; ++x) {
|
|
Packit |
ed3af9 |
int r,g,b,a;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
pxl = f(src, x, y);
|
|
Packit |
ed3af9 |
r = gdImageRed(src, pxl);
|
|
Packit |
ed3af9 |
g = gdImageGreen(src, pxl);
|
|
Packit |
ed3af9 |
b = gdImageBlue(src, pxl);
|
|
Packit |
ed3af9 |
a = gdImageAlpha(src, pxl);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
r = r + red;
|
|
Packit |
ed3af9 |
g = g + green;
|
|
Packit |
ed3af9 |
b = b + blue;
|
|
Packit |
ed3af9 |
a = a + alpha;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
r = (r > 255)? 255 : ((r < 0)? 0 : r);
|
|
Packit |
ed3af9 |
g = (g > 255)? 255 : ((g < 0)? 0 : g);
|
|
Packit |
ed3af9 |
b = (b > 255)? 255 : ((b < 0)? 0 : b);
|
|
Packit |
ed3af9 |
a = (a > 127)? 127 : ((a < 0)? 0 : a);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a);
|
|
Packit |
ed3af9 |
if (new_pxl == -1) {
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorClosestAlpha(src, r, g, b, a);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageSetPixel (src, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageConvolution
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Apply a convolution matrix to an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Depending on the matrix a wide range of effects can be accomplished, e.g.
|
|
Packit |
ed3af9 |
* blurring, sharpening, embossing and edge detection.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* src - The image.
|
|
Packit |
ed3af9 |
* filter - The 3x3 convolution matrix.
|
|
Packit |
ed3af9 |
* filter_div - The value to divide the convoluted channel values by.
|
|
Packit |
ed3af9 |
* offset - The value to add to the convoluted channel values.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageEdgeDetectQuick>
|
|
Packit |
ed3af9 |
* - <gdImageGaussianBlur>
|
|
Packit |
ed3af9 |
* - <gdImageEmboss>
|
|
Packit |
ed3af9 |
* - <gdImageMeanRemoval>
|
|
Packit |
ed3af9 |
* - <gdImageSmooth>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y, i, j, new_a;
|
|
Packit |
ed3af9 |
float new_r, new_g, new_b;
|
|
Packit |
ed3af9 |
int new_pxl, pxl=0;
|
|
Packit |
ed3af9 |
gdImagePtr srcback;
|
|
Packit |
ed3af9 |
FuncPtr f;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (src==NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* We need the orinal image with each safe neoghb. pixel */
|
|
Packit |
ed3af9 |
srcback = gdImageCreateTrueColor (src->sx, src->sy);
|
|
Packit |
ed3af9 |
if (srcback==NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
gdImageSaveAlpha(srcback, 1);
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(srcback, 0, 0, 0, 127);
|
|
Packit |
ed3af9 |
gdImageFill(srcback, 0, 0, new_pxl);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
f = GET_PIXEL_FUNCTION(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for ( y=0; y<src->sy; y++) {
|
|
Packit |
ed3af9 |
for(x=0; x<src->sx; x++) {
|
|
Packit |
ed3af9 |
new_r = new_g = new_b = 0;
|
|
Packit |
ed3af9 |
new_a = gdImageAlpha(srcback, pxl);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (j=0; j<3; j++) {
|
|
Packit |
ed3af9 |
int yv = MIN(MAX(y - 1 + j, 0), src->sy - 1);
|
|
Packit |
ed3af9 |
for (i=0; i<3; i++) {
|
|
Packit |
ed3af9 |
pxl = f(srcback, MIN(MAX(x - 1 + i, 0), src->sx - 1), yv);
|
|
Packit |
ed3af9 |
new_r += (float)gdImageRed(srcback, pxl) * filter[j][i];
|
|
Packit |
ed3af9 |
new_g += (float)gdImageGreen(srcback, pxl) * filter[j][i];
|
|
Packit |
ed3af9 |
new_b += (float)gdImageBlue(srcback, pxl) * filter[j][i];
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_r = (new_r/filter_div)+offset;
|
|
Packit |
ed3af9 |
new_g = (new_g/filter_div)+offset;
|
|
Packit |
ed3af9 |
new_b = (new_b/filter_div)+offset;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r);
|
|
Packit |
ed3af9 |
new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g);
|
|
Packit |
ed3af9 |
new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
|
|
Packit |
ed3af9 |
if (new_pxl == -1) {
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageSetPixel (src, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageDestroy(srcback);
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
Function: gdImageSelectiveBlur
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageSelectiveBlur( gdImagePtr src)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int x, y, i, j;
|
|
Packit |
ed3af9 |
float new_r, new_g, new_b;
|
|
Packit |
ed3af9 |
int new_pxl, cpxl, pxl, new_a=0;
|
|
Packit |
ed3af9 |
float flt_r [3][3];
|
|
Packit |
ed3af9 |
float flt_g [3][3];
|
|
Packit |
ed3af9 |
float flt_b [3][3];
|
|
Packit |
ed3af9 |
float flt_r_sum, flt_g_sum, flt_b_sum;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
gdImagePtr srcback;
|
|
Packit |
ed3af9 |
FuncPtr f;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (src==NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* We need the orinal image with each safe neoghb. pixel */
|
|
Packit |
ed3af9 |
srcback = gdImageCreateTrueColor (src->sx, src->sy);
|
|
Packit |
ed3af9 |
if (srcback==NULL) {
|
|
Packit |
ed3af9 |
return 0;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
f = GET_PIXEL_FUNCTION(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for(y = 0; y<src->sy; y++) {
|
|
Packit |
ed3af9 |
for (x=0; x<src->sx; x++) {
|
|
Packit |
ed3af9 |
flt_r_sum = flt_g_sum = flt_b_sum = 0.0;
|
|
Packit |
ed3af9 |
cpxl = f(src, x, y);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (j=0; j<3; j++) {
|
|
Packit |
ed3af9 |
for (i=0; i<3; i++) {
|
|
Packit |
ed3af9 |
if ((j == 1) && (i == 1)) {
|
|
Packit |
ed3af9 |
flt_r[1][1] = flt_g[1][1] = flt_b[1][1] = 0.5;
|
|
Packit |
ed3af9 |
} else {
|
|
Packit |
ed3af9 |
pxl = f(src, x-(3>>1)+i, y-(3>>1)+j);
|
|
Packit |
ed3af9 |
new_a = gdImageAlpha(srcback, pxl);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_r = ((float)gdImageRed(srcback, cpxl)) - ((float)gdImageRed (srcback, pxl));
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (new_r < 0.0f) {
|
|
Packit |
ed3af9 |
new_r = -new_r;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
if (new_r != 0) {
|
|
Packit |
ed3af9 |
flt_r[j][i] = 1.0f/new_r;
|
|
Packit |
ed3af9 |
} else {
|
|
Packit |
ed3af9 |
flt_r[j][i] = 1.0f;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_g = ((float)gdImageGreen(srcback, cpxl)) - ((float)gdImageGreen(srcback, pxl));
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (new_g < 0.0f) {
|
|
Packit |
ed3af9 |
new_g = -new_g;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
if (new_g != 0) {
|
|
Packit |
ed3af9 |
flt_g[j][i] = 1.0f/new_g;
|
|
Packit |
ed3af9 |
} else {
|
|
Packit |
ed3af9 |
flt_g[j][i] = 1.0f;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_b = ((float)gdImageBlue(srcback, cpxl)) - ((float)gdImageBlue(srcback, pxl));
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (new_b < 0.0f) {
|
|
Packit |
ed3af9 |
new_b = -new_b;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
if (new_b != 0) {
|
|
Packit |
ed3af9 |
flt_b[j][i] = 1.0f/new_b;
|
|
Packit |
ed3af9 |
} else {
|
|
Packit |
ed3af9 |
flt_b[j][i] = 1.0f;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
flt_r_sum += flt_r[j][i];
|
|
Packit |
ed3af9 |
flt_g_sum += flt_g[j][i];
|
|
Packit |
ed3af9 |
flt_b_sum += flt_b [j][i];
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (j=0; j<3; j++) {
|
|
Packit |
ed3af9 |
for (i=0; i<3; i++) {
|
|
Packit |
ed3af9 |
if (flt_r_sum != 0.0) {
|
|
Packit |
ed3af9 |
flt_r[j][i] /= flt_r_sum;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
if (flt_g_sum != 0.0) {
|
|
Packit |
ed3af9 |
flt_g[j][i] /= flt_g_sum;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
if (flt_b_sum != 0.0) {
|
|
Packit |
ed3af9 |
flt_b [j][i] /= flt_b_sum;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_r = new_g = new_b = 0.0;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (j=0; j<3; j++) {
|
|
Packit |
ed3af9 |
for (i=0; i<3; i++) {
|
|
Packit |
ed3af9 |
pxl = f(src, x-(3>>1)+i, y-(3>>1)+j);
|
|
Packit |
ed3af9 |
new_r += (float)gdImageRed(srcback, pxl) * flt_r[j][i];
|
|
Packit |
ed3af9 |
new_g += (float)gdImageGreen(srcback, pxl) * flt_g[j][i];
|
|
Packit |
ed3af9 |
new_b += (float)gdImageBlue(srcback, pxl) * flt_b[j][i];
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r);
|
|
Packit |
ed3af9 |
new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g);
|
|
Packit |
ed3af9 |
new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b);
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
|
|
Packit |
ed3af9 |
if (new_pxl == -1) {
|
|
Packit |
ed3af9 |
new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageSetPixel (src, x, y, new_pxl);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
gdImageDestroy(srcback);
|
|
Packit |
ed3af9 |
return 1;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageEdgeDetectQuick
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Edge detection of an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* (see edge_detect_quick.jpg)
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* src - The image.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageMeanRemoval>
|
|
Packit |
ed3af9 |
* - <gdImageConvolution>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageEdgeDetectQuick(gdImagePtr src)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
float filter[3][3] = {{-1.0,0.0,-1.0},
|
|
Packit |
ed3af9 |
{0.0,4.0,0.0},
|
|
Packit |
ed3af9 |
{-1.0,0.0,-1.0}};
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return gdImageConvolution(src, filter, 1, 127);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
Function: gdImageGaussianBlur
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
<gdImageGaussianBlur> performs a Gaussian blur of radius 1 on the
|
|
Packit |
ed3af9 |
image. The image is modified in place.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
*NOTE:* You will almost certain want to use
|
|
Packit |
ed3af9 |
<gdImageCopyGaussianBlurred> instead, as it allows you to change
|
|
Packit |
ed3af9 |
your kernel size and sigma value. Future versions of this
|
|
Packit |
ed3af9 |
function may fall back to calling it instead of
|
|
Packit |
ed3af9 |
<gdImageConvolution>, causing subtle changes so be warned.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Parameters:
|
|
Packit |
ed3af9 |
im - The image to blur
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Returns:
|
|
Packit |
ed3af9 |
GD_TRUE (1) on success, GD_FALSE (0) on failure.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageGaussianBlur(gdImagePtr im)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
float filter[3][3] = {
|
|
Packit |
ed3af9 |
{1.0, 2.0, 1.0},
|
|
Packit |
ed3af9 |
{2.0, 4.0, 2.0},
|
|
Packit |
ed3af9 |
{1.0, 2.0, 1.0}
|
|
Packit |
ed3af9 |
};
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return gdImageConvolution(im, filter, 16, 0);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageEmboss
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Emboss an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* (see emboss.jpg)
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* im - The image.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageConvolution>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageEmboss(gdImagePtr im)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
float filter[3][3] = {{1.0,1.0,1.0},
|
|
Packit |
ed3af9 |
{0.0,0.0,0.0},
|
|
Packit |
ed3af9 |
{-1.0,-1.0,-1.0}};
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
float filter[3][3] = {{ 1.5, 0.0, 0.0},
|
|
Packit |
ed3af9 |
{ 0.0, 0.0, 0.0},
|
|
Packit |
ed3af9 |
{ 0.0, 0.0,-1.5}};
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return gdImageConvolution(im, filter, 1, 127);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageMeanRemoval
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Mean removal of an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* (see mean_removal.jpg)
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* im - The image.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageEdgeDetectQuick>
|
|
Packit |
ed3af9 |
* - <gdImageConvolution>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageMeanRemoval(gdImagePtr im)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
float filter[3][3] = {{-1.0,-1.0,-1.0},
|
|
Packit |
ed3af9 |
{-1.0,9.0,-1.0},
|
|
Packit |
ed3af9 |
{-1.0,-1.0,-1.0}};
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return gdImageConvolution(im, filter, 1, 0);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/**
|
|
Packit |
ed3af9 |
* Function: gdImageSmooth
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Smooth an image
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* (see smooth.jpg)
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Parameters:
|
|
Packit |
ed3af9 |
* im - The image.
|
|
Packit |
ed3af9 |
* weight - The strength of the smoothing.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* Returns:
|
|
Packit |
ed3af9 |
* Non-zero on success, zero on failure.
|
|
Packit |
ed3af9 |
*
|
|
Packit |
ed3af9 |
* See also:
|
|
Packit |
ed3af9 |
* - <gdImageConvolution>
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
BGD_DECLARE(int) gdImageSmooth(gdImagePtr im, float weight)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
float filter[3][3] = {{1.0,1.0,1.0},
|
|
Packit |
ed3af9 |
{1.0,0.0,1.0},
|
|
Packit |
ed3af9 |
{1.0,1.0,1.0}};
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
filter[1][1] = weight;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return gdImageConvolution(im, filter, weight+8, 0);
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* ======================== Gaussian Blur Code ======================== */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* Return an array of coefficients for 'radius' and 'sigma' (sigma >=
|
|
Packit |
ed3af9 |
* 0 means compute it). Result length is 2*radius+1. */
|
|
Packit |
ed3af9 |
static double *
|
|
Packit |
ed3af9 |
gaussian_coeffs(int radius, double sigmaArg) {
|
|
Packit |
ed3af9 |
const double sigma = (sigmaArg <= 0.0) ? (2.0/3.0)*radius : sigmaArg;
|
|
Packit |
ed3af9 |
const double s = 2.0 * sigma * sigma;
|
|
Packit |
ed3af9 |
double *result;
|
|
Packit |
ed3af9 |
double sum = 0;
|
|
Packit |
ed3af9 |
int x, n, count;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
count = 2*radius + 1;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
result = gdMalloc(sizeof(double) * count);
|
|
Packit |
ed3af9 |
if (!result) {
|
|
Packit |
ed3af9 |
return NULL;
|
|
Packit |
ed3af9 |
}/* if */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (x = -radius; x <= radius; x++) {
|
|
Packit |
ed3af9 |
double coeff = exp(-(x*x)/s);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
sum += coeff;
|
|
Packit |
ed3af9 |
result[x + radius] = coeff;
|
|
Packit |
ed3af9 |
}/* for */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (n = 0; n < count; n++) {
|
|
Packit |
ed3af9 |
result[n] /= sum;
|
|
Packit |
ed3af9 |
}/* for */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return result;
|
|
Packit |
ed3af9 |
}/* gaussian_coeffs*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
static inline int
|
|
Packit |
ed3af9 |
reflect(int max, int x)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
assert(x > -max && x < 2*max);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if(x < 0) return -x;
|
|
Packit |
ed3af9 |
if(x >= max) return max - (x - max) - 1;
|
|
Packit |
ed3af9 |
return x;
|
|
Packit |
ed3af9 |
}/* reflect*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
static inline void
|
|
Packit |
ed3af9 |
applyCoeffsLine(gdImagePtr src, gdImagePtr dst, int line, int linelen,
|
|
Packit |
ed3af9 |
double *coeffs, int radius, gdAxis axis)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int ndx;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (ndx = 0; ndx < linelen; ndx++) {
|
|
Packit |
ed3af9 |
double r = 0, g = 0, b = 0, a = 0;
|
|
Packit |
ed3af9 |
int cndx;
|
|
Packit |
ed3af9 |
int *dest = (axis == HORIZONTAL) ?
|
|
Packit |
ed3af9 |
&dst->tpixels[line][ndx] :
|
|
Packit |
ed3af9 |
&dst->tpixels[ndx][line];
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (cndx = -radius; cndx <= radius; cndx++) {
|
|
Packit |
ed3af9 |
const double coeff = coeffs[cndx + radius];
|
|
Packit |
ed3af9 |
const int rndx = reflect(linelen, ndx + cndx);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
const int srcpx = (axis == HORIZONTAL) ?
|
|
Packit |
ed3af9 |
src->tpixels[line][rndx] :
|
|
Packit |
ed3af9 |
src->tpixels[rndx][line];
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
r += coeff * (double)gdTrueColorGetRed(srcpx);
|
|
Packit |
ed3af9 |
g += coeff * (double)gdTrueColorGetGreen(srcpx);
|
|
Packit |
ed3af9 |
b += coeff * (double)gdTrueColorGetBlue(srcpx);
|
|
Packit |
ed3af9 |
a += coeff * (double)gdTrueColorGetAlpha(srcpx);
|
|
Packit |
ed3af9 |
}/* for */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
*dest = gdTrueColorAlpha(uchar_clamp(r, 0xFF), uchar_clamp(g, 0xFF),
|
|
Packit |
ed3af9 |
uchar_clamp(b, 0xFF), uchar_clamp(a, 0x7F));
|
|
Packit |
ed3af9 |
}/* for */
|
|
Packit |
ed3af9 |
}/* applyCoeffsLine*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
static void
|
|
Packit |
ed3af9 |
applyCoeffs(gdImagePtr src, gdImagePtr dst, double *coeffs, int radius,
|
|
Packit |
ed3af9 |
gdAxis axis)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
int line, numlines, linelen;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (axis == HORIZONTAL) {
|
|
Packit |
ed3af9 |
numlines = src->sy;
|
|
Packit |
ed3af9 |
linelen = src->sx;
|
|
Packit |
ed3af9 |
} else {
|
|
Packit |
ed3af9 |
numlines = src->sx;
|
|
Packit |
ed3af9 |
linelen = src->sy;
|
|
Packit |
ed3af9 |
}/* if .. else*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
for (line = 0; line < numlines; line++) {
|
|
Packit |
ed3af9 |
applyCoeffsLine(src, dst, line, linelen, coeffs, radius, axis);
|
|
Packit |
ed3af9 |
}/* for */
|
|
Packit |
ed3af9 |
}/* applyCoeffs*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/*
|
|
Packit |
ed3af9 |
Function: gdImageCopyGaussianBlurred
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Return a copy of the source image _src_ blurred according to the
|
|
Packit |
ed3af9 |
parameters using the Gaussian Blur algorithm.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
_radius_ is a radius, not a diameter so a radius of 2 (for
|
|
Packit |
ed3af9 |
example) will blur across a region 5 pixels across (2 to the
|
|
Packit |
ed3af9 |
center, 1 for the center itself and another 2 to the other edge).
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
_sigma_ represents the "fatness" of the curve (lower == fatter).
|
|
Packit |
ed3af9 |
If _sigma_ is less than or equal to 0,
|
|
Packit |
ed3af9 |
<gdImageCopyGaussianBlurred> ignores it and instead computes an
|
|
Packit |
ed3af9 |
"optimal" value. Be warned that future versions of this function
|
|
Packit |
ed3af9 |
may compute sigma differently.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
The resulting image is always truecolor.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
More Details:
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
A Gaussian Blur is generated by replacing each pixel's color
|
|
Packit |
ed3af9 |
values with the average of the surrounding pixels' colors. This
|
|
Packit |
ed3af9 |
region is a circle whose radius is given by argument _radius_.
|
|
Packit |
ed3af9 |
Thus, a larger radius will yield a blurrier image.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
This average is not a simple mean of the values. Instead, values
|
|
Packit |
ed3af9 |
are weighted using the Gaussian function (roughly a bell curve
|
|
Packit |
ed3af9 |
centered around the destination pixel) giving it much more
|
|
Packit |
ed3af9 |
influence on the result than its neighbours. Thus, a fatter curve
|
|
Packit |
ed3af9 |
will give the center pixel more weight and make the image less
|
|
Packit |
ed3af9 |
blurry; lower _sigma_ values will yield flatter curves.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Currently, <gdImageCopyGaussianBlurred> computes the default sigma
|
|
Packit |
ed3af9 |
as
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
(2/3)*radius
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Note, however that we reserve the right to change this if we find
|
|
Packit |
ed3af9 |
a better ratio. If you absolutely need the current sigma value,
|
|
Packit |
ed3af9 |
you should set it yourself.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Parameters:
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
src - the source image
|
|
Packit |
ed3af9 |
radius - the blur radius (*not* diameter--range is 2*radius + 1)
|
|
Packit |
ed3af9 |
sigma - the sigma value or a value <= 0.0 to use the computed default
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Returns:
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
The new image or NULL if an error occurred. The result is always
|
|
Packit |
ed3af9 |
truecolor.
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
Example:
|
|
Packit |
ed3af9 |
(start code)
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
FILE *in;
|
|
Packit |
ed3af9 |
gdImagePtr result, src;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
in = fopen("foo.png", "rb");
|
|
Packit |
ed3af9 |
src = gdImageCreateFromPng(in);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
result = gdImageCopyGaussianBlurred(im, src->sx / 10, -1.0);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
(end code)
|
|
Packit |
ed3af9 |
*/
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* TODO: Look into turning this into a generic seperable filter
|
|
Packit |
ed3af9 |
* function with Gaussian Blur being one special case. (At the
|
|
Packit |
ed3af9 |
* moment, I can't find any other useful separable filter so for not,
|
|
Packit |
ed3af9 |
* it's just blur.) */
|
|
Packit |
ed3af9 |
BGD_DECLARE(gdImagePtr)
|
|
Packit |
ed3af9 |
gdImageCopyGaussianBlurred(gdImagePtr src, int radius, double sigma)
|
|
Packit |
ed3af9 |
{
|
|
Packit |
ed3af9 |
gdImagePtr tmp = NULL, result = NULL;
|
|
Packit |
ed3af9 |
double *coeffs;
|
|
Packit |
ed3af9 |
int freeSrc = 0;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (radius < 1) {
|
|
Packit |
ed3af9 |
return NULL;
|
|
Packit |
ed3af9 |
}/* if */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* Compute the coefficients. */
|
|
Packit |
ed3af9 |
coeffs = gaussian_coeffs(radius, sigma);
|
|
Packit |
ed3af9 |
if (!coeffs) {
|
|
Packit |
ed3af9 |
return NULL;
|
|
Packit |
ed3af9 |
}/* if */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* If the image is not truecolor, we first make a truecolor
|
|
Packit |
ed3af9 |
* scratch copy. */
|
|
Packit |
ed3af9 |
if (!src->trueColor) {
|
|
Packit |
ed3af9 |
int tcstat;
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
src = gdImageClone(src);
|
|
Packit |
ed3af9 |
if (!src) {
|
|
Packit |
ed3af9 |
gdFree(coeffs);
|
|
Packit |
ed3af9 |
return NULL;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
tcstat = gdImagePaletteToTrueColor(src);
|
|
Packit |
ed3af9 |
if (!tcstat) {
|
|
Packit |
ed3af9 |
gdImageDestroy(src);
|
|
Packit |
ed3af9 |
gdFree(coeffs);
|
|
Packit |
ed3af9 |
return NULL;
|
|
Packit |
ed3af9 |
}/* if */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
freeSrc = 1;
|
|
Packit |
ed3af9 |
}/* if */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* Apply the filter horizontally. */
|
|
Packit |
ed3af9 |
tmp = gdImageCreateTrueColor(src->sx, src->sy);
|
|
Packit |
ed3af9 |
if (!tmp) {
|
|
Packit |
ed3af9 |
gdFree(coeffs);
|
|
Packit |
ed3af9 |
return NULL;
|
|
Packit |
ed3af9 |
}
|
|
Packit |
ed3af9 |
applyCoeffs(src, tmp, coeffs, radius, HORIZONTAL);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
/* Apply the filter vertically. */
|
|
Packit |
ed3af9 |
result = gdImageCreateTrueColor(src->sx, src->sy);
|
|
Packit |
ed3af9 |
if (result) {
|
|
Packit |
ed3af9 |
applyCoeffs(tmp, result, coeffs, radius, VERTICAL);
|
|
Packit |
ed3af9 |
}/* if */
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
gdImageDestroy(tmp);
|
|
Packit |
ed3af9 |
gdFree(coeffs);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
if (freeSrc) gdImageDestroy(src);
|
|
Packit |
ed3af9 |
|
|
Packit |
ed3af9 |
return result;
|
|
Packit |
ed3af9 |
}/* gdImageCopyGaussianBlurred*/
|
|
Packit |
ed3af9 |
|