Last active
April 16, 2016 10:07
-
-
Save pierrejoye/59d72385ed1888cf8894a7ed437235ae to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c | |
index a06e333..d93bcdb 100644 | |
--- a/ext/gd/libgd/gd_interpolation.c | |
+++ b/ext/gd/libgd/gd_interpolation.c | |
@@ -1662,13 +1662,28 @@ gdImagePtr gdImageScale(const gdImagePtr src, const unsigned int new_width, cons | |
return im_scaled; | |
} | |
+int gdRotatedImageSize(gdImagePtr src, const float angle, gdRectPtr bbox) | |
+{ | |
+ gdRect src_area; | |
+ double m[6]; | |
+ | |
+ gdAffineRotate(m, angle); | |
+ src_area.x = 0; | |
+ src_area.y = 0; | |
+ src_area.width = gdImageSX(src); | |
+ src_area.height = gdImageSY(src); | |
+ if (gdTransformAffineBoundingBox(&src_area, m, bbox) != GD_TRUE) { | |
+ return GD_FALSE; | |
+ } | |
+ return GD_TRUE; | |
+} | |
+ | |
gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, const int bgColor) | |
{ | |
float _angle = ((float) (-degrees / 180.0f) * (float)M_PI); | |
const int src_w = gdImageSX(src); | |
const int src_h = gdImageSY(src); | |
- const unsigned int new_width = (unsigned int)(abs((int)(src_w * cos(_angle))) + abs((int)(src_h * sin(_angle))) + 0.5f); | |
- const unsigned int new_height = (unsigned int)(abs((int)(src_w * sin(_angle))) + abs((int)(src_h * cos(_angle))) + 0.5f); | |
+ unsigned int new_width, new_height; | |
const gdFixed f_0_5 = gd_ftofx(0.5f); | |
const gdFixed f_H = gd_itofx(src_h/2); | |
const gdFixed f_W = gd_itofx(src_w/2); | |
@@ -1679,7 +1694,11 @@ gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, co | |
unsigned int dst_offset_y = 0; | |
unsigned int i; | |
gdImagePtr dst; | |
+ gdRect bbox; | |
+ gdRotatedImageSize(src, degrees, &bbox); | |
+ new_width = bbox.width; | |
+ new_height = bbox.height; | |
dst = gdImageCreateTrueColor(new_width, new_height); | |
if (!dst) { | |
return NULL; | |
@@ -1717,8 +1736,7 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b | |
const int angle_rounded = (int)floor(degrees * 100); | |
const int src_w = gdImageSX(src); | |
const int src_h = gdImageSY(src); | |
- const unsigned int new_width = (unsigned int)(abs((int)(src_w * cos(_angle))) + abs((int)(src_h * sin(_angle))) + 0.5f); | |
- const unsigned int new_height = (unsigned int)(abs((int)(src_w * sin(_angle))) + abs((int)(src_h * cos(_angle))) + 0.5f); | |
+ unsigned int new_width, new_height; | |
const gdFixed f_0_5 = gd_ftofx(0.5f); | |
const gdFixed f_H = gd_itofx(src_h/2); | |
const gdFixed f_W = gd_itofx(src_w/2); | |
@@ -1735,12 +1753,15 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b | |
const gdFixed f_slop = f_slop_x > 0 && f_slop_x > 0 ? | |
f_slop_x > f_slop_y ? gd_divfx(f_slop_y, f_slop_x) : gd_divfx(f_slop_x, f_slop_y) | |
: 0; | |
- | |
+ gdRect bbox; | |
if (bgColor < 0) { | |
return NULL; | |
} | |
+ gdRotatedImageSize(src, degrees, &bbox); | |
+ new_width = bbox.width; | |
+ new_height = bbox.height; | |
dst = gdImageCreateTrueColor(new_width, new_height); | |
if (!dst) { | |
return NULL; | |
@@ -1780,8 +1801,7 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int | |
float _angle = (float)((- degrees / 180.0f) * M_PI); | |
const unsigned int src_w = gdImageSX(src); | |
const unsigned int src_h = gdImageSY(src); | |
- unsigned int new_width = abs((int)(src_w*cos(_angle))) + abs((int)(src_h*sin(_angle) + 0.5f)); | |
- unsigned int new_height = abs((int)(src_w*sin(_angle))) + abs((int)(src_h*cos(_angle) + 0.5f)); | |
+ unsigned int new_width, new_height; | |
const gdFixed f_0_5 = gd_ftofx(0.5f); | |
const gdFixed f_H = gd_itofx(src_h/2); | |
const gdFixed f_W = gd_itofx(src_w/2); | |
@@ -1793,8 +1813,15 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int | |
unsigned int dst_offset_y = 0; | |
unsigned int src_offset_x, src_offset_y; | |
gdImagePtr dst; | |
+ gdRect bbox; | |
+ | |
+ gdRotatedImageSize(src, degrees, &bbox); | |
+ | |
+ new_width = bbox.width; | |
+ new_height = bbox.height; | |
dst = gdImageCreateTrueColor(new_width, new_height); | |
+ | |
if (dst == NULL) { | |
return NULL; | |
} | |
@@ -1812,7 +1839,7 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int | |
const unsigned int m = gd_fxtoi(f_m); | |
const unsigned int n = gd_fxtoi(f_n); | |
- if ((m > 0) && (m < src_h - 1) && (n > 0) && (n < src_w - 1)) { | |
+ if ((m >= 0) && (m < src_h - 1) && (n >= 0) && (n < src_w - 1)) { | |
const gdFixed f_f = f_m - gd_itofx(m); | |
const gdFixed f_g = f_n - gd_itofx(n); | |
const gdFixed f_w1 = gd_mulfx(f_1-f_f, f_1-f_g); | |
@@ -1820,11 +1847,6 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int | |
const gdFixed f_w3 = gd_mulfx(f_f, f_1-f_g); | |
const gdFixed f_w4 = gd_mulfx(f_f, f_g); | |
- if (n < src_w - 1) { | |
- src_offset_x = n + 1; | |
- src_offset_y = m; | |
- } | |
- | |
if (m < src_h-1) { | |
src_offset_x = n; | |
src_offset_y = m + 1; | |
@@ -1834,18 +1856,19 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int | |
src_offset_x = n + 1; | |
src_offset_y = m + 1; | |
} | |
+ | |
{ | |
const int pixel1 = src->tpixels[src_offset_y][src_offset_x]; | |
register int pixel2, pixel3, pixel4; | |
if (src_offset_y + 1 >= src_h) { | |
- pixel2 = bgColor; | |
- pixel3 = bgColor; | |
- pixel4 = bgColor; | |
+ pixel2 = pixel1; | |
+ pixel3 = pixel1; | |
+ pixel4 = pixel1; | |
} else if (src_offset_x + 1 >= src_w) { | |
- pixel2 = bgColor; | |
- pixel3 = bgColor; | |
- pixel4 = bgColor; | |
+ pixel2 = pixel1; | |
+ pixel3 = pixel1; | |
+ pixel4 = pixel1; | |
} else { | |
pixel2 = src->tpixels[src_offset_y][src_offset_x + 1]; | |
pixel3 = src->tpixels[src_offset_y + 1][src_offset_x]; | |
@@ -1895,8 +1918,7 @@ gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const | |
const float _angle = (float)((- degrees / 180.0f) * M_PI); | |
const int src_w = gdImageSX(src); | |
const int src_h = gdImageSY(src); | |
- const unsigned int new_width = abs((int)(src_w*cos(_angle))) + abs((int)(src_h*sin(_angle) + 0.5f)); | |
- const unsigned int new_height = abs((int)(src_w*sin(_angle))) + abs((int)(src_h*cos(_angle) + 0.5f)); | |
+ unsigned int new_width, new_height; | |
const gdFixed f_0_5 = gd_ftofx(0.5f); | |
const gdFixed f_H = gd_itofx(src_h/2); | |
const gdFixed f_W = gd_itofx(src_w/2); | |
@@ -1912,7 +1934,11 @@ gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const | |
unsigned int dst_offset_y = 0; | |
unsigned int i; | |
gdImagePtr dst; | |
+ gdRect bbox; | |
+ gdRotatedImageSize(src, degrees, &bbox); | |
+ new_width = bbox.width; | |
+ new_height = bbox.height; | |
dst = gdImageCreateTrueColor(new_width, new_height); | |
if (dst == NULL) { | |
@@ -2160,12 +2186,19 @@ gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const | |
gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, int bgcolor) | |
{ | |
- const int angle_rounded = (int)floor(angle * 100); | |
- | |
+ int angle_rounded; | |
+ float angle_normalized = angle; | |
if (bgcolor < 0) { | |
return NULL; | |
} | |
+ if (angle > 360) { | |
+ angle_normalized = (float)(((int)(angle * 100)) % 36000) / 100.0f; | |
+ } | |
+ if (angle_normalized < 0) { | |
+ angle_normalized += 360; | |
+ } | |
+ | |
/* impact perf a bit, but not that much. Implementation for palette | |
images can be done at a later point. | |
*/ | |
@@ -2176,8 +2209,21 @@ gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, in | |
gdImagePaletteToTrueColor(src); | |
} | |
+ angle_rounded = (int)floor(angle_normalized * 100); | |
/* no interpolation needed here */ | |
switch (angle_rounded) { | |
+ case 0: | |
+ gdImagePtr dst = gdImageCreateTrueColor(src->sx, src->sy); | |
+ if (dst == NULL) { | |
+ return NULL; | |
+ } | |
+ dst->transparent = src->transparent; | |
+ dst->saveAlphaFlag = 1; | |
+ dst->alphaBlendingFlag = gdEffectReplace; | |
+ | |
+ gdImageCopy(dst, src, 0,0,0,0,src->sx,src->sy); | |
+ return dst; | |
+ break; | |
case -27000: | |
case 9000: | |
return gdImageRotate90(src, 0); | |
@@ -2195,19 +2241,19 @@ gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, in | |
switch (src->interpolation_id) { | |
case GD_NEAREST_NEIGHBOUR: | |
- return gdImageRotateNearestNeighbour(src, angle, bgcolor); | |
+ return gdImageRotateNearestNeighbour(src, angle_normalized, bgcolor); | |
break; | |
case GD_BILINEAR_FIXED: | |
- return gdImageRotateBilinear(src, angle, bgcolor); | |
+ return gdImageRotateBilinear(src, angle_normalized, bgcolor); | |
break; | |
case GD_BICUBIC_FIXED: | |
- return gdImageRotateBicubicFixed(src, angle, bgcolor); | |
+ return gdImageRotateBicubicFixed(src, angle_normalized, bgcolor); | |
break; | |
default: | |
- return gdImageRotateGeneric(src, angle, bgcolor); | |
+ return gdImageRotateGeneric(src, angle_normalized, bgcolor); | |
} | |
return NULL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment