Annotation of embedaddon/php/ext/gd/libgd/gd_rotate.c, revision 1.1.1.1
1.1 misho 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
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:
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) */
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: dst->transparent = src->transparent;
220:
221: if (dst != NULL) {
222: int old_blendmode = dst->alphaBlendingFlag;
223: dst->alphaBlendingFlag = 0;
224:
225: gdImagePaletteCopy (dst, src);
226:
227: for (uY = 0; uY<src->sy; uY++) {
228: for (uX = 0; uX<src->sx; uX++) {
229: c = f (src, uX, uY);
230: if (!src->trueColor) {
231: r = gdImageRed(src,c);
232: g = gdImageGreen(src,c);
233: b = gdImageBlue(src,c);
234: a = gdImageAlpha(src,c);
235: c = gdTrueColorAlpha(r, g, b, a);
236: }
237: if (ignoretransparent && c == dst->transparent) {
238: gdImageSetPixel(dst, uY, (dst->sy - uX - 1), dst->transparent);
239: } else {
240: gdImageSetPixel(dst, uY, (dst->sy - uX - 1), c);
241: }
242: }
243: }
244: dst->alphaBlendingFlag = old_blendmode;
245: }
246:
247: return dst;
248: }
249:
250: /* Rotates an image by 180 degrees (counter clockwise) */
251: gdImagePtr gdImageRotate180 (gdImagePtr src, int ignoretransparent)
252: {
253: int uY, uX;
254: int c,r,g,b,a;
255: gdImagePtr dst;
256: typedef int (*FuncPtr)(gdImagePtr, int, int);
257: FuncPtr f;
258:
259: if (src->trueColor) {
260: f = gdImageGetTrueColorPixel;
261: } else {
262: f = gdImageGetPixel;
263: }
264: dst = gdImageCreateTrueColor(src->sx, src->sy);
265: dst->transparent = src->transparent;
266:
267: if (dst != NULL) {
268: int old_blendmode = dst->alphaBlendingFlag;
269: dst->alphaBlendingFlag = 0;
270:
271: gdImagePaletteCopy (dst, src);
272:
273: for (uY = 0; uY<src->sy; uY++) {
274: for (uX = 0; uX<src->sx; uX++) {
275: c = f (src, uX, uY);
276: if (!src->trueColor) {
277: r = gdImageRed(src,c);
278: g = gdImageGreen(src,c);
279: b = gdImageBlue(src,c);
280: a = gdImageAlpha(src,c);
281: c = gdTrueColorAlpha(r, g, b, a);
282: }
283:
284: if (ignoretransparent && c == dst->transparent) {
285: gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), dst->transparent);
286: } else {
287: gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), c);
288: }
289: }
290: }
291: dst->alphaBlendingFlag = old_blendmode;
292: }
293:
294: return dst;
295: }
296:
297: /* Rotates an image by 270 degrees (counter clockwise) */
298: gdImagePtr gdImageRotate270 (gdImagePtr src, int ignoretransparent)
299: {
300: int uY, uX;
301: int c,r,g,b,a;
302: gdImagePtr dst;
303: typedef int (*FuncPtr)(gdImagePtr, int, int);
304: FuncPtr f;
305:
306: if (src->trueColor) {
307: f = gdImageGetTrueColorPixel;
308: } else {
309: f = gdImageGetPixel;
310: }
311: dst = gdImageCreateTrueColor (src->sy, src->sx);
312: dst->transparent = src->transparent;
313:
314: if (dst != NULL) {
315: int old_blendmode = dst->alphaBlendingFlag;
316: dst->alphaBlendingFlag = 0;
317:
318: gdImagePaletteCopy (dst, src);
319:
320: for (uY = 0; uY<src->sy; uY++) {
321: for (uX = 0; uX<src->sx; uX++) {
322: c = f (src, uX, uY);
323: if (!src->trueColor) {
324: r = gdImageRed(src,c);
325: g = gdImageGreen(src,c);
326: b = gdImageBlue(src,c);
327: a = gdImageAlpha(src,c);
328: c = gdTrueColorAlpha(r, g, b, a);
329: }
330:
331: if (ignoretransparent && c == dst->transparent) {
332: gdImageSetPixel(dst, (dst->sx - uY - 1), uX, dst->transparent);
333: } else {
334: gdImageSetPixel(dst, (dst->sx - uY - 1), uX, c);
335: }
336: }
337: }
338: dst->alphaBlendingFlag = old_blendmode;
339: }
340:
341: return dst;
342: }
343:
344: gdImagePtr gdImageRotate45 (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent)
345: {
346: typedef int (*FuncPtr)(gdImagePtr, int, int);
347: gdImagePtr dst1,dst2,dst3;
348: FuncPtr f;
349: double dRadAngle, dSinE, dTan, dShear;
350: double dOffset; /* Variable skew offset */
351: int u, iShear, newx, newy;
352: int clrBackR, clrBackG, clrBackB, clrBackA;
353:
354: /* See GEMS I for the algorithm details */
355: dRadAngle = dAngle * ROTATE_DEG2RAD; /* Angle in radians */
356: dSinE = sin (dRadAngle);
357: dTan = tan (dRadAngle / 2.0);
358:
359: newx = (int)(src->sx + src->sy * fabs(dTan));
360: newy = src->sy;
361:
362: /* 1st shear */
363: if (src->trueColor) {
364: f = gdImageGetTrueColorPixel;
365: } else {
366: f = gdImageGetPixel;
367: }
368:
369: dst1 = gdImageCreateTrueColor(newx, newy);
370: /******* Perform 1st shear (horizontal) ******/
371: if (dst1 == NULL) {
372: return NULL;
373: }
374: #ifdef HAVE_GD_BUNDLED
375: dst1->alphaBlendingFlag = gdEffectReplace;
376: #else
377: gdImageAlphaBlending(dst1, 0);
378: #endif
379: if (dAngle == 0.0) {
380: /* Returns copy of src */
381: gdImageCopy (dst1, src,0,0,0,0,src->sx,src->sy);
382: return dst1;
383: }
384:
385: gdImagePaletteCopy (dst1, src);
386:
387: if (ignoretransparent) {
388: if (gdImageTrueColor(src)) {
389: dst1->transparent = src->transparent;
390: } else {
391:
392: dst1->transparent = gdTrueColorAlpha(gdImageRed(src, src->transparent), gdImageBlue(src, src->transparent), gdImageGreen(src, src->transparent), 127);
393: }
394: }
395:
396: dRadAngle = dAngle * ROTATE_DEG2RAD; /* Angle in radians */
397: dSinE = sin (dRadAngle);
398: dTan = tan (dRadAngle / 2.0);
399:
400: for (u = 0; u < dst1->sy; u++) {
401: if (dTan >= 0.0) {
402: dShear = ((double)(u + 0.5)) * dTan;
403: } else {
404: dShear = ((double)(u - dst1->sy) + 0.5) * dTan;
405: }
406:
407: iShear = (int)floor(dShear);
408: gdImageSkewX(dst1, src, u, iShear, (dShear - iShear), clrBack, ignoretransparent);
409: }
410:
411: /*
412: The 1st shear may use the original clrBack as color index
413: Convert it once here
414: */
415: if(!src->trueColor) {
416: clrBackR = gdImageRed(src, clrBack);
417: clrBackG = gdImageGreen(src, clrBack);
418: clrBackB = gdImageBlue(src, clrBack);
419: clrBackA = gdImageAlpha(src, clrBack);
420: clrBack = gdTrueColorAlpha(clrBackR, clrBackG, clrBackB, clrBackA);
421: }
422: /* 2nd shear */
423: newx = dst1->sx;
424:
425: if (dSinE > 0.0) {
426: dOffset = (src->sx-1) * dSinE;
427: } else {
428: dOffset = -dSinE * (src->sx - newx);
429: }
430:
431: newy = (int) ((double) src->sx * fabs( dSinE ) + (double) src->sy * cos (dRadAngle))+1;
432:
433: if (src->trueColor) {
434: f = gdImageGetTrueColorPixel;
435: } else {
436: f = gdImageGetPixel;
437: }
438: dst2 = gdImageCreateTrueColor(newx, newy);
439: if (dst2 == NULL) {
440: gdImageDestroy(dst1);
441: return NULL;
442: }
443:
444: #ifdef HAVE_GD_BUNDLED
445: dst2->alphaBlendingFlag = gdEffectReplace;
446: #else
447: gdImageAlphaBlending(dst2, 0);
448: #endif
449:
450: if (ignoretransparent) {
451: dst2->transparent = dst1->transparent;
452: }
453:
454: for (u = 0; u < dst2->sx; u++, dOffset -= dSinE) {
455: iShear = (int)floor (dOffset);
456: gdImageSkewY(dst2, dst1, u, iShear, (dOffset - (double)iShear), clrBack, ignoretransparent);
457: }
458:
459: /* 3rd shear */
460: gdImageDestroy(dst1);
461:
462: newx = (int) ((double)src->sy * fabs (dSinE) + (double)src->sx * cos (dRadAngle)) + 1;
463: newy = dst2->sy;
464:
465: if (src->trueColor) {
466: f = gdImageGetTrueColorPixel;
467: } else {
468: f = gdImageGetPixel;
469: }
470: dst3 = gdImageCreateTrueColor(newx, newy);
471: if (dst3 == NULL) {
472: gdImageDestroy(dst2);
473: return NULL;
474: }
475:
476: #ifdef HAVE_GD_BUNDLED
477: dst3->alphaBlendingFlag = gdEffectReplace;
478: #else
479: gdImageAlphaBlending(dst3, 0);
480: #endif
481:
482: if (ignoretransparent) {
483: dst3->transparent = dst2->transparent;
484: }
485:
486: if (dSinE >= 0.0) {
487: dOffset = (double)(src->sx - 1) * dSinE * -dTan;
488: } else {
489: dOffset = dTan * ((double)(src->sx - 1) * -dSinE + (double)(1 - newy));
490: }
491:
492: for (u = 0; u < dst3->sy; u++, dOffset += dTan) {
493: int iShear = (int)floor(dOffset);
494: gdImageSkewX(dst3, dst2, u, iShear, (dOffset - iShear), clrBack, ignoretransparent);
495: }
496:
497: gdImageDestroy(dst2);
498:
499: return dst3;
500: }
501:
502: gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent)
503: {
504: gdImagePtr pMidImg;
505: gdImagePtr rotatedImg;
506:
507: if (src == NULL) {
508: return NULL;
509: }
510:
511: if (!gdImageTrueColor(src) && (clrBack < 0 || clrBack>=gdImageColorsTotal(src))) {
512: return NULL;
513: }
514:
515: while (dAngle >= 360.0) {
516: dAngle -= 360.0;
517: }
518:
519: while (dAngle < 0) {
520: dAngle += 360.0;
521: }
522:
523: if (dAngle == 90.00) {
524: return gdImageRotate90(src, ignoretransparent);
525: }
526: if (dAngle == 180.00) {
527: return gdImageRotate180(src, ignoretransparent);
528: }
529: if(dAngle == 270.00) {
530: return gdImageRotate270 (src, ignoretransparent);
531: }
532:
533: if ((dAngle > 45.0) && (dAngle <= 135.0)) {
534: pMidImg = gdImageRotate90 (src, ignoretransparent);
535: dAngle -= 90.0;
536: } else if ((dAngle > 135.0) && (dAngle <= 225.0)) {
537: pMidImg = gdImageRotate180 (src, ignoretransparent);
538: dAngle -= 180.0;
539: } else if ((dAngle > 225.0) && (dAngle <= 315.0)) {
540: pMidImg = gdImageRotate270 (src, ignoretransparent);
541: dAngle -= 270.0;
542: } else {
543: return gdImageRotate45 (src, dAngle, clrBack, ignoretransparent);
544: }
545:
546: if (pMidImg == NULL) {
547: return NULL;
548: }
549:
550: rotatedImg = gdImageRotate45 (pMidImg, dAngle, clrBack, ignoretransparent);
551: gdImageDestroy(pMidImg);
552:
553: return rotatedImg;
554: }
555: /* End Rotate function */
556:
557:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>