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