@@ -1709,13 +1709,28 @@ gdImagePtr gdImageScale(const gdImagePtr src, const unsigned int new_width, cons
1709
1709
return im_scaled ;
1710
1710
}
1711
1711
1712
+ static int gdRotatedImageSize (gdImagePtr src , const float angle , gdRectPtr bbox )
1713
+ {
1714
+ gdRect src_area ;
1715
+ double m [6 ];
1716
+
1717
+ gdAffineRotate (m , angle );
1718
+ src_area .x = 0 ;
1719
+ src_area .y = 0 ;
1720
+ src_area .width = gdImageSX (src );
1721
+ src_area .height = gdImageSY (src );
1722
+ if (gdTransformAffineBoundingBox (& src_area , m , bbox ) != GD_TRUE ) {
1723
+ return GD_FALSE ;
1724
+ }
1725
+
1726
+ return GD_TRUE ;
1727
+ }
1728
+
1712
1729
gdImagePtr gdImageRotateNearestNeighbour (gdImagePtr src , const float degrees , const int bgColor )
1713
1730
{
1714
1731
float _angle = ((float ) (- degrees / 180.0f ) * (float )M_PI );
1715
1732
const int src_w = gdImageSX (src );
1716
1733
const int src_h = gdImageSY (src );
1717
- const unsigned int new_width = (unsigned int )(abs ((int )(src_w * cos (_angle ))) + abs ((int )(src_h * sin (_angle ))) + 0.5f );
1718
- const unsigned int new_height = (unsigned int )(abs ((int )(src_w * sin (_angle ))) + abs ((int )(src_h * cos (_angle ))) + 0.5f );
1719
1734
const gdFixed f_0_5 = gd_ftofx (0.5f );
1720
1735
const gdFixed f_H = gd_itofx (src_h /2 );
1721
1736
const gdFixed f_W = gd_itofx (src_w /2 );
@@ -1726,6 +1741,12 @@ gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src, const float degrees, co
1726
1741
unsigned int dst_offset_y = 0 ;
1727
1742
unsigned int i ;
1728
1743
gdImagePtr dst ;
1744
+ gdRect bbox ;
1745
+ int new_height , new_width ;
1746
+
1747
+ gdRotatedImageSize (src , degrees , & bbox );
1748
+ new_width = bbox .width ;
1749
+ new_height = bbox .height ;
1729
1750
1730
1751
if (new_width == 0 || new_height == 0 ) {
1731
1752
return NULL ;
@@ -1768,8 +1789,6 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b
1768
1789
const int angle_rounded = (int )floor (degrees * 100 );
1769
1790
const int src_w = gdImageSX (src );
1770
1791
const int src_h = gdImageSY (src );
1771
- const unsigned int new_width = (unsigned int )(abs ((int )(src_w * cos (_angle ))) + abs ((int )(src_h * sin (_angle ))) + 0.5f );
1772
- const unsigned int new_height = (unsigned int )(abs ((int )(src_w * sin (_angle ))) + abs ((int )(src_h * cos (_angle ))) + 0.5f );
1773
1792
const gdFixed f_0_5 = gd_ftofx (0.5f );
1774
1793
const gdFixed f_H = gd_itofx (src_h /2 );
1775
1794
const gdFixed f_W = gd_itofx (src_w /2 );
@@ -1780,6 +1799,8 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b
1780
1799
unsigned int dst_offset_y = 0 ;
1781
1800
unsigned int i ;
1782
1801
gdImagePtr dst ;
1802
+ int new_width , new_height ;
1803
+ gdRect bbox ;
1783
1804
1784
1805
const gdFixed f_slop_y = f_sin ;
1785
1806
const gdFixed f_slop_x = f_cos ;
@@ -1792,6 +1813,10 @@ gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees, const int b
1792
1813
return NULL ;
1793
1814
}
1794
1815
1816
+ gdRotatedImageSize (src , degrees , & bbox );
1817
+ new_width = bbox .width ;
1818
+ new_height = bbox .height ;
1819
+
1795
1820
dst = gdImageCreateTrueColor (new_width , new_height );
1796
1821
if (!dst ) {
1797
1822
return NULL ;
@@ -1831,8 +1856,7 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int
1831
1856
float _angle = (float )((- degrees / 180.0f ) * M_PI );
1832
1857
const unsigned int src_w = gdImageSX (src );
1833
1858
const unsigned int src_h = gdImageSY (src );
1834
- unsigned int new_width = abs ((int )(src_w * cos (_angle ))) + abs ((int )(src_h * sin (_angle ) + 0.5f ));
1835
- unsigned int new_height = abs ((int )(src_w * sin (_angle ))) + abs ((int )(src_h * cos (_angle ) + 0.5f ));
1859
+ unsigned int new_width , new_height ;
1836
1860
const gdFixed f_0_5 = gd_ftofx (0.5f );
1837
1861
const gdFixed f_H = gd_itofx (src_h /2 );
1838
1862
const gdFixed f_W = gd_itofx (src_w /2 );
@@ -1844,6 +1868,12 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int
1844
1868
unsigned int dst_offset_y = 0 ;
1845
1869
unsigned int src_offset_x , src_offset_y ;
1846
1870
gdImagePtr dst ;
1871
+ gdRect bbox ;
1872
+
1873
+ gdRotatedImageSize (src , degrees , & bbox );
1874
+
1875
+ new_width = bbox .width ;
1876
+ new_height = bbox .height ;
1847
1877
1848
1878
dst = gdImageCreateTrueColor (new_width , new_height );
1849
1879
if (dst == NULL ) {
@@ -1863,19 +1893,14 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int
1863
1893
const unsigned int m = gd_fxtoi (f_m );
1864
1894
const unsigned int n = gd_fxtoi (f_n );
1865
1895
1866
- if ((m > 0 ) && (m < src_h - 1 ) && (n > 0 ) && (n < src_w - 1 )) {
1896
+ if ((m >= 0 ) && (m < src_h - 1 ) && (n >= 0 ) && (n < src_w - 1 )) {
1867
1897
const gdFixed f_f = f_m - gd_itofx (m );
1868
1898
const gdFixed f_g = f_n - gd_itofx (n );
1869
1899
const gdFixed f_w1 = gd_mulfx (f_1 - f_f , f_1 - f_g );
1870
1900
const gdFixed f_w2 = gd_mulfx (f_1 - f_f , f_g );
1871
1901
const gdFixed f_w3 = gd_mulfx (f_f , f_1 - f_g );
1872
1902
const gdFixed f_w4 = gd_mulfx (f_f , f_g );
1873
1903
1874
- if (n < src_w - 1 ) {
1875
- src_offset_x = n + 1 ;
1876
- src_offset_y = m ;
1877
- }
1878
-
1879
1904
if (m < src_h - 1 ) {
1880
1905
src_offset_x = n ;
1881
1906
src_offset_y = m + 1 ;
@@ -1890,13 +1915,13 @@ gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees, const int
1890
1915
register int pixel2 , pixel3 , pixel4 ;
1891
1916
1892
1917
if (src_offset_y + 1 >= src_h ) {
1893
- pixel2 = bgColor ;
1894
- pixel3 = bgColor ;
1895
- pixel4 = bgColor ;
1918
+ pixel2 = pixel1 ;
1919
+ pixel3 = pixel1 ;
1920
+ pixel4 = pixel1 ;
1896
1921
} else if (src_offset_x + 1 >= src_w ) {
1897
- pixel2 = bgColor ;
1898
- pixel3 = bgColor ;
1899
- pixel4 = bgColor ;
1922
+ pixel2 = pixel1 ;
1923
+ pixel3 = pixel1 ;
1924
+ pixel4 = pixel1 ;
1900
1925
} else {
1901
1926
pixel2 = src -> tpixels [src_offset_y ][src_offset_x + 1 ];
1902
1927
pixel3 = src -> tpixels [src_offset_y + 1 ][src_offset_x ];
@@ -1946,8 +1971,7 @@ gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const
1946
1971
const float _angle = (float )((- degrees / 180.0f ) * M_PI );
1947
1972
const int src_w = gdImageSX (src );
1948
1973
const int src_h = gdImageSY (src );
1949
- const unsigned int new_width = abs ((int )(src_w * cos (_angle ))) + abs ((int )(src_h * sin (_angle ) + 0.5f ));
1950
- const unsigned int new_height = abs ((int )(src_w * sin (_angle ))) + abs ((int )(src_h * cos (_angle ) + 0.5f ));
1974
+ unsigned int new_width , new_height ;
1951
1975
const gdFixed f_0_5 = gd_ftofx (0.5f );
1952
1976
const gdFixed f_H = gd_itofx (src_h /2 );
1953
1977
const gdFixed f_W = gd_itofx (src_w /2 );
@@ -1963,7 +1987,11 @@ gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const
1963
1987
unsigned int dst_offset_y = 0 ;
1964
1988
unsigned int i ;
1965
1989
gdImagePtr dst ;
1990
+ gdRect bbox ;
1966
1991
1992
+ gdRotatedImageSize (src , degrees , & bbox );
1993
+ new_width = bbox .width ;
1994
+ new_height = bbox .height ;
1967
1995
dst = gdImageCreateTrueColor (new_width , new_height );
1968
1996
1969
1997
if (dst == NULL ) {
@@ -2206,8 +2234,11 @@ gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees, const
2206
2234
2207
2235
gdImagePtr gdImageRotateInterpolated (const gdImagePtr src , const float angle , int bgcolor )
2208
2236
{
2209
- const int angle_rounded = (int )floor (angle * 100 );
2210
-
2237
+ /* round to two decimals and keep the 100x multiplication to use it in the common square angles
2238
+ case later. Keep the two decimal precisions so smaller rotation steps can be done, useful for
2239
+ slow animations, f.e. */
2240
+ const int angle_rounded = fmod ((int ) floorf (angle * 100 ), 360 * 100 );
2241
+
2211
2242
if (bgcolor < 0 ) {
2212
2243
return NULL ;
2213
2244
}
@@ -2224,6 +2255,18 @@ gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, in
2224
2255
2225
2256
/* no interpolation needed here */
2226
2257
switch (angle_rounded ) {
2258
+ case 0 : {
2259
+ gdImagePtr dst = gdImageCreateTrueColor (src -> sx , src -> sy );
2260
+ if (dst == NULL ) {
2261
+ return NULL ;
2262
+ }
2263
+ dst -> transparent = src -> transparent ;
2264
+ dst -> saveAlphaFlag = 1 ;
2265
+ dst -> alphaBlendingFlag = gdEffectReplace ;
2266
+
2267
+ gdImageCopy (dst , src , 0 ,0 ,0 ,0 ,src -> sx ,src -> sy );
2268
+ return dst ;
2269
+ }
2227
2270
case -27000 :
2228
2271
case 9000 :
2229
2272
return gdImageRotate90 (src , 0 );
0 commit comments