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