1 #include <stdio.h>
2 #include <stdlib.h>
3 
4 #include "gd.h"
5 #include "gdtest.h"
6 
7 #define WIDTH 300
8 #define HEIGHT 200
9 #define LX (WIDTH/2)    // Line X
10 #define LY (HEIGHT/2)   // Line Y
11 #define HT 3            // Half of line-thickness
12 
13 #define CLOSE_ENOUGH 0
14 #define PIXEL_CLOSE_ENOUGH 0
15 
16 
17 void
save(gdImagePtr im,const char * filename)18 save(gdImagePtr im, const char *filename) {
19 #if 0   // set TRUE to write out some intermediate images
20     FILE *out;
21 
22     out = fopen(filename, "wb");
23     gdImagePng(im, out);
24     fclose(out);
25 #else
26     (void)im, (void)filename;
27 #endif
28 }/* save*/
29 
30 
31 /* Test gdImageScale() with bicubic interpolation on a simple
32  * all-white image. */
33 
mkwhite(int x,int y)34 gdImagePtr mkwhite(int x, int y)
35 {
36     gdImagePtr im;
37 
38 	im = gdImageCreateTrueColor(x, y);
39 	gdImageFilledRectangle(im, 0, 0, x-1, y-1,
40                            gdImageColorExactAlpha(im, 255, 255, 255, 0));
41 
42     gdTestAssert(im != NULL);
43 
44     gdImageSetInterpolationMethod(im, GD_BICUBIC);    // FP interp'n
45 
46     return im;
47 }/* mkwhite*/
48 
49 
50 /* Fill with almost-black. */
mkblack(gdImagePtr ptr)51 void mkblack(gdImagePtr ptr)
52 {
53     gdImageFilledRectangle(ptr, 0, 0, ptr->sx - 1, ptr->sy - 1,
54                            gdImageColorExactAlpha(ptr, 2, 2, 2, 0));
55 }/* mkblack*/
56 
57 
mkcross()58 gdImagePtr mkcross() {
59     gdImagePtr im;
60     int fg, n;
61 
62     im = mkwhite(WIDTH, HEIGHT);
63     fg = gdImageColorAllocate(im, 0, 0, 0);
64 
65     for (n = -HT; n < HT; n++) {
66         gdImageLine(im, LX-n, 0, LX-n, HEIGHT-1, fg);
67         gdImageLine(im, 0, LY-n, WIDTH-1, LY-n, fg);
68     }/* for */
69 
70     return im;
71 }/* mkcross*/
72 
73 
74 
blurblank(gdImagePtr im,int radius,double sigma)75 void blurblank(gdImagePtr im, int radius, double sigma) {
76     gdImagePtr result;
77 
78     result = gdImageCopyGaussianBlurred(im, radius, sigma);
79     gdTestAssert(!!result);
80     if (!result) return;
81 
82     gdTestAssert(gdMaxPixelDiff(im, result) <= CLOSE_ENOUGH);
83 
84     gdImageDestroy(result);
85 }/* blurblank*/
86 
87 
do_test()88 void do_test()
89 {
90 	gdImagePtr im, imref;
91 
92 	im = mkwhite(WIDTH, HEIGHT);
93     imref = mkwhite(WIDTH, HEIGHT);
94 
95     /* Blur a plain white image to various radii and ensure they're
96      * still similar enough. */
97     blurblank(im, 1, 0.0);
98     blurblank(im, 2, 0.0);
99     blurblank(im, 4, 0.0);
100     blurblank(im, 8, 0.0);
101     blurblank(im, 16, 0.0);
102 
103     /* Ditto a black image. */
104     mkblack(im);
105     gdTestAssert(gdMaxPixelDiff(im, imref) >= 240); /* Leaves a little wiggle room */
106 
107     blurblank(im, 1, 0.0);
108     blurblank(im, 2, 0.0);
109     blurblank(im, 4, 0.0);
110     blurblank(im, 8, 0.0);
111     blurblank(im, 16, 0.0);
112 
113     gdImageDestroy(im);
114     gdImageDestroy(imref);
115 }/* do_test*/
116 
117 /* Ensure that RGB values are equal, then return r (which is therefore
118  * the whiteness.) */
getwhite(gdImagePtr im,int x,int y)119 int getwhite(gdImagePtr im, int x, int y)
120 {
121     int px, r, g, b;
122 
123     px = gdImageGetPixel(im, x, y);
124     r = gdImageRed(im, px);
125     g = gdImageGreen(im, px);
126     b = gdImageBlue(im, px);
127 
128     gdTestAssert(r == g && r == b);
129 
130     return r;
131 }/* getrgb*/
132 
whitecmp(gdImagePtr im1,gdImagePtr im2,int x,int y)133 int whitecmp(gdImagePtr im1, gdImagePtr im2, int x, int y) {
134     int w1, w2;
135 
136     w1 = getwhite(im1, x, y);
137     w2 = getwhite(im2, x, y);
138 
139     return abs(w1 - w2);
140 }/* whitediff*/
141 
do_crosstest()142 void do_crosstest()
143 {
144     gdImagePtr im = mkcross();
145     gdImagePtr blurred;
146     const int RADIUS = 16;
147 
148     gdTestAssert(!!im);
149 
150     save(im, "cross.png");
151 
152     blurred = gdImageCopyGaussianBlurred(im, RADIUS, 0.0);
153 	gdTestAssert(blurred != NULL);
154     save(blurred, "blurredcross.png");
155 
156     /* These spots shouldn't be affected. */
157     gdTestAssert(whitecmp(im, blurred, 5, 5) <= PIXEL_CLOSE_ENOUGH);
158     gdTestAssert(whitecmp(im, blurred, WIDTH-5, 5) <= PIXEL_CLOSE_ENOUGH);
159     gdTestAssert(whitecmp(im, blurred, 5, HEIGHT-5) <= PIXEL_CLOSE_ENOUGH);
160     gdTestAssert(whitecmp(im, blurred, WIDTH-5, HEIGHT-5) <= PIXEL_CLOSE_ENOUGH);
161 
162 //    printf("%d %d %d %d\n", whitecmp(im, blurred, 0, 0), whitecmp(im, blurred, WIDTH-1, 0),
163 //         whitecmp(im, blurred, 0, HEIGHT-1), whitecmp(im, blurred, WIDTH-1, HEIGHT-1));
164 
165     /* Ditto these, right in the corners */
166     gdTestAssert(whitecmp(im, blurred, 0, 0) <= PIXEL_CLOSE_ENOUGH);
167     gdTestAssert(whitecmp(im, blurred, WIDTH-1, 0) <= PIXEL_CLOSE_ENOUGH);
168     gdTestAssert(whitecmp(im, blurred, 0, HEIGHT-1) <= PIXEL_CLOSE_ENOUGH);
169     gdTestAssert(whitecmp(im, blurred, WIDTH-1, HEIGHT-1) <= PIXEL_CLOSE_ENOUGH);
170 
171     /* Now, poking let's poke around the blurred lines. */
172 
173     /* Vertical line gets darker when approached from the left. */
174     gdTestAssert(getwhite(blurred, 1, 1) > getwhite(blurred, LX - (HT - 1), 1));
175     gdTestAssert(getwhite(blurred, LX - 2, 1) > getwhite(blurred, LX - 1, 1));
176 
177     /* ...and lighter when moving away to the right. */
178     gdTestAssert(getwhite(blurred, LX + 2, 1) >= getwhite(blurred, LX + 1, 1));
179     gdTestAssert(getwhite(blurred, LX + 3, 1) >= getwhite(blurred, LX + 2, 1));
180     gdTestAssert(getwhite(blurred, WIDTH - 1, 1) > getwhite(blurred, LX + 1, 1));
181 
182     /* And the same way, vertically */
183     gdTestAssert(getwhite(blurred, 1, 1) > getwhite(blurred, 1, LY - (HT - 1)));
184     gdTestAssert(getwhite(blurred, 1, LY - (HT - 1)) > getwhite(blurred, 1, LY - (HT - 2)));
185 
186     gdTestAssert(getwhite(blurred, 1, LY)     <= getwhite(blurred, 1, LY + 1));
187     gdTestAssert(getwhite(blurred, 1, LY + 1) <  getwhite(blurred, 1, LY + 3));
188     gdTestAssert(getwhite(blurred, 1, LY + 3) <  getwhite(blurred, 1, HEIGHT-1));
189 	gdImageDestroy(blurred);
190 	gdImageDestroy(im);
191 }/* do_crosstest*/
192 
193 
main()194 int main()
195 {
196 
197     do_test();
198     do_crosstest();
199 
200     return gdNumFailures();
201 }
202