|
Packit Service |
df60bb |
/**
|
|
Packit Service |
df60bb |
* File: Cropping
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Crop an image
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Some functions to crop images, automatically (auto detection of the border
|
|
Packit Service |
df60bb |
* color), using a given color (with or without tolerance) or using a given
|
|
Packit Service |
df60bb |
* rectangle.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Example:
|
|
Packit Service |
df60bb |
* (start code)
|
|
Packit Service |
df60bb |
* im2 = gdImageAutoCrop(im, GD_CROP_SIDES);
|
|
Packit Service |
df60bb |
* if (im2) {
|
|
Packit Service |
df60bb |
* gdImageDestroy(im); // unless you need the original image subsequently
|
|
Packit Service |
df60bb |
* // do something with the cropped image
|
|
Packit Service |
df60bb |
* }
|
|
Packit Service |
df60bb |
* gdImageDestroy(im2);
|
|
Packit Service |
df60bb |
* (end code)
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
df60bb |
#include "config.h"
|
|
Packit Service |
df60bb |
#endif
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
#include <stdlib.h>
|
|
Packit Service |
df60bb |
#include "gd.h"
|
|
Packit Service |
df60bb |
#include "gd_color.h"
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
static int gdGuessBackgroundColorFromCorners(gdImagePtr im, int *color);
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/**
|
|
Packit Service |
df60bb |
* Function: gdImageCrop
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Crop an image to a given rectangle
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Parameters:
|
|
Packit Service |
df60bb |
* src - The image.
|
|
Packit Service |
df60bb |
* crop - The cropping rectangle, see <gdRect>.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Returns:
|
|
Packit Service |
df60bb |
* The newly created cropped image, or NULL on failure.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* See also:
|
|
Packit Service |
df60bb |
* - <gdImageCropAuto>
|
|
Packit Service |
df60bb |
* - <gdImageCropThreshold>
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
BGD_DECLARE(gdImagePtr) gdImageCrop(gdImagePtr src, const gdRect *crop)
|
|
Packit Service |
df60bb |
{
|
|
Packit Service |
df60bb |
gdImagePtr dst;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
if (gdImageTrueColor(src)) {
|
|
Packit Service |
df60bb |
dst = gdImageCreateTrueColor(crop->width, crop->height);
|
|
Packit Service |
df60bb |
} else {
|
|
Packit Service |
df60bb |
dst = gdImageCreate(crop->width, crop->height);
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
if (!dst) return NULL;
|
|
Packit Service |
df60bb |
gdImageCopy(dst, src, 0, 0, crop->x, crop->y, crop->width, crop->height);
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
return dst;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/**
|
|
Packit Service |
df60bb |
* Function: gdImageCropAuto
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Crop an image automatically
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* This function detects the cropping area according to the given _mode_.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Parameters:
|
|
Packit Service |
df60bb |
* im - The image.
|
|
Packit Service |
df60bb |
* mode - The cropping mode, see <gdCropMode>.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Returns:
|
|
Packit Service |
df60bb |
* The newly created cropped image, or NULL on failure.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* See also:
|
|
Packit Service |
df60bb |
* - <gdImageCrop>
|
|
Packit Service |
df60bb |
* - <gdImageCropThreshold>
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
BGD_DECLARE(gdImagePtr) gdImageCropAuto(gdImagePtr im, const unsigned int mode)
|
|
Packit Service |
df60bb |
{
|
|
Packit Service |
df60bb |
const int width = gdImageSX(im);
|
|
Packit Service |
df60bb |
const int height = gdImageSY(im);
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
int x,y;
|
|
Packit Service |
df60bb |
int color, match;
|
|
Packit Service |
df60bb |
gdRect crop;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
crop.x = 0;
|
|
Packit Service |
df60bb |
crop.y = 0;
|
|
Packit Service |
df60bb |
crop.width = 0;
|
|
Packit Service |
df60bb |
crop.height = 0;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
switch (mode) {
|
|
Packit Service |
df60bb |
case GD_CROP_TRANSPARENT:
|
|
Packit Service |
df60bb |
color = gdImageGetTransparent(im);
|
|
Packit Service |
df60bb |
break;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
case GD_CROP_BLACK:
|
|
Packit Service |
df60bb |
color = gdImageColorClosestAlpha(im, 0, 0, 0, 0);
|
|
Packit Service |
df60bb |
break;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
case GD_CROP_WHITE:
|
|
Packit Service |
df60bb |
color = gdImageColorClosestAlpha(im, 255, 255, 255, 0);
|
|
Packit Service |
df60bb |
break;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
case GD_CROP_SIDES:
|
|
Packit Service |
df60bb |
gdGuessBackgroundColorFromCorners(im, &color;;
|
|
Packit Service |
df60bb |
break;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
case GD_CROP_DEFAULT:
|
|
Packit Service |
df60bb |
default:
|
|
Packit Service |
df60bb |
color = gdImageGetTransparent(im);
|
|
Packit Service |
df60bb |
break;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/* TODO: Add gdImageGetRowPtr and works with ptr at the row level
|
|
Packit Service |
df60bb |
* for the true color and palette images
|
|
Packit Service |
df60bb |
* new formats will simply work with ptr
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (y = 0; match && y < height; y++) {
|
|
Packit Service |
df60bb |
for (x = 0; match && x < width; x++) {
|
|
Packit Service |
df60bb |
match = (color == gdImageGetPixel(im, x,y));
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/* Nothing to do > bye
|
|
Packit Service |
df60bb |
* Duplicate the image?
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
if (y == height - 1) {
|
|
Packit Service |
df60bb |
return NULL;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
crop.y = y -1;
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (y = height - 1; match && y >= 0; y--) {
|
|
Packit Service |
df60bb |
for (x = 0; match && x < width; x++) {
|
|
Packit Service |
df60bb |
match = (color == gdImageGetPixel(im, x,y));
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
if (y == 0) {
|
|
Packit Service |
df60bb |
crop.height = height - crop.y + 1;
|
|
Packit Service |
df60bb |
} else {
|
|
Packit Service |
df60bb |
crop.height = y - crop.y + 2;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (x = 0; match && x < width; x++) {
|
|
Packit Service |
df60bb |
for (y = 0; match && y < crop.y + crop.height - 1; y++) {
|
|
Packit Service |
df60bb |
match = (color == gdImageGetPixel(im, x,y));
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
crop.x = x - 1;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (x = width - 1; match && x >= 0; x--) {
|
|
Packit Service |
df60bb |
for (y = 0; match && y < crop.y + crop.height - 1; y++) {
|
|
Packit Service |
df60bb |
match = (color == gdImageGetPixel(im, x,y));
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
crop.width = x - crop.x + 2;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
return gdImageCrop(im, &crop;;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/**
|
|
Packit Service |
df60bb |
* Function: gdImageCropThreshold
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Crop an image using a given color
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* The _threshold_ defines the tolerance to be used while comparing the image
|
|
Packit Service |
df60bb |
* color and the color to crop. The method used to calculate the color
|
|
Packit Service |
df60bb |
* difference is based on the color distance in the RGB(A) cube.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Parameters:
|
|
Packit Service |
df60bb |
* im - The image.
|
|
Packit Service |
df60bb |
* color - The crop color.
|
|
Packit Service |
df60bb |
* threshold - The crop threshold.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* Returns:
|
|
Packit Service |
df60bb |
* The newly created cropped image, or NULL on failure.
|
|
Packit Service |
df60bb |
*
|
|
Packit Service |
df60bb |
* See also:
|
|
Packit Service |
df60bb |
* - <gdImageCrop>
|
|
Packit Service |
df60bb |
* - <gdImageCropAuto>
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
BGD_DECLARE(gdImagePtr) gdImageCropThreshold(gdImagePtr im, const unsigned int color, const float threshold)
|
|
Packit Service |
df60bb |
{
|
|
Packit Service |
df60bb |
const int width = gdImageSX(im);
|
|
Packit Service |
df60bb |
const int height = gdImageSY(im);
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
int x,y;
|
|
Packit Service |
df60bb |
int match;
|
|
Packit Service |
df60bb |
gdRect crop;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
crop.x = 0;
|
|
Packit Service |
df60bb |
crop.y = 0;
|
|
Packit Service |
df60bb |
crop.width = 0;
|
|
Packit Service |
df60bb |
crop.height = 0;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/* Pierre: crop everything sounds bad */
|
|
Packit Service |
df60bb |
if (threshold > 100.0) {
|
|
Packit Service |
df60bb |
return NULL;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
if (!gdImageTrueColor(im) && color >= gdImageColorsTotal(im)) {
|
|
Packit Service |
df60bb |
return NULL;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/* TODO: Add gdImageGetRowPtr and works with ptr at the row level
|
|
Packit Service |
df60bb |
* for the true color and palette images
|
|
Packit Service |
df60bb |
* new formats will simply work with ptr
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (y = 0; match && y < height; y++) {
|
|
Packit Service |
df60bb |
for (x = 0; match && x < width; x++) {
|
|
Packit Service |
df60bb |
match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/* Pierre
|
|
Packit Service |
df60bb |
* Nothing to do > bye
|
|
Packit Service |
df60bb |
* Duplicate the image?
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
if (y == height - 1) {
|
|
Packit Service |
df60bb |
return NULL;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
crop.y = y -1;
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (y = height - 1; match && y >= 0; y--) {
|
|
Packit Service |
df60bb |
for (x = 0; match && x < width; x++) {
|
|
Packit Service |
df60bb |
match = (gdColorMatch(im, color, gdImageGetPixel(im, x, y), threshold)) > 0;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
if (y == 0) {
|
|
Packit Service |
df60bb |
crop.height = height - crop.y + 1;
|
|
Packit Service |
df60bb |
} else {
|
|
Packit Service |
df60bb |
crop.height = y - crop.y + 2;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (x = 0; match && x < width; x++) {
|
|
Packit Service |
df60bb |
for (y = 0; match && y < crop.y + crop.height - 1; y++) {
|
|
Packit Service |
df60bb |
match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
crop.x = x - 1;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
match = 1;
|
|
Packit Service |
df60bb |
for (x = width - 1; match && x >= 0; x--) {
|
|
Packit Service |
df60bb |
for (y = 0; match && y < crop.y + crop.height - 1; y++) {
|
|
Packit Service |
df60bb |
match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
crop.width = x - crop.x + 2;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
return gdImageCrop(im, &crop;;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
/* This algorithm comes from pnmcrop (http://netpbm.sourceforge.net/)
|
|
Packit Service |
df60bb |
* Three steps:
|
|
Packit Service |
df60bb |
* - if 3 corners are equal.
|
|
Packit Service |
df60bb |
* - if two are equal.
|
|
Packit Service |
df60bb |
* - Last solution: average the colors
|
|
Packit Service |
df60bb |
*/
|
|
Packit Service |
df60bb |
static int gdGuessBackgroundColorFromCorners(gdImagePtr im, int *color)
|
|
Packit Service |
df60bb |
{
|
|
Packit Service |
df60bb |
const int tl = gdImageGetPixel(im, 0, 0);
|
|
Packit Service |
df60bb |
const int tr = gdImageGetPixel(im, gdImageSX(im) - 1, 0);
|
|
Packit Service |
df60bb |
const int bl = gdImageGetPixel(im, 0, gdImageSY(im) -1);
|
|
Packit Service |
df60bb |
const int br = gdImageGetPixel(im, gdImageSX(im) - 1, gdImageSY(im) -1);
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
if (tr == bl && tr == br) {
|
|
Packit Service |
df60bb |
*color = tr;
|
|
Packit Service |
df60bb |
return 3;
|
|
Packit Service |
df60bb |
} else if (tl == bl && tl == br) {
|
|
Packit Service |
df60bb |
*color = tl;
|
|
Packit Service |
df60bb |
return 3;
|
|
Packit Service |
df60bb |
} else if (tl == tr && tl == br) {
|
|
Packit Service |
df60bb |
*color = tl;
|
|
Packit Service |
df60bb |
return 3;
|
|
Packit Service |
df60bb |
} else if (tl == tr && tl == bl) {
|
|
Packit Service |
df60bb |
*color = tl;
|
|
Packit Service |
df60bb |
return 3;
|
|
Packit Service |
df60bb |
} else if (tl == tr || tl == bl || tl == br) {
|
|
Packit Service |
df60bb |
*color = tl;
|
|
Packit Service |
df60bb |
return 2;
|
|
Packit Service |
df60bb |
} else if (tr == bl) {
|
|
Packit Service |
df60bb |
*color = tr;
|
|
Packit Service |
df60bb |
return 2;
|
|
Packit Service |
df60bb |
} else if (br == bl) {
|
|
Packit Service |
df60bb |
*color = bl;
|
|
Packit Service |
df60bb |
return 2;
|
|
Packit Service |
df60bb |
} else {
|
|
Packit Service |
df60bb |
register int r,b,g,a;
|
|
Packit Service |
df60bb |
|
|
Packit Service |
df60bb |
r = (int)(0.5f + (gdImageRed(im, tl) + gdImageRed(im, tr) + gdImageRed(im, bl) + gdImageRed(im, br)) / 4);
|
|
Packit Service |
df60bb |
g = (int)(0.5f + (gdImageGreen(im, tl) + gdImageGreen(im, tr) + gdImageGreen(im, bl) + gdImageGreen(im, br)) / 4);
|
|
Packit Service |
df60bb |
b = (int)(0.5f + (gdImageBlue(im, tl) + gdImageBlue(im, tr) + gdImageBlue(im, bl) + gdImageBlue(im, br)) / 4);
|
|
Packit Service |
df60bb |
a = (int)(0.5f + (gdImageAlpha(im, tl) + gdImageAlpha(im, tr) + gdImageAlpha(im, bl) + gdImageAlpha(im, br)) / 4);
|
|
Packit Service |
df60bb |
*color = gdImageColorClosestAlpha(im, r, g, b, a);
|
|
Packit Service |
df60bb |
return 0;
|
|
Packit Service |
df60bb |
}
|
|
Packit Service |
df60bb |
}
|