Skip to content

Instantly share code, notes, and snippets.

@pierrejoye
Last active April 16, 2016 10:07
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save pierrejoye/59d72385ed1888cf8894a7ed437235ae to your computer and use it in GitHub Desktop.
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