summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwilson chen <willson.chenwx@gmail.com>2020-03-21 15:31:40 +0800
committerGitHub <noreply@github.com>2020-03-21 15:31:40 +0800
commit3f50ffaefdf8bf5ec5441afb4f032d32de8be7a4 (patch)
treed4c5bef5f21e24bd1cdc1257d02c82786518dde8
parent08238a0ac2a309d1009ccfcf53f7e9908ae61881 (diff)
downloadlibgd-3f50ffaefdf8bf5ec5441afb4f032d32de8be7a4.tar.gz
Fixed #596: gdTransformAffineCopy run error
And add test case for it.
-rw-r--r--src/gd_interpolation.c84
-rw-r--r--src/gd_matrix.c2
-rw-r--r--tests/gdimagerotate/php_bug_65070_exp.pngbin32722 -> 32699 bytes
-rw-r--r--tests/gdtransformaffineboundingbox/github_bug_00221.c2
-rw-r--r--tests/gdtransformaffinecopy/.gitignore1
-rw-r--r--tests/gdtransformaffinecopy/CMakeLists.txt1
-rw-r--r--tests/gdtransformaffinecopy/Makemodule.am3
-rw-r--r--tests/gdtransformaffinecopy/github_bug_00596.c42
8 files changed, 119 insertions, 16 deletions
diff --git a/src/gd_interpolation.c b/src/gd_interpolation.c
index 90d4a93..7d2ef57 100644
--- a/src/gd_interpolation.c
+++ b/src/gd_interpolation.c
@@ -1975,6 +1975,51 @@ BGD_DECLARE(int) gdTransformAffineGetImage(gdImagePtr *dst,
}
}
+/** Function: getPixelRgbInterpolated
+ * get the index of the image's colors
+ *
+ * Parameters:
+ * im - Image to draw the transformed image
+ * tcolor - TrueColor
+ *
+ * Return:
+ * index of colors
+ */
+static int getPixelRgbInterpolated(gdImagePtr im, const int tcolor)
+{
+ unsigned char r, g, b, a;
+ int ct;
+
+ b = (unsigned char)tcolor;
+ g = (unsigned char)tcolor >> 8;
+ r = (unsigned char)tcolor >> 16;
+ a = (unsigned char)tcolor >> 24;
+
+ b = CLAMP(b, 0, 255);
+ g = CLAMP(g, 0, 255);
+ r = CLAMP(r, 0, 255);
+ a = CLAMP(a, 0, 127);
+
+ for (int i = 0; i < im->colorsTotal; i++) {
+ if (im->red[i] == r && im->green[i] == g && im->blue[i] == b && im->alpha[i] == a) {
+ return i;
+ }
+ }
+
+ ct = im->colorsTotal;
+ if (ct == gdMaxColors) {
+ return -1;
+ }
+
+ im->colorsTotal++;
+ im->red[ct] = r;
+ im->green[ct] = g;
+ im->blue[ct] = b;
+ im->alpha[ct] = a;
+ im->open[ct] = 0;
+
+ return ct;
+}
/**
* Function: gdTransformAffineCopy
* Applies an affine transformation to a region and copy the result
@@ -2011,8 +2056,11 @@ BGD_DECLARE(int) gdTransformAffineCopy(gdImagePtr dst,
gdImageSetInterpolationMethod(src, GD_BICUBIC);
}
-
gdImageClipRectangle(src, src_region);
+ c1x = src_region->x;
+ c1y = src_region->y;
+ c2x = src_region->x + src_region->width -1;
+ c2y = src_region->y + src_region->height -1;
if (src_region->x > 0 || src_region->y > 0
|| src_region->width < gdImageSX(src)
@@ -2036,8 +2084,6 @@ BGD_DECLARE(int) gdTransformAffineCopy(gdImagePtr dst,
return GD_FALSE;
}
- gdImageGetClip(dst, &c1x, &c1y, &c2x, &c2y);
-
end_x = bbox.width + abs(bbox.x);
end_y = bbox.height + abs(bbox.y);
@@ -2053,18 +2099,24 @@ BGD_DECLARE(int) gdTransformAffineCopy(gdImagePtr dst,
if (dst->alphaBlendingFlag) {
for (y = bbox.y; y <= end_y; y++) {
pt.y = y + 0.5;
- for (x = 0; x <= end_x; x++) {
+ for (x = bbox.x; x <= end_x; x++) {
pt.x = x + 0.5;
gdAffineApplyToPointF(&src_pt, &pt, inv);
- gdImageSetPixel(dst, dst_x + x, dst_y + y, getPixelInterpolated(src, src_offset_x + src_pt.x, src_offset_y + src_pt.y, 0));
+ if (floor(src_offset_x + src_pt.x) < c1x
+ || floor(src_offset_x + src_pt.x) > c2x
+ || floor(src_offset_y + src_pt.y) < c1y
+ || floor(src_offset_y + src_pt.y) > c2y) {
+ continue;
+ }
+ gdImageSetPixel(dst, dst_x + x, dst_y + y, getPixelInterpolated(src, (int)(src_offset_x + src_pt.x), (int)(src_offset_y + src_pt.y), 0));
}
}
} else {
- for (y = 0; y <= end_y; y++) {
+ for (y = bbox.y; y <= end_y; y++) {
unsigned char *dst_p = NULL;
int *tdst_p = NULL;
- pt.y = y + 0.5 + bbox.y;
+ pt.y = y + 0.5;
if ((dst_y + y) < 0 || ((dst_y + y) > gdImageSY(dst) -1)) {
continue;
}
@@ -2074,17 +2126,23 @@ BGD_DECLARE(int) gdTransformAffineCopy(gdImagePtr dst,
dst_p = dst->pixels[dst_y + y] + dst_x;
}
- for (x = 0; x <= end_x; x++) {
- pt.x = x + 0.5 + bbox.x;
+ for (x = bbox.x; x <= end_x; x++) {
+ pt.x = x + 0.5;
gdAffineApplyToPointF(&src_pt, &pt, inv);
if ((dst_x + x) < 0 || (dst_x + x) > (gdImageSX(dst) - 1)) {
break;
}
+ if (floor(src_offset_x + src_pt.x) < c1x
+ || floor(src_offset_x + src_pt.x) > c2x
+ || floor(src_offset_y + src_pt.y) < c1y
+ || floor(src_offset_y + src_pt.y) > c2y) {
+ continue;
+ }
if (dst->trueColor) {
- *(tdst_p++) = getPixelInterpolated(src, src_offset_x + src_pt.x, src_offset_y + src_pt.y, -1);
+ *(tdst_p + dst_x + x) = getPixelInterpolated(src, (int)(src_offset_x + src_pt.x), (int)(src_offset_y + src_pt.y), -1);
} else {
- *(dst_p++) = getPixelInterpolated(src, src_offset_x + src_pt.x, src_offset_y + src_pt.y, -1);
+ *(dst_p + dst_x + x) = getPixelRgbInterpolated(dst, getPixelInterpolated(src, (int)(src_offset_x + src_pt.x), (int)(src_offset_y + src_pt.y), -1));
}
}
}
@@ -2148,8 +2206,8 @@ BGD_DECLARE(int) gdTransformAffineBoundingBox(gdRectPtr src, const double affine
}
bbox->x = (int) min.x;
bbox->y = (int) min.y;
- bbox->width = (int) ceil((max.x - min.x)) + 1;
- bbox->height = (int) ceil(max.y - min.y) + 1;
+ bbox->width = (int) ceil((max.x - min.x));
+ bbox->height = (int) ceil(max.y - min.y);
return GD_TRUE;
}
diff --git a/src/gd_matrix.c b/src/gd_matrix.c
index 7d3fe35..ada63e6 100644
--- a/src/gd_matrix.c
+++ b/src/gd_matrix.c
@@ -63,7 +63,7 @@ BGD_DECLARE(int) gdAffineInvert (double dst[6], const double src[6])
{
double r_det = (src[0] * src[3] - src[1] * src[2]);
- if (r_det <= 0.0) {
+ if (fabs(r_det) <= 0.0) {
return GD_FALSE;
}
diff --git a/tests/gdimagerotate/php_bug_65070_exp.png b/tests/gdimagerotate/php_bug_65070_exp.png
index fba85f6..64b8b10 100644
--- a/tests/gdimagerotate/php_bug_65070_exp.png
+++ b/tests/gdimagerotate/php_bug_65070_exp.png
Binary files differ
diff --git a/tests/gdtransformaffineboundingbox/github_bug_00221.c b/tests/gdtransformaffineboundingbox/github_bug_00221.c
index 4a50f73..9e75d0e 100644
--- a/tests/gdtransformaffineboundingbox/github_bug_00221.c
+++ b/tests/gdtransformaffineboundingbox/github_bug_00221.c
@@ -24,7 +24,7 @@ int main()
if (gdTransformAffineBoundingBox(&area, affine, &bbox) != GD_TRUE) {
return 1;
}
- if (!(bbox.x ==-253 && bbox.y ==-228 && bbox.width == 298 && bbox.height == 230)) {
+ if (!(bbox.x ==-253 && bbox.y ==-228 && bbox.width == 297 && bbox.height == 229)) {
return 1;
}
diff --git a/tests/gdtransformaffinecopy/.gitignore b/tests/gdtransformaffinecopy/.gitignore
index 85e7fa0..2af21d5 100644
--- a/tests/gdtransformaffinecopy/.gitignore
+++ b/tests/gdtransformaffinecopy/.gitignore
@@ -1,3 +1,4 @@
/github_bug_00583
/github_bug_00585
/github_bug_00586
+/github_bug_00596
diff --git a/tests/gdtransformaffinecopy/CMakeLists.txt b/tests/gdtransformaffinecopy/CMakeLists.txt
index f3475db..4af9fcc 100644
--- a/tests/gdtransformaffinecopy/CMakeLists.txt
+++ b/tests/gdtransformaffinecopy/CMakeLists.txt
@@ -2,6 +2,7 @@ LIST(APPEND TESTS_FILES
github_bug_00583
github_bug_00585
github_bug_00586
+ github_bug_00596
)
ADD_GD_TESTS()
diff --git a/tests/gdtransformaffinecopy/Makemodule.am b/tests/gdtransformaffinecopy/Makemodule.am
index 5541e8b..494ec80 100644
--- a/tests/gdtransformaffinecopy/Makemodule.am
+++ b/tests/gdtransformaffinecopy/Makemodule.am
@@ -1,7 +1,8 @@
libgd_test_programs += \
gdtransformaffinecopy/github_bug_00583 \
gdtransformaffinecopy/github_bug_00585 \
- gdtransformaffinecopy/github_bug_00586
+ gdtransformaffinecopy/github_bug_00586 \
+ gdtransformaffinecopy/github_bug_00596
EXTRA_DIST += \
gdtransformaffinecopy/CMakeLists.txt
diff --git a/tests/gdtransformaffinecopy/github_bug_00596.c b/tests/gdtransformaffinecopy/github_bug_00596.c
new file mode 100644
index 0000000..51912e1
--- /dev/null
+++ b/tests/gdtransformaffinecopy/github_bug_00596.c
@@ -0,0 +1,42 @@
+/**
+ * Test gdTransformAffineCopy() run error
+ *
+ * See <https://github.com/libgd/libgd/issues/596>
+ *
+ */
+
+#include "gd.h"
+#include "gdtest.h"
+
+int main()
+{
+ double matrix[] = {1, 0, 0, 1, 0, 0};
+ gdImagePtr src, dst;
+ gdRect rect = {0, 0, 16, 16};
+ int white, green;
+ int status = 0;
+ int res;
+ int actual_color = 0;
+ int expected_color = 0x00ff00;
+
+ src = gdImageCreateTrueColor(16, 16);
+ gdTestAssert(src != NULL);
+ white = gdImageColorAllocate(src, 255, 255, 255);
+ gdImageFilledRectangle(src, 0, 0, 16, 16, white);
+
+ dst = gdImageCreateTrueColor(50, 50);
+ gdTestAssert(dst != NULL);
+ green = gdImageColorAllocate(dst, 0, 255, 0);
+ gdImageFilledRectangle(dst, 0, 0, 50, 50, green);
+
+ res = gdTransformAffineCopy(dst, 4, 4, src, &rect, matrix);
+ gdTestAssert(res != GD_FALSE);
+
+ status = gdNumFailures();
+ actual_color = gdImageGetPixel(dst, 20, 5);
+ status = (actual_color == expected_color) ? status : 1;
+
+ gdImageDestroy(src);
+ gdImageDestroy(dst);
+ return status;
+}