1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif /* HAVE_CONFIG_H */
4 
5 #include "gd.h"
6 #include "gd_intern.h"
7 #include <math.h>
8 
9 /*
10  * Rotate function Added on 2003/12
11  * by Pierre-Alain Joye (pierre@php.net)
12  **/
13 /* Begin rotate function */
14 #ifdef ROTATE_PI
15 #undef ROTATE_PI
16 #endif /* ROTATE_PI */
17 
18 typedef int (BGD_STDCALL *FuncPtr)(gdImagePtr, int, int);
19 
20 #define ROTATE_DEG2RAD  3.1415926535897932384626433832795/180
gdImageSkewX(gdImagePtr dst,gdImagePtr src,int uRow,int iOffset,double dWeight,int clrBack,int ignoretransparent)21 void gdImageSkewX (gdImagePtr dst, gdImagePtr src, int uRow, int iOffset, double dWeight, int clrBack, int ignoretransparent)
22 {
23 	int i, r, g, b, a, clrBackR, clrBackG, clrBackB, clrBackA;
24 	FuncPtr f;
25 
26 	int pxlOldLeft, pxlLeft=0, pxlSrc;
27 
28 	/* Keep clrBack as color index if required */
29 	if (src->trueColor) {
30 		pxlOldLeft = clrBack;
31 		f = gdImageGetTrueColorPixel;
32 	} else {
33 		pxlOldLeft = clrBack;
34 		clrBackR = gdImageRed(src, clrBack);
35 		clrBackG = gdImageGreen(src, clrBack);
36 		clrBackB = gdImageBlue(src, clrBack);
37 		clrBackA = gdImageAlpha(src, clrBack);
38 		clrBack =  gdTrueColorAlpha(clrBackR, clrBackG, clrBackB, clrBackA);
39 		f = gdImageGetPixel;
40 	}
41 
42 	for (i = 0; i < iOffset; i++) {
43 		gdImageSetPixel (dst, i, uRow, clrBack);
44 	}
45 
46 	if (i < dst->sx) {
47 		gdImageSetPixel (dst, i, uRow, clrBack);
48 	}
49 
50 	for (i = 0; i < src->sx; i++) {
51 		pxlSrc = f (src,i,uRow);
52 
53 		r = (int)(gdImageRed(src,pxlSrc) * dWeight);
54 		g = (int)(gdImageGreen(src,pxlSrc) * dWeight);
55 		b = (int)(gdImageBlue(src,pxlSrc) * dWeight);
56 		a = (int)(gdImageAlpha(src,pxlSrc) * dWeight);
57 
58 		if (r>255) {
59 			r = 255;
60 		}
61 
62 		if (g>255) {
63 			g = 255;
64 		}
65 
66 		if (b>255) {
67 			b = 255;
68 		}
69 
70 		if (a>127) {
71 			a = 127;
72 		}
73 
74 		pxlLeft = gdTrueColorAlpha(r, g, b, a);
75 
76 		r = gdImageRed(src,pxlSrc)   - (r - gdImageRed(src,pxlOldLeft));
77 		g = gdImageGreen(src,pxlSrc) - (g - gdImageGreen(src,pxlOldLeft));
78 		b = gdImageBlue(src,pxlSrc)  - (b - gdImageBlue(src,pxlOldLeft));
79 		a = gdImageAlpha(src,pxlSrc) - (a - gdImageAlpha(src,pxlOldLeft));
80 
81 		if (r>255) {
82 			r = 255;
83 		}
84 
85 		if (g>255) {
86 			g = 255;
87 		}
88 
89 		if (b>255) {
90 			b = 255;
91 		}
92 
93 		if (a>127) {
94 			a = 127;
95 		}
96 
97 		if (ignoretransparent && pxlSrc == dst->transparent) {
98 			pxlSrc = dst->transparent;
99 		} else {
100 			pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a);
101 
102 			if (pxlSrc == -1) {
103 				pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a);
104 			}
105 		}
106 
107 		if ((i + iOffset >= 0) && (i + iOffset < dst->sx)) {
108 			gdImageSetPixel (dst, i+iOffset, uRow,  pxlSrc);
109 		}
110 
111 		pxlOldLeft = pxlLeft;
112 	}
113 
114 	i += iOffset;
115 
116 	if (i < dst->sx) {
117 		gdImageSetPixel (dst, i, uRow, pxlLeft);
118 	}
119 
120 	gdImageSetPixel (dst, iOffset, uRow, clrBack);
121 
122 	i--;
123 
124 	while (++i < dst->sx) {
125 		gdImageSetPixel (dst, i, uRow, clrBack);
126 	}
127 }
128 
gdImageSkewY(gdImagePtr dst,gdImagePtr src,int uCol,int iOffset,double dWeight,int clrBack,int ignoretransparent)129 void gdImageSkewY (gdImagePtr dst, gdImagePtr src, int uCol, int iOffset, double dWeight, int clrBack, int ignoretransparent)
130 {
131 	int i, iYPos=0, r, g, b, a;
132 	FuncPtr f;
133 	int pxlOldLeft, pxlLeft=0, pxlSrc;
134 
135 	if (src->trueColor) {
136 		f = gdImageGetTrueColorPixel;
137 	} else {
138 		f = gdImageGetPixel;
139 	}
140 
141 	for (i = 0; i<=iOffset; i++) {
142 		gdImageSetPixel (dst, uCol, i, clrBack);
143 	}
144 	r = (int)((double)gdImageRed(src,clrBack) * dWeight);
145 	g = (int)((double)gdImageGreen(src,clrBack) * dWeight);
146 	b = (int)((double)gdImageBlue(src,clrBack) * dWeight);
147 	a = (int)((double)gdImageAlpha(src,clrBack) * dWeight);
148 
149 	pxlOldLeft = gdImageColorAllocateAlpha(dst, r, g, b, a);
150 
151 	for (i = 0; i < src->sy; i++) {
152 		pxlSrc = f (src, uCol, i);
153 		iYPos = i + iOffset;
154 
155 		r = (int)((double)gdImageRed(src,pxlSrc) * dWeight);
156 		g = (int)((double)gdImageGreen(src,pxlSrc) * dWeight);
157 		b = (int)((double)gdImageBlue(src,pxlSrc) * dWeight);
158 		a = (int)((double)gdImageAlpha(src,pxlSrc) * dWeight);
159 
160 		if (r>255) {
161         	r = 255;
162 		}
163 
164 		if (g>255) {
165 			g = 255;
166 		}
167 
168 		if (b>255) {
169     			b = 255;
170 		}
171 
172 		if (a>127) {
173 			a = 127;
174 		}
175 
176 		pxlLeft = gdTrueColorAlpha(r, g, b, a);
177 
178 		r = gdImageRed(src,pxlSrc)   - (r - gdImageRed(src,pxlOldLeft));
179 		g = gdImageGreen(src,pxlSrc) - (g - gdImageGreen(src,pxlOldLeft));
180 		b = gdImageBlue(src,pxlSrc)  - (b - gdImageBlue(src,pxlOldLeft));
181 		a = gdImageAlpha(src,pxlSrc) - (a - gdImageAlpha(src,pxlOldLeft));
182 
183 		if (r>255) {
184         	r = 255;
185 		}
186 
187 		if (g>255) {
188 			g = 255;
189 		}
190 
191 		if (b>255) {
192     			b = 255;
193 		}
194 
195 		if (a>127) {
196 			a = 127;
197 		}
198 
199 		if (ignoretransparent && pxlSrc == dst->transparent) {
200 			pxlSrc = dst->transparent;
201 		} else {
202 			pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a);
203 
204 			if (pxlSrc == -1) {
205 				pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a);
206 			}
207 		}
208 
209 		if ((iYPos >= 0) && (iYPos < dst->sy)) {
210 			gdImageSetPixel (dst, uCol, iYPos, pxlSrc);
211 		}
212 
213 		pxlOldLeft = pxlLeft;
214 	}
215 
216 	i = iYPos;
217 	if (i < dst->sy) {
218 		gdImageSetPixel (dst, uCol, i, pxlLeft);
219 	}
220 
221 	i--;
222 	while (++i < dst->sy) {
223 		gdImageSetPixel (dst, uCol, i, clrBack);
224 	}
225 }
226 
227 /* Rotates an image by 90 degrees (counter clockwise) */
gdImageRotate90(gdImagePtr src,int ignoretransparent)228 gdImagePtr gdImageRotate90 (gdImagePtr src, int ignoretransparent)
229 {
230 	int uY, uX;
231 	int c,r,g,b,a;
232 	gdImagePtr dst;
233 	FuncPtr f;
234 
235 	if (src->trueColor) {
236 		f = gdImageGetTrueColorPixel;
237 	} else {
238 		f = gdImageGetPixel;
239 	}
240 	dst = gdImageCreateTrueColor(src->sy, src->sx);
241 	if (dst != NULL) {
242 		int old_blendmode = dst->alphaBlendingFlag;
243 		dst->alphaBlendingFlag = 0;
244 
245 		dst->transparent = src->transparent;
246 
247 		gdImagePaletteCopy (dst, src);
248 
249 		for (uY = 0; uY<src->sy; uY++) {
250 			for (uX = 0; uX<src->sx; uX++) {
251 				c = f (src, uX, uY);
252 				if (!src->trueColor) {
253 					r = gdImageRed(src,c);
254 					g = gdImageGreen(src,c);
255 					b = gdImageBlue(src,c);
256 					a = gdImageAlpha(src,c);
257 					c = gdTrueColorAlpha(r, g, b, a);
258 				}
259 				if (ignoretransparent && c == dst->transparent) {
260 					gdImageSetPixel(dst, uY, (dst->sy - uX - 1), dst->transparent);
261 				} else {
262 					gdImageSetPixel(dst, uY, (dst->sy - uX - 1), c);
263 				}
264 			}
265 		}
266 		dst->alphaBlendingFlag = old_blendmode;
267 	}
268 
269 	return dst;
270 }
271 
272 /* Rotates an image by 180 degrees (counter clockwise) */
gdImageRotate180(gdImagePtr src,int ignoretransparent)273 gdImagePtr gdImageRotate180 (gdImagePtr src, int ignoretransparent)
274 {
275 	int uY, uX;
276 	int c,r,g,b,a;
277 	gdImagePtr dst;
278 	FuncPtr f;
279 
280 	if (src->trueColor) {
281 		f = gdImageGetTrueColorPixel;
282 	} else {
283 		f = gdImageGetPixel;
284 	}
285 	dst = gdImageCreateTrueColor(src->sx, src->sy);
286 
287 	if (dst != NULL) {
288 		int old_blendmode = dst->alphaBlendingFlag;
289 		dst->alphaBlendingFlag = 0;
290 
291 		dst->transparent = src->transparent;
292 
293 		gdImagePaletteCopy (dst, src);
294 
295 		for (uY = 0; uY<src->sy; uY++) {
296 			for (uX = 0; uX<src->sx; uX++) {
297 				c = f (src, uX, uY);
298 				if (!src->trueColor) {
299 					r = gdImageRed(src,c);
300 					g = gdImageGreen(src,c);
301 					b = gdImageBlue(src,c);
302 					a = gdImageAlpha(src,c);
303 					c = gdTrueColorAlpha(r, g, b, a);
304 				}
305 
306 				if (ignoretransparent && c == dst->transparent) {
307 					gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), dst->transparent);
308 				} else {
309 					gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), c);
310 				}
311 			}
312 		}
313 		dst->alphaBlendingFlag = old_blendmode;
314 	}
315 
316 	return dst;
317 }
318 
319 /* Rotates an image by 270 degrees (counter clockwise) */
gdImageRotate270(gdImagePtr src,int ignoretransparent)320 gdImagePtr gdImageRotate270 (gdImagePtr src, int ignoretransparent)
321 {
322 	int uY, uX;
323 	int c,r,g,b,a;
324 	gdImagePtr dst;
325 	FuncPtr f;
326 
327 	if (src->trueColor) {
328 		f = gdImageGetTrueColorPixel;
329 	} else {
330 		f = gdImageGetPixel;
331 	}
332 	dst = gdImageCreateTrueColor (src->sy, src->sx);
333 
334 	if (dst != NULL) {
335 		int old_blendmode = dst->alphaBlendingFlag;
336 		dst->alphaBlendingFlag = 0;
337 
338 		dst->transparent = src->transparent;
339 
340 		gdImagePaletteCopy (dst, src);
341 
342 		for (uY = 0; uY<src->sy; uY++) {
343 			for (uX = 0; uX<src->sx; uX++) {
344 				c = f (src, uX, uY);
345 				if (!src->trueColor) {
346 					r = gdImageRed(src,c);
347 					g = gdImageGreen(src,c);
348 					b = gdImageBlue(src,c);
349 					a = gdImageAlpha(src,c);
350 					c = gdTrueColorAlpha(r, g, b, a);
351 				}
352 
353 				if (ignoretransparent && c == dst->transparent) {
354 					gdImageSetPixel(dst, (dst->sx - uY - 1), uX, dst->transparent);
355 				} else {
356 					gdImageSetPixel(dst, (dst->sx - uY - 1), uX, c);
357 				}
358 			}
359 		}
360 		dst->alphaBlendingFlag = old_blendmode;
361 	}
362 
363 	return dst;
364 }
365