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