diff options
author | wilson chen <willson.chenwx@gmail.com> | 2020-03-21 15:31:40 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-21 15:31:40 +0800 |
commit | 3f50ffaefdf8bf5ec5441afb4f032d32de8be7a4 (patch) | |
tree | d4c5bef5f21e24bd1cdc1257d02c82786518dde8 | |
parent | 08238a0ac2a309d1009ccfcf53f7e9908ae61881 (diff) | |
download | libgd-3f50ffaefdf8bf5ec5441afb4f032d32de8be7a4.tar.gz |
Fixed #596: gdTransformAffineCopy run error
And add test case for it.
-rw-r--r-- | src/gd_interpolation.c | 84 | ||||
-rw-r--r-- | src/gd_matrix.c | 2 | ||||
-rw-r--r-- | tests/gdimagerotate/php_bug_65070_exp.png | bin | 32722 -> 32699 bytes | |||
-rw-r--r-- | tests/gdtransformaffineboundingbox/github_bug_00221.c | 2 | ||||
-rw-r--r-- | tests/gdtransformaffinecopy/.gitignore | 1 | ||||
-rw-r--r-- | tests/gdtransformaffinecopy/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/gdtransformaffinecopy/Makemodule.am | 3 | ||||
-rw-r--r-- | tests/gdtransformaffinecopy/github_bug_00596.c | 42 |
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 Binary files differindex fba85f6..64b8b10 100644 --- a/tests/gdimagerotate/php_bug_65070_exp.png +++ b/tests/gdimagerotate/php_bug_65070_exp.png 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; +} |