fix #227 drop usage of GD_BILINEAR_FIXED and GD_BICUBIC_FIXED for gdImageRotateInterpolated, the quality does not match expectation. It is also trickier to maintain for little gain. The generic method is used and will be optimized for 2.3 to match fixed pt performance, if necessary. Also use png for comparison to avoid jpeg artifact, making impossible to exactly compare results

master
Pierre Joye 2016-06-15 09:38:22 +07:00
parent 2da8294ff4
commit bd6d2e101f
17 changed files with 54 additions and 449 deletions

View File

@ -90,10 +90,6 @@ static gdImagePtr gdImageScaleNearestNeighbour(gdImagePtr im,
static gdImagePtr gdImageRotateNearestNeighbour(gdImagePtr src,
const float degrees,
const int bgColor);
static gdImagePtr gdImageRotateBilinear(gdImagePtr src, const float degrees,
const int bgColor);
static gdImagePtr gdImageRotateBicubicFixed(gdImagePtr src, const float degrees,
const int bgColor);
static gdImagePtr gdImageRotateGeneric(gdImagePtr src, const float degrees,
const int bgColor);
@ -141,28 +137,29 @@ typedef struct
} LineContribType;
/* Each core filter has its own radius */
#define DEFAULT_FILTER_BICUBIC 3.0
#define DEFAULT_FILTER_BOX 0.5
#define DEFAULT_FILTER_GENERALIZED_CUBIC 0.5
#define DEFAULT_FILTER_RADIUS 1.0
#define DEFAULT_LANCZOS8_RADIUS 8.0
#define DEFAULT_LANCZOS3_RADIUS 3.0
#define DEFAULT_HERMITE_RADIUS 1.0
#define DEFAULT_BOX_RADIUS 0.5
#define DEFAULT_TRIANGLE_RADIUS 1.0
#define DEFAULT_BELL_RADIUS 1.5
#define DEFAULT_CUBICSPLINE_RADIUS 2.0
#define DEFAULT_MITCHELL_RADIUS 2.0
#define DEFAULT_COSINE_RADIUS 1.0
#define DEFAULT_CATMULLROM_RADIUS 2.0
#define DEFAULT_QUADRATIC_RADIUS 1.5
#define DEFAULT_QUADRATICBSPLINE_RADIUS 1.5
#define DEFAULT_CUBICCONVOLUTION_RADIUS 3.0
#define DEFAULT_GAUSSIAN_RADIUS 1.0
#define DEFAULT_HANNING_RADIUS 1.0
#define DEFAULT_HAMMING_RADIUS 1.0
#define DEFAULT_SINC_RADIUS 1.0
#define DEFAULT_WELSH_RADIUS 1.0
#define DEFAULT_FILTER_LINEAR 1.0f
#define DEFAULT_FILTER_BICUBIC 3.0f
#define DEFAULT_FILTER_BOX 0.5f
#define DEFAULT_FILTER_GENERALIZED_CUBIC 0.5f
#define DEFAULT_FILTER_RADIUS 1.0f
#define DEFAULT_LANCZOS8_RADIUS 8.0f
#define DEFAULT_LANCZOS3_RADIUS 3.0f
#define DEFAULT_HERMITE_RADIUS 1.0f
#define DEFAULT_BOX_RADIUS 0.5f
#define DEFAULT_TRIANGLE_RADIUS 1.0f
#define DEFAULT_BELL_RADIUS 1.5f
#define DEFAULT_CUBICSPLINE_RADIUS 2.0f
#define DEFAULT_MITCHELL_RADIUS 2.0f
#define DEFAULT_COSINE_RADIUS 1.0f
#define DEFAULT_CATMULLROM_RADIUS 2.0f
#define DEFAULT_QUADRATIC_RADIUS 1.5f
#define DEFAULT_QUADRATICBSPLINE_RADIUS 1.5f
#define DEFAULT_CUBICCONVOLUTION_RADIUS 3.0f
#define DEFAULT_GAUSSIAN_RADIUS 1.0f
#define DEFAULT_HANNING_RADIUS 1.0f
#define DEFAULT_HAMMING_RADIUS 1.0f
#define DEFAULT_SINC_RADIUS 1.0f
#define DEFAULT_WELSH_RADIUS 1.0f
static double KernelBessel_J1(const double x)
{
@ -309,6 +306,15 @@ static double filter_blackman(const double x)
return (0.42f+0.5f*(double)cos(M_PI*x)+0.08f*(double)cos(2.0f*M_PI*x));
}
double filter_linear(const double x) {
double ax = fabs(x);
if (ax < 1.0f) {
return (1.0f - ax);
}
return 0.0f;
}
/**
* Bicubic interpolation kernel (a=-1):
\verbatim
@ -754,7 +760,7 @@ int getPixelInterpolated(gdImagePtr im, const double x, const double y, const in
double new_r = 0.0f, new_g = 0.0f, new_b = 0.0f, new_a = 0.0f;
/* These methods use special implementations */
if (im->interpolation_id == GD_BILINEAR_FIXED || im->interpolation_id == GD_BICUBIC_FIXED || im->interpolation_id == GD_NEAREST_NEIGHBOUR) {
if (im->interpolation_id == GD_NEAREST_NEIGHBOUR) {
return -1;
}
@ -1573,7 +1579,9 @@ BGD_DECLARE(gdImagePtr) gdImageScale(const gdImagePtr src, const unsigned int ne
if (new_width == 0 || new_height == 0) {
return NULL;
}
if (new_width == gdImageSX(src) && new_height == gdImageSY(src)) {
return gdImageClone(src);
}
switch (src->interpolation_id) {
/*Special cases, optimized implementations */
case GD_NEAREST_NEIGHBOUR:
@ -1581,10 +1589,12 @@ BGD_DECLARE(gdImagePtr) gdImageScale(const gdImagePtr src, const unsigned int ne
break;
case GD_BILINEAR_FIXED:
case GD_LINEAR:
im_scaled = gdImageScaleBilinear(src, new_width, new_height);
break;
case GD_BICUBIC_FIXED:
case GD_BICUBIC:
im_scaled = gdImageScaleBicubicFixed(src, new_width, new_height);
break;
@ -1707,7 +1717,11 @@ gdImageRotateGeneric(gdImagePtr src, const float degrees, const int bgColor)
if (src->trueColor == 0) {
gdImagePaletteToTrueColor(src);
}
if (src->interpolation == NULL) {
gdImageSetInterpolationMethod(src, GD_DEFAULT);
}
gdRotatedImageSize(src, degrees, &bbox);
new_width = bbox.width;
new_height = bbox.height;
@ -1740,412 +1754,6 @@ gdImageRotateGeneric(gdImagePtr src, const float degrees, const int bgColor)
return dst;
}
static gdImagePtr
gdImageRotateBilinear(gdImagePtr src, const float degrees, const int bgColor)
{
float _angle = (float)((- degrees / 180.0f) * M_PI);
const unsigned int src_w = gdImageSX(src);
const unsigned int src_h = gdImageSY(src);
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);
const gdFixed f_cos = gd_ftofx(cos(-_angle));
const gdFixed f_sin = gd_ftofx(sin(-_angle));
const gdFixed f_1 = gd_itofx(1);
unsigned int i;
unsigned int dst_offset_x;
unsigned int dst_offset_y = 0;
unsigned int src_offset_x, src_offset_y;
gdImagePtr dst;
gdRect bbox;
int new_height, new_width;
/* impact perf a bit, but not that much. Implementation for palette
images can be done at a later point.
*/
if (src->trueColor == 0) {
gdImagePaletteToTrueColor(src);
}
gdRotatedImageSize(src, degrees, &bbox);
new_width = bbox.width;
new_height = bbox.height;
dst = gdImageCreateTrueColor(new_width, new_height);
if (dst == NULL) {
return NULL;
}
dst->saveAlphaFlag = 1;
for (i = 0; i < new_height; i++) {
unsigned int j;
dst_offset_x = 0;
for (j=0; j < new_width; j++) {
const gdFixed f_i = gd_itofx((int)i - (int)new_height / 2);
const gdFixed f_j = gd_itofx((int)j - (int)new_width / 2);
const gdFixed f_m = gd_mulfx(f_j,f_sin) + gd_mulfx(f_i,f_cos) + f_0_5 + f_H;
const gdFixed f_n = gd_mulfx(f_j,f_cos) - gd_mulfx(f_i,f_sin) + f_0_5 + f_W;
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)) {
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);
const gdFixed f_w2 = gd_mulfx(f_1-f_f, f_g);
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;
}
if (!((n >= src_w - 1) || (m >= src_h - 1))) {
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;
} else if (src_offset_x + 1 >= src_w) {
pixel2 = bgColor;
pixel3 = bgColor;
pixel4 = bgColor;
} else {
pixel2 = src->tpixels[src_offset_y][src_offset_x + 1];
pixel3 = src->tpixels[src_offset_y + 1][src_offset_x];
pixel4 = src->tpixels[src_offset_y + 1][src_offset_x + 1];
}
{
const gdFixed f_r1 = gd_itofx(gdTrueColorGetRed(pixel1));
const gdFixed f_r2 = gd_itofx(gdTrueColorGetRed(pixel2));
const gdFixed f_r3 = gd_itofx(gdTrueColorGetRed(pixel3));
const gdFixed f_r4 = gd_itofx(gdTrueColorGetRed(pixel4));
const gdFixed f_g1 = gd_itofx(gdTrueColorGetGreen(pixel1));
const gdFixed f_g2 = gd_itofx(gdTrueColorGetGreen(pixel2));
const gdFixed f_g3 = gd_itofx(gdTrueColorGetGreen(pixel3));
const gdFixed f_g4 = gd_itofx(gdTrueColorGetGreen(pixel4));
const gdFixed f_b1 = gd_itofx(gdTrueColorGetBlue(pixel1));
const gdFixed f_b2 = gd_itofx(gdTrueColorGetBlue(pixel2));
const gdFixed f_b3 = gd_itofx(gdTrueColorGetBlue(pixel3));
const gdFixed f_b4 = gd_itofx(gdTrueColorGetBlue(pixel4));
const gdFixed f_a1 = gd_itofx(gdTrueColorGetAlpha(pixel1));
const gdFixed f_a2 = gd_itofx(gdTrueColorGetAlpha(pixel2));
const gdFixed f_a3 = gd_itofx(gdTrueColorGetAlpha(pixel3));
const gdFixed f_a4 = gd_itofx(gdTrueColorGetAlpha(pixel4));
const gdFixed f_red = gd_mulfx(f_w1, f_r1) + gd_mulfx(f_w2, f_r2) + gd_mulfx(f_w3, f_r3) + gd_mulfx(f_w4, f_r4);
const gdFixed f_green = gd_mulfx(f_w1, f_g1) + gd_mulfx(f_w2, f_g2) + gd_mulfx(f_w3, f_g3) + gd_mulfx(f_w4, f_g4);
const gdFixed f_blue = gd_mulfx(f_w1, f_b1) + gd_mulfx(f_w2, f_b2) + gd_mulfx(f_w3, f_b3) + gd_mulfx(f_w4, f_b4);
const gdFixed f_alpha = gd_mulfx(f_w1, f_a1) + gd_mulfx(f_w2, f_a2) + gd_mulfx(f_w3, f_a3) + gd_mulfx(f_w4, f_a4);
const unsigned char red = (unsigned char) CLAMP(gd_fxtoi(f_red), 0, 255);
const unsigned char green = (unsigned char) CLAMP(gd_fxtoi(f_green), 0, 255);
const unsigned char blue = (unsigned char) CLAMP(gd_fxtoi(f_blue), 0, 255);
const unsigned char alpha = (unsigned char) CLAMP(gd_fxtoi(f_alpha), 0, 127);
dst->tpixels[dst_offset_y][dst_offset_x++] = gdTrueColorAlpha(red, green, blue, alpha);
}
}
} else {
dst->tpixels[dst_offset_y][dst_offset_x++] = bgColor;
}
}
dst_offset_y++;
}
return dst;
}
static gdImagePtr
gdImageRotateBicubicFixed(gdImagePtr src, const float degrees,const int bgColor)
{
const float _angle = (float)((- degrees / 180.0f) * M_PI);
const int src_w = gdImageSX(src);
const int src_h = gdImageSY(src);
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);
const gdFixed f_cos = gd_ftofx(cos(-_angle));
const gdFixed f_sin = gd_ftofx(sin(-_angle));
const gdFixed f_1 = gd_itofx(1);
const gdFixed f_2 = gd_itofx(2);
const gdFixed f_4 = gd_itofx(4);
const gdFixed f_6 = gd_itofx(6);
const gdFixed f_gama = gd_ftofx(1.04f);
unsigned int dst_offset_x;
unsigned int dst_offset_y = 0;
unsigned int i;
gdImagePtr dst;
gdRect bbox;
int new_height, new_width;
/* impact perf a bit, but not that much. Implementation for palette
images can be done at a later point.
*/
if (src->trueColor == 0) {
gdImagePaletteToTrueColor(src);
}
gdRotatedImageSize(src, degrees, &bbox);
new_width = bbox.width;
new_height = bbox.height;
dst = gdImageCreateTrueColor(new_width, new_height);
if (dst == NULL) {
return NULL;
}
dst->saveAlphaFlag = 1;
for (i=0; i < new_height; i++) {
unsigned int j;
dst_offset_x = 0;
for (j=0; j < new_width; j++) {
const gdFixed f_i = gd_itofx((int)i - (int)new_height / 2);
const gdFixed f_j = gd_itofx((int)j - (int)new_width / 2);
const gdFixed f_m = gd_mulfx(f_j,f_sin) + gd_mulfx(f_i,f_cos) + f_0_5 + f_H;
const gdFixed f_n = gd_mulfx(f_j,f_cos) - gd_mulfx(f_i,f_sin) + f_0_5 + f_W;
const int m = gd_fxtoi(f_m);
const int n = gd_fxtoi(f_n);
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);
unsigned int src_offset_x[16], src_offset_y[16];
unsigned char red, green, blue, alpha;
gdFixed f_red=0, f_green=0, f_blue=0, f_alpha=0;
int k;
if ((m < 1) || (n < 1)) {
src_offset_x[0] = n;
src_offset_y[0] = m;
} else {
src_offset_x[0] = n - 1;
src_offset_y[0] = m;
}
if (m < 1) {
src_offset_x[1] = n;
src_offset_y[1] = m;
} else {
src_offset_x[1] = n;
src_offset_y[1] = m ;
}
if ((m < 1) || (n >= src_w-1)) {
src_offset_x[2] = - 1;
src_offset_y[2] = - 1;
} else {
src_offset_x[2] = n + 1;
src_offset_y[2] = m ;
}
if ((m < 1) || (n >= src_w-2)) {
src_offset_x[3] = - 1;
src_offset_y[3] = - 1;
} else {
src_offset_x[3] = n + 1 + 1;
src_offset_y[3] = m ;
}
if (n < 1) {
src_offset_x[4] = - 1;
src_offset_y[4] = - 1;
} else {
src_offset_x[4] = n - 1;
src_offset_y[4] = m;
}
src_offset_x[5] = n;
src_offset_y[5] = m;
if (n >= src_w-1) {
src_offset_x[6] = - 1;
src_offset_y[6] = - 1;
} else {
src_offset_x[6] = n + 1;
src_offset_y[6] = m;
}
if (n >= src_w-2) {
src_offset_x[7] = - 1;
src_offset_y[7] = - 1;
} else {
src_offset_x[7] = n + 1 + 1;
src_offset_y[7] = m;
}
if ((m >= src_h-1) || (n < 1)) {
src_offset_x[8] = - 1;
src_offset_y[8] = - 1;
} else {
src_offset_x[8] = n - 1;
src_offset_y[8] = m;
}
if (m >= src_h-1) {
src_offset_x[8] = - 1;
src_offset_y[8] = - 1;
} else {
src_offset_x[9] = n;
src_offset_y[9] = m;
}
if ((m >= src_h-1) || (n >= src_w-1)) {
src_offset_x[10] = - 1;
src_offset_y[10] = - 1;
} else {
src_offset_x[10] = n + 1;
src_offset_y[10] = m;
}
if ((m >= src_h-1) || (n >= src_w-2)) {
src_offset_x[11] = - 1;
src_offset_y[11] = - 1;
} else {
src_offset_x[11] = n + 1 + 1;
src_offset_y[11] = m;
}
if ((m >= src_h-2) || (n < 1)) {
src_offset_x[12] = - 1;
src_offset_y[12] = - 1;
} else {
src_offset_x[12] = n - 1;
src_offset_y[12] = m;
}
if (m >= src_h-2) {
src_offset_x[13] = - 1;
src_offset_y[13] = - 1;
} else {
src_offset_x[13] = n;
src_offset_y[13] = m;
}
if ((m >= src_h-2) || (n >= src_w - 1)) {
src_offset_x[14] = - 1;
src_offset_y[14] = - 1;
} else {
src_offset_x[14] = n + 1;
src_offset_y[14] = m;
}
if ((m >= src_h-2) || (n >= src_w-2)) {
src_offset_x[15] = - 1;
src_offset_y[15] = - 1;
} else {
src_offset_x[15] = n + 1 + 1;
src_offset_y[15] = m;
}
for (k=-1; k<3; k++) {
const gdFixed f = gd_itofx(k)-f_f;
const gdFixed f_fm1 = f - f_1;
const gdFixed f_fp1 = f + f_1;
const gdFixed f_fp2 = f + f_2;
gdFixed f_a = 0, f_b = 0,f_c = 0, f_d = 0;
gdFixed f_RY;
int l;
if (f_fp2 > 0) {
f_a = gd_mulfx(f_fp2,gd_mulfx(f_fp2,f_fp2));
}
if (f_fp1 > 0) {
f_b = gd_mulfx(f_fp1,gd_mulfx(f_fp1,f_fp1));
}
if (f > 0) {
f_c = gd_mulfx(f,gd_mulfx(f,f));
}
if (f_fm1 > 0) {
f_d = gd_mulfx(f_fm1,gd_mulfx(f_fm1,f_fm1));
}
f_RY = gd_divfx((f_a-gd_mulfx(f_4,f_b)+gd_mulfx(f_6,f_c)-gd_mulfx(f_4,f_d)),f_6);
for (l=-1; l< 3; l++) {
const gdFixed f = gd_itofx(l) - f_g;
const gdFixed f_fm1 = f - f_1;
const gdFixed f_fp1 = f + f_1;
const gdFixed f_fp2 = f + f_2;
gdFixed f_a = 0, f_b = 0, f_c = 0, f_d = 0;
gdFixed f_RX, f_R;
const int _k = ((k + 1) * 4) + (l + 1);
register gdFixed f_rs, f_gs, f_bs, f_as;
register int c;
if (f_fp2 > 0) {
f_a = gd_mulfx(f_fp2,gd_mulfx(f_fp2,f_fp2));
}
if (f_fp1 > 0) {
f_b = gd_mulfx(f_fp1,gd_mulfx(f_fp1,f_fp1));
}
if (f > 0) {
f_c = gd_mulfx(f,gd_mulfx(f,f));
}
if (f_fm1 > 0) {
f_d = gd_mulfx(f_fm1,gd_mulfx(f_fm1,f_fm1));
}
f_RX = gd_divfx((f_a - gd_mulfx(f_4, f_b) + gd_mulfx(f_6, f_c) - gd_mulfx(f_4, f_d)), f_6);
f_R = gd_mulfx(f_RY, f_RX);
if ((src_offset_x[_k] <= 0) || (src_offset_y[_k] <= 0) || (src_offset_y[_k] >= src_h) || (src_offset_x[_k] >= src_w)) {
c = bgColor;
} else if ((src_offset_x[_k] <= 1) || (src_offset_y[_k] <= 1) || (src_offset_y[_k] >= (int)src_h - 1) || (src_offset_x[_k] >= (int)src_w - 1)) {
gdFixed f_127 = gd_itofx(127);
c = src->tpixels[src_offset_y[_k]][src_offset_x[_k]];
c = c | (( (int) (gd_fxtof(gd_mulfx(f_R, f_127)) + 50.5f)) << 24);
c = _color_blend(bgColor, c);
} else {
c = src->tpixels[src_offset_y[_k]][src_offset_x[_k]];
}
f_rs = gd_itofx(gdTrueColorGetRed(c));
f_gs = gd_itofx(gdTrueColorGetGreen(c));
f_bs = gd_itofx(gdTrueColorGetBlue(c));
f_as = gd_itofx(gdTrueColorGetAlpha(c));
f_red += gd_mulfx(f_rs, f_R);
f_green += gd_mulfx(f_gs, f_R);
f_blue += gd_mulfx(f_bs, f_R);
f_alpha += gd_mulfx(f_as, f_R);
}
}
red = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_red, f_gama)), 0, 255);
green = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_green, f_gama)), 0, 255);
blue = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_blue, f_gama)), 0, 255);
alpha = (unsigned char) CLAMP(gd_fxtoi(gd_mulfx(f_alpha, f_gama)), 0, 127);
dst->tpixels[dst_offset_y][dst_offset_x] = gdTrueColorAlpha(red, green, blue, alpha);
} else {
dst->tpixels[dst_offset_y][dst_offset_x] = bgColor;
}
dst_offset_x++;
}
dst_offset_y++;
}
return dst;
}
BGD_DECLARE(gdImagePtr) gdImageRotateInterpolated(const gdImagePtr src, const float angle, int bgcolor)
{
/* round to two decimals and keep the 100x multiplication to use it in the common square angles
@ -2195,13 +1803,7 @@ BGD_DECLARE(gdImagePtr) gdImageRotateInterpolated(const gdImagePtr src, const fl
break;
case GD_BILINEAR_FIXED:
return gdImageRotateBilinear(src, angle, bgcolor);
break;
case GD_BICUBIC_FIXED:
return gdImageRotateBicubicFixed(src, angle, bgcolor);
break;
default:
return gdImageRotateGeneric(src, angle, bgcolor);
}
@ -2477,23 +2079,24 @@ BGD_DECLARE(int) gdImageSetInterpolationMethod(gdImagePtr im, gdInterpolationMet
}
switch (id) {
case GD_DEFAULT:
id = GD_BILINEAR_FIXED;
/* Optimized versions */
case GD_BILINEAR_FIXED:
case GD_BICUBIC_FIXED:
case GD_NEAREST_NEIGHBOUR:
case GD_WEIGHTED4:
im->interpolation = NULL;
break;
/* generic versions*/
/* GD_BILINEAR_FIXED and GD_BICUBIC_FIXED are kept for BC reasons */
case GD_BILINEAR_FIXED:
case GD_LINEAR:
im->interpolation = filter_linear;
break;
case GD_BELL:
im->interpolation = filter_bell;
break;
case GD_BESSEL:
im->interpolation = filter_bessel;
break;
case GD_BICUBIC_FIXED:
case GD_BICUBIC:
im->interpolation = filter_bicubic;
break;
@ -2539,7 +2142,9 @@ BGD_DECLARE(int) gdImageSetInterpolationMethod(gdImagePtr im, gdInterpolationMet
case GD_TRIANGLE:
im->interpolation = filter_triangle;
break;
case GD_DEFAULT:
id = GD_LINEAR;
im->interpolation = filter_linear;
default:
return 0;
break;

View File

@ -8,7 +8,7 @@ int main()
{
gdImagePtr im, exp;
char path[2048];
const char *file_im = "gdimagerotate/remirh128.jpg";
const char *file_im = "gdimagerotate/remirh128.png";
const char *file_exp = "gdimagerotate/bug00067";
FILE *fp;
int color;
@ -24,7 +24,7 @@ int main()
return 1;
}
im = gdImageCreateFromJpeg(fp);
im = gdImageCreateFromPng(fp);
fclose(fp);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB