2016-10-09 03:46:31 -07:00
|
|
|
/**
|
|
|
|
* File: Cropping
|
|
|
|
*
|
|
|
|
* Crop an image
|
|
|
|
*
|
|
|
|
* Some functions to crop images, automatically (auto detection of the border
|
|
|
|
* color), using a given color (with or without tolerance) or using a given
|
|
|
|
* rectangle.
|
2018-06-21 19:47:42 -07:00
|
|
|
*
|
2016-10-09 03:46:31 -07:00
|
|
|
* Example:
|
|
|
|
* (start code)
|
|
|
|
* im2 = gdImageAutoCrop(im, GD_CROP_SIDES);
|
|
|
|
* if (im2) {
|
|
|
|
* gdImageDestroy(im); // unless you need the original image subsequently
|
|
|
|
* // do something with the cropped image
|
|
|
|
* }
|
|
|
|
* gdImageDestroy(im2);
|
|
|
|
* (end code)
|
2007-12-12 07:56:03 -08:00
|
|
|
*/
|
|
|
|
|
2016-10-09 03:46:31 -07:00
|
|
|
|
2013-04-12 06:01:43 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2007-12-28 08:38:19 -08:00
|
|
|
#include <stdlib.h>
|
2008-08-31 09:57:18 -07:00
|
|
|
#include "gd.h"
|
2008-11-23 06:32:35 -08:00
|
|
|
#include "gd_color.h"
|
2007-12-12 07:56:03 -08:00
|
|
|
|
|
|
|
static int gdGuessBackgroundColorFromCorners(gdImagePtr im, int *color);
|
|
|
|
|
2016-10-09 03:46:31 -07:00
|
|
|
/**
|
|
|
|
* Function: gdImageCrop
|
|
|
|
*
|
|
|
|
* Crop an image to a given rectangle
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* src - The image.
|
|
|
|
* crop - The cropping rectangle, see <gdRect>.
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The newly created cropped image, or NULL on failure.
|
|
|
|
*
|
|
|
|
* See also:
|
|
|
|
* - <gdImageCropAuto>
|
|
|
|
* - <gdImageCropThreshold>
|
2016-07-20 12:13:38 -07:00
|
|
|
*/
|
2007-12-12 07:56:03 -08:00
|
|
|
BGD_DECLARE(gdImagePtr) gdImageCrop(gdImagePtr src, const gdRect *crop)
|
|
|
|
{
|
|
|
|
gdImagePtr dst;
|
2018-02-02 07:36:00 -08:00
|
|
|
int alphaBlendingFlag;
|
2007-12-12 07:56:03 -08:00
|
|
|
|
2016-09-11 07:17:49 -07:00
|
|
|
if (gdImageTrueColor(src)) {
|
|
|
|
dst = gdImageCreateTrueColor(crop->width, crop->height);
|
|
|
|
} else {
|
|
|
|
dst = gdImageCreate(crop->width, crop->height);
|
|
|
|
}
|
2009-03-04 03:55:18 -08:00
|
|
|
if (!dst) return NULL;
|
2018-02-02 07:36:00 -08:00
|
|
|
alphaBlendingFlag = dst->alphaBlendingFlag;
|
|
|
|
gdImageAlphaBlending(dst, gdEffectReplace);
|
2007-12-12 07:56:03 -08:00
|
|
|
gdImageCopy(dst, src, 0, 0, crop->x, crop->y, crop->width, crop->height);
|
2018-02-02 07:36:00 -08:00
|
|
|
gdImageAlphaBlending(dst, alphaBlendingFlag);
|
2007-12-12 07:56:03 -08:00
|
|
|
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
2016-10-09 03:46:31 -07:00
|
|
|
/**
|
|
|
|
* Function: gdImageCropAuto
|
|
|
|
*
|
|
|
|
* Crop an image automatically
|
|
|
|
*
|
|
|
|
* This function detects the cropping area according to the given _mode_.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* im - The image.
|
|
|
|
* mode - The cropping mode, see <gdCropMode>.
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The newly created cropped image, or NULL on failure.
|
|
|
|
*
|
|
|
|
* See also:
|
|
|
|
* - <gdImageCrop>
|
|
|
|
* - <gdImageCropThreshold>
|
2016-07-20 12:13:38 -07:00
|
|
|
*/
|
2013-04-04 07:45:58 -07:00
|
|
|
BGD_DECLARE(gdImagePtr) gdImageCropAuto(gdImagePtr im, const unsigned int mode)
|
2007-12-12 07:56:03 -08:00
|
|
|
{
|
|
|
|
const int width = gdImageSX(im);
|
|
|
|
const int height = gdImageSY(im);
|
|
|
|
|
|
|
|
int x,y;
|
2013-02-10 19:06:21 -08:00
|
|
|
int color, match;
|
2007-12-12 07:56:03 -08:00
|
|
|
gdRect crop;
|
|
|
|
|
|
|
|
crop.x = 0;
|
|
|
|
crop.y = 0;
|
|
|
|
crop.width = 0;
|
|
|
|
crop.height = 0;
|
|
|
|
|
|
|
|
switch (mode) {
|
2013-04-03 05:23:11 -07:00
|
|
|
case GD_CROP_TRANSPARENT:
|
|
|
|
color = gdImageGetTransparent(im);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GD_CROP_BLACK:
|
|
|
|
color = gdImageColorClosestAlpha(im, 0, 0, 0, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GD_CROP_WHITE:
|
|
|
|
color = gdImageColorClosestAlpha(im, 255, 255, 255, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GD_CROP_SIDES:
|
|
|
|
gdGuessBackgroundColorFromCorners(im, &color);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GD_CROP_DEFAULT:
|
|
|
|
default:
|
|
|
|
color = gdImageGetTransparent(im);
|
|
|
|
break;
|
2007-12-12 07:56:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Add gdImageGetRowPtr and works with ptr at the row level
|
|
|
|
* for the true color and palette images
|
|
|
|
* new formats will simply work with ptr
|
|
|
|
*/
|
|
|
|
match = 1;
|
|
|
|
for (y = 0; match && y < height; y++) {
|
|
|
|
for (x = 0; match && x < width; x++) {
|
|
|
|
match = (color == gdImageGetPixel(im, x,y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
/* Whole image would be cropped > bye */
|
|
|
|
if (match) {
|
2007-12-28 08:38:19 -08:00
|
|
|
return NULL;
|
2007-12-12 07:56:03 -08:00
|
|
|
}
|
|
|
|
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
crop.y = y - 1;
|
|
|
|
|
2007-12-12 07:56:03 -08:00
|
|
|
match = 1;
|
|
|
|
for (y = height - 1; match && y >= 0; y--) {
|
|
|
|
for (x = 0; match && x < width; x++) {
|
|
|
|
match = (color == gdImageGetPixel(im, x,y));
|
|
|
|
}
|
|
|
|
}
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
crop.height = y - crop.y + 2;
|
2007-12-12 07:56:03 -08:00
|
|
|
|
|
|
|
match = 1;
|
|
|
|
for (x = 0; match && x < width; x++) {
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
for (y = 0; match && y < crop.y + crop.height; y++) {
|
2007-12-12 07:56:03 -08:00
|
|
|
match = (color == gdImageGetPixel(im, x,y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
crop.x = x - 1;
|
|
|
|
|
|
|
|
match = 1;
|
|
|
|
for (x = width - 1; match && x >= 0; x--) {
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
for (y = 0; match && y < crop.y + crop.height; y++) {
|
2007-12-12 07:56:03 -08:00
|
|
|
match = (color == gdImageGetPixel(im, x,y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
crop.width = x - crop.x + 2;
|
|
|
|
|
|
|
|
return gdImageCrop(im, &crop);
|
|
|
|
}
|
|
|
|
|
2016-10-09 03:46:31 -07:00
|
|
|
/**
|
|
|
|
* Function: gdImageCropThreshold
|
|
|
|
*
|
|
|
|
* Crop an image using a given color
|
|
|
|
*
|
|
|
|
* The _threshold_ defines the tolerance to be used while comparing the image
|
|
|
|
* color and the color to crop. The method used to calculate the color
|
|
|
|
* difference is based on the color distance in the RGB(A) cube.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* im - The image.
|
|
|
|
* color - The crop color.
|
|
|
|
* threshold - The crop threshold.
|
2018-06-21 19:47:42 -07:00
|
|
|
*
|
2016-10-09 03:46:31 -07:00
|
|
|
* Returns:
|
|
|
|
* The newly created cropped image, or NULL on failure.
|
|
|
|
*
|
|
|
|
* See also:
|
|
|
|
* - <gdImageCrop>
|
|
|
|
* - <gdImageCropAuto>
|
2016-07-20 12:13:38 -07:00
|
|
|
*/
|
2013-04-04 07:45:58 -07:00
|
|
|
BGD_DECLARE(gdImagePtr) gdImageCropThreshold(gdImagePtr im, const unsigned int color, const float threshold)
|
2007-12-12 07:56:03 -08:00
|
|
|
{
|
|
|
|
const int width = gdImageSX(im);
|
|
|
|
const int height = gdImageSY(im);
|
|
|
|
|
|
|
|
int x,y;
|
2007-12-28 08:38:19 -08:00
|
|
|
int match;
|
2007-12-12 07:56:03 -08:00
|
|
|
gdRect crop;
|
|
|
|
|
|
|
|
crop.x = 0;
|
|
|
|
crop.y = 0;
|
|
|
|
crop.width = 0;
|
|
|
|
crop.height = 0;
|
|
|
|
|
2007-12-28 08:38:19 -08:00
|
|
|
/* Pierre: crop everything sounds bad */
|
2008-11-26 05:43:45 -08:00
|
|
|
if (threshold > 100.0) {
|
2007-12-28 08:38:19 -08:00
|
|
|
return NULL;
|
2007-12-12 07:56:03 -08:00
|
|
|
}
|
|
|
|
|
2016-07-20 02:40:17 -07:00
|
|
|
if (!gdImageTrueColor(im) && color >= gdImageColorsTotal(im)) {
|
2016-06-26 21:17:39 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-12-12 07:56:03 -08:00
|
|
|
/* TODO: Add gdImageGetRowPtr and works with ptr at the row level
|
|
|
|
* for the true color and palette images
|
|
|
|
* new formats will simply work with ptr
|
|
|
|
*/
|
|
|
|
match = 1;
|
|
|
|
for (y = 0; match && y < height; y++) {
|
|
|
|
for (x = 0; match && x < width; x++) {
|
|
|
|
match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
/* Whole image would be cropped > bye */
|
|
|
|
if (match) {
|
2007-12-28 08:38:19 -08:00
|
|
|
return NULL;
|
2007-12-12 07:56:03 -08:00
|
|
|
}
|
|
|
|
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
crop.y = y - 1;
|
|
|
|
|
2007-12-12 07:56:03 -08:00
|
|
|
match = 1;
|
|
|
|
for (y = height - 1; match && y >= 0; y--) {
|
|
|
|
for (x = 0; match && x < width; x++) {
|
|
|
|
match = (gdColorMatch(im, color, gdImageGetPixel(im, x, y), threshold)) > 0;
|
|
|
|
}
|
|
|
|
}
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
crop.height = y - crop.y + 2;
|
2007-12-12 07:56:03 -08:00
|
|
|
|
|
|
|
match = 1;
|
|
|
|
for (x = 0; match && x < width; x++) {
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
for (y = 0; match && y < crop.y + crop.height; y++) {
|
2007-12-12 07:56:03 -08:00
|
|
|
match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
crop.x = x - 1;
|
|
|
|
|
|
|
|
match = 1;
|
|
|
|
for (x = width - 1; match && x >= 0; x--) {
|
Fix #485: auto cropping has insufficient precision
After calculating the top crop amount, we bail out if the whole image
was going to be cropped away. The condition to check this
is off-by-one, though, since `y` would be equal to `height` in this
case. However, `y` would be equal to `height` also in case only the
last row of the image would have to be retained. We instead check for
`match` which indicates whether all pixels have the same color.
After calculating the bottom crop amount, we must never calculate the
`crop.height` based on the image height, since its irrelevant.
When calculating the left and right crop amount, we must not ignore the
last row of the image.
The partially identical implementation of `gdImageCropThreshold()` has
exactly the same issues, so we fix it as well.
Future scope for *improvements*:
- Replace the `match` flag with respective `goto`s (basically, `break
2`) is supposed to yield clearer code.
- Don't check the rows which will be top-cropped anyway, when
calculating the left and right crop amount, for efficiency.
- Join the implementations of calculating the crop rectangle of
`gdImageCropAuto()` and `gdImageCropThreshold()`.
2018-11-25 05:39:09 -08:00
|
|
|
for (y = 0; match && y < crop.y + crop.height; y++) {
|
2007-12-12 07:56:03 -08:00
|
|
|
match = (gdColorMatch(im, color, gdImageGetPixel(im, x,y), threshold)) > 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
crop.width = x - crop.x + 2;
|
|
|
|
|
|
|
|
return gdImageCrop(im, &crop);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This algorithm comes from pnmcrop (http://netpbm.sourceforge.net/)
|
|
|
|
* Three steps:
|
|
|
|
* - if 3 corners are equal.
|
|
|
|
* - if two are equal.
|
|
|
|
* - Last solution: average the colors
|
|
|
|
*/
|
|
|
|
static int gdGuessBackgroundColorFromCorners(gdImagePtr im, int *color)
|
|
|
|
{
|
|
|
|
const int tl = gdImageGetPixel(im, 0, 0);
|
|
|
|
const int tr = gdImageGetPixel(im, gdImageSX(im) - 1, 0);
|
|
|
|
const int bl = gdImageGetPixel(im, 0, gdImageSY(im) -1);
|
|
|
|
const int br = gdImageGetPixel(im, gdImageSX(im) - 1, gdImageSY(im) -1);
|
|
|
|
|
|
|
|
if (tr == bl && tr == br) {
|
|
|
|
*color = tr;
|
|
|
|
return 3;
|
|
|
|
} else if (tl == bl && tl == br) {
|
|
|
|
*color = tl;
|
|
|
|
return 3;
|
|
|
|
} else if (tl == tr && tl == br) {
|
|
|
|
*color = tl;
|
|
|
|
return 3;
|
|
|
|
} else if (tl == tr && tl == bl) {
|
|
|
|
*color = tl;
|
|
|
|
return 3;
|
|
|
|
} else if (tl == tr || tl == bl || tl == br) {
|
|
|
|
*color = tl;
|
|
|
|
return 2;
|
2018-11-25 08:58:41 -08:00
|
|
|
} else if (tr == bl || tr == br) {
|
2007-12-12 07:56:03 -08:00
|
|
|
*color = tr;
|
|
|
|
return 2;
|
|
|
|
} else if (br == bl) {
|
|
|
|
*color = bl;
|
|
|
|
return 2;
|
|
|
|
} else {
|
2008-01-13 13:11:35 -08:00
|
|
|
register int r,b,g,a;
|
2007-12-12 07:56:03 -08:00
|
|
|
|
2020-05-13 04:19:08 -07:00
|
|
|
r = (2 + gdImageRed(im, tl) + gdImageRed(im, tr) + gdImageRed(im, bl) + gdImageRed(im, br)) / 4;
|
|
|
|
g = (2 + gdImageGreen(im, tl) + gdImageGreen(im, tr) + gdImageGreen(im, bl) + gdImageGreen(im, br)) / 4;
|
|
|
|
b = (2 + gdImageBlue(im, tl) + gdImageBlue(im, tr) + gdImageBlue(im, bl) + gdImageBlue(im, br)) / 4;
|
|
|
|
a = (2 + gdImageAlpha(im, tl) + gdImageAlpha(im, tr) + gdImageAlpha(im, bl) + gdImageAlpha(im, br)) / 4;
|
2007-12-12 07:56:03 -08:00
|
|
|
*color = gdImageColorClosestAlpha(im, r, g, b, a);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|