Commits

Chris Reuter committed 5b7f746 Merge

Merged libgd/gd-libgd into master

Comments (0)

Files changed (4)

 /tests/gdimagerotate/bug00067
 /tests/gdimageline/gdImageAALine_thickness
 /tests/gdimageline/gdimageline_bug5
+/tests/gdinterpolatedscale/gdTrivialResize
+/tests/gdinterpolatedscale/gdModesAndPalettes
+

src/gd_interpolation.c

 }
 
 
+/* Convert a double to an unsigned char, rounding to the nearest
+ * integer and clamping the result between 0 and 255.  The absolute
+ * value of clr must be less than the maximum value of an unsigned
+ * short. */
+static inline unsigned char
+uchar_clamp(double clr) {
+	unsigned short result;
+
+	assert(fabs(clr) <= SHRT_MAX);
+
+	/* Casting a negative float to an unsigned short is undefined.
+	 * However, casting a float to a signed truncates toward zero and
+	 * casting a negative signed value to an unsigned of the same size
+	 * results in a bit-identical value (assuming twos-complement
+	 * arithmetic).	 This is what we want: all legal negative values
+	 * for clr will be greater than 255. */
+
+	/* Convert and clamp. */
+	result = (unsigned short)(short)(clr + 0.5);
+	if (result > 255) {
+		result = (clr < 0) ? 0 : 255;
+	}/* if */
+
+	return result;
+}/* uchar_clamp*/
+
 static inline void
 _gdScaleOneAxis(gdImagePtr pSrc, gdImagePtr dst,
-                unsigned int dst_len, unsigned int row, LineContribType *contrib,
-                gdAxis axis)
+				unsigned int dst_len, unsigned int row, LineContribType *contrib,
+				gdAxis axis)
 {
 	unsigned int ndx;
 
 	for (ndx = 0; ndx < dst_len; ndx++) {
-		register unsigned char r = 0, g = 0, b = 0, a = 0;
+		double r = 0, g = 0, b = 0, a = 0;
 		const int left = contrib->ContribRow[ndx].Left;
 		const int right = contrib->ContribRow[ndx].Right;
-        int *dest = (axis == HORIZONTAL) ? 
-            &dst->tpixels[row][ndx] : 
-            &dst->tpixels[ndx][row];
+		int *dest = (axis == HORIZONTAL) ? 
+			&dst->tpixels[row][ndx] : 
+			&dst->tpixels[ndx][row];
 
 		int i;
 
 		/* Accumulate each channel */
 		for (i = left; i <= right; i++) {
 			const int left_channel = i - left;
-            const int srcpx = (axis == HORIZONTAL) ?
-                pSrc->tpixels[row][i] : 
-                pSrc->tpixels[i][row];
-
-			r += (unsigned char)(contrib->ContribRow[ndx].Weights[left_channel] * (double)(gdTrueColorGetRed(srcpx)));
-			g += (unsigned char)(contrib->ContribRow[ndx].Weights[left_channel] * (double)(gdTrueColorGetGreen(srcpx)));
-			b += (unsigned char)(contrib->ContribRow[ndx].Weights[left_channel] * (double)(gdTrueColorGetBlue(srcpx)));
-			a += (unsigned char)(contrib->ContribRow[ndx].Weights[left_channel] * (double)(gdTrueColorGetAlpha(srcpx)));
+			const int srcpx = (axis == HORIZONTAL) ?
+				pSrc->tpixels[row][i] : 
+				pSrc->tpixels[i][row];
+
+			r += contrib->ContribRow[ndx].Weights[left_channel]
+				* (double)(gdTrueColorGetRed(srcpx));
+			g += contrib->ContribRow[ndx].Weights[left_channel]
+				* (double)(gdTrueColorGetGreen(srcpx));
+			b += contrib->ContribRow[ndx].Weights[left_channel]
+				* (double)(gdTrueColorGetBlue(srcpx));
+			a += contrib->ContribRow[ndx].Weights[left_channel]
+				* (double)(gdTrueColorGetAlpha(srcpx));
 		}/* for */
 
-        *dest = gdTrueColorAlpha(r, g, b, a);
+		*dest = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g),uchar_clamp(b),
+								 uchar_clamp(a));
 	}/* for */
 }/* _gdScaleOneAxis*/
 
         return gdImageClone(src);
     }/* if */
 
+	/* Convert to truecolor if it isn't; this code requires it. */
+	if (!src->trueColor) {
+		gdImagePaletteToTrueColor(src);
+	}/* if */
+
     /* Scale horizontally unless sizes are the same. */
     if (src_width == new_width) {
         tmp_im = src;

tests/Makefile.am

 	gif/bug00181 \
 	gif/bug00227 \
 	bmp/bmp_null \
-	gdinterpolatedscale/gdTrivialResize
+	gdinterpolatedscale/gdTrivialResize \
+	gdinterpolatedscale/gdModesAndPalettes
 
 EXTRA_PROGRAMS = \
 	gdimagestringft/gdimagestringft_bbox \

tests/gdinterpolatedscale/gdModesAndPalettes.c

+/* Exercise all scaling with all interpolation modes and ensure that
+ * at least, something comes back. */
+
+#include <stdio.h>
+
+#include "gd.h"
+#include "gdtest.h"
+
+#define X 100
+#define Y 100
+
+#define NX 20
+#define NY 20
+
+int main() {
+    int method, i;
+
+    for(method = GD_BELL; method <= GD_TRIANGLE; method++) {   /* GD_WEIGHTED4 is unsupported. */
+        gdImagePtr im[2];
+
+        // printf("Method = %d\n", method);
+        im[0] = gdImageCreateTrueColor(X, Y);
+        im[1] = gdImageCreatePalette(X, Y);
+
+        for (i = 0; i < 2; i++) {
+            gdImagePtr result;
+
+            // printf("    %s\n", i == 0 ? "truecolor" : "palette");
+
+            gdImageFilledRectangle(im[i], 0, 0, X-1, Y-1,
+                                   gdImageColorExactAlpha(im[i], 255, 255, 255, 0));
+
+            gdImageSetInterpolationMethod(im[i], method);
+            gdTestAssert(im[i]->interpolation_id == method); /* No getter yet. */
+
+            result = gdImageScale(im[i], NX, NY);
+            gdTestAssert(result != NULL);
+            gdTestAssert(result != im[i]);
+            gdTestAssert(result->sx == NX && result->sy == NY);
+
+            gdImageDestroy(result);
+            gdImageDestroy(im[i]);
+        }/* for */
+    }/* for*/
+
+
+    return gdNumFailures();
+}/* main*/