Annotation of embedaddon/php/ext/gd/libgd/gd_rotate.c, revision 1.1.1.2
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:
220: if (dst != NULL) {
221: int old_blendmode = dst->alphaBlendingFlag;
222: dst->alphaBlendingFlag = 0;
223:
1.1.1.2 ! misho 224: dst->transparent = src->transparent;
! 225:
1.1 misho 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) */
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:
1.1.1.2 ! misho 271: dst->transparent = src->transparent;
! 272:
1.1 misho 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) */
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:
1.1.1.2 ! misho 319: dst->transparent = src->transparent;
! 320:
1.1 misho 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:
347: gdImagePtr gdImageRotate45 (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent)
348: {
349: typedef int (*FuncPtr)(gdImagePtr, int, int);
350: gdImagePtr dst1,dst2,dst3;
351: FuncPtr f;
352: double dRadAngle, dSinE, dTan, dShear;
353: double dOffset; /* Variable skew offset */
354: int u, iShear, newx, newy;
355: int clrBackR, clrBackG, clrBackB, clrBackA;
356:
357: /* See GEMS I for the algorithm details */
358: dRadAngle = dAngle * ROTATE_DEG2RAD; /* Angle in radians */
359: dSinE = sin (dRadAngle);
360: dTan = tan (dRadAngle / 2.0);
361:
362: newx = (int)(src->sx + src->sy * fabs(dTan));
363: newy = src->sy;
364:
365: /* 1st shear */
366: if (src->trueColor) {
367: f = gdImageGetTrueColorPixel;
368: } else {
369: f = gdImageGetPixel;
370: }
371:
372: dst1 = gdImageCreateTrueColor(newx, newy);
373: /******* Perform 1st shear (horizontal) ******/
374: if (dst1 == NULL) {
375: return NULL;
376: }
377: #ifdef HAVE_GD_BUNDLED
378: dst1->alphaBlendingFlag = gdEffectReplace;
379: #else
380: gdImageAlphaBlending(dst1, 0);
381: #endif
382: if (dAngle == 0.0) {
383: /* Returns copy of src */
384: gdImageCopy (dst1, src,0,0,0,0,src->sx,src->sy);
385: return dst1;
386: }
387:
388: gdImagePaletteCopy (dst1, src);
389:
390: if (ignoretransparent) {
391: if (gdImageTrueColor(src)) {
392: dst1->transparent = src->transparent;
393: } else {
394:
395: dst1->transparent = gdTrueColorAlpha(gdImageRed(src, src->transparent), gdImageBlue(src, src->transparent), gdImageGreen(src, src->transparent), 127);
396: }
397: }
398:
399: dRadAngle = dAngle * ROTATE_DEG2RAD; /* Angle in radians */
400: dSinE = sin (dRadAngle);
401: dTan = tan (dRadAngle / 2.0);
402:
403: for (u = 0; u < dst1->sy; u++) {
404: if (dTan >= 0.0) {
405: dShear = ((double)(u + 0.5)) * dTan;
406: } else {
407: dShear = ((double)(u - dst1->sy) + 0.5) * dTan;
408: }
409:
410: iShear = (int)floor(dShear);
411: gdImageSkewX(dst1, src, u, iShear, (dShear - iShear), clrBack, ignoretransparent);
412: }
413:
414: /*
415: The 1st shear may use the original clrBack as color index
416: Convert it once here
417: */
418: if(!src->trueColor) {
419: clrBackR = gdImageRed(src, clrBack);
420: clrBackG = gdImageGreen(src, clrBack);
421: clrBackB = gdImageBlue(src, clrBack);
422: clrBackA = gdImageAlpha(src, clrBack);
423: clrBack = gdTrueColorAlpha(clrBackR, clrBackG, clrBackB, clrBackA);
424: }
425: /* 2nd shear */
426: newx = dst1->sx;
427:
428: if (dSinE > 0.0) {
429: dOffset = (src->sx-1) * dSinE;
430: } else {
431: dOffset = -dSinE * (src->sx - newx);
432: }
433:
434: newy = (int) ((double) src->sx * fabs( dSinE ) + (double) src->sy * cos (dRadAngle))+1;
435:
436: if (src->trueColor) {
437: f = gdImageGetTrueColorPixel;
438: } else {
439: f = gdImageGetPixel;
440: }
441: dst2 = gdImageCreateTrueColor(newx, newy);
442: if (dst2 == NULL) {
443: gdImageDestroy(dst1);
444: return NULL;
445: }
446:
447: #ifdef HAVE_GD_BUNDLED
448: dst2->alphaBlendingFlag = gdEffectReplace;
449: #else
450: gdImageAlphaBlending(dst2, 0);
451: #endif
452:
453: if (ignoretransparent) {
454: dst2->transparent = dst1->transparent;
455: }
456:
457: for (u = 0; u < dst2->sx; u++, dOffset -= dSinE) {
458: iShear = (int)floor (dOffset);
459: gdImageSkewY(dst2, dst1, u, iShear, (dOffset - (double)iShear), clrBack, ignoretransparent);
460: }
461:
462: /* 3rd shear */
463: gdImageDestroy(dst1);
464:
465: newx = (int) ((double)src->sy * fabs (dSinE) + (double)src->sx * cos (dRadAngle)) + 1;
466: newy = dst2->sy;
467:
468: if (src->trueColor) {
469: f = gdImageGetTrueColorPixel;
470: } else {
471: f = gdImageGetPixel;
472: }
473: dst3 = gdImageCreateTrueColor(newx, newy);
474: if (dst3 == NULL) {
475: gdImageDestroy(dst2);
476: return NULL;
477: }
478:
479: #ifdef HAVE_GD_BUNDLED
480: dst3->alphaBlendingFlag = gdEffectReplace;
481: #else
482: gdImageAlphaBlending(dst3, 0);
483: #endif
484:
485: if (ignoretransparent) {
486: dst3->transparent = dst2->transparent;
487: }
488:
489: if (dSinE >= 0.0) {
490: dOffset = (double)(src->sx - 1) * dSinE * -dTan;
491: } else {
492: dOffset = dTan * ((double)(src->sx - 1) * -dSinE + (double)(1 - newy));
493: }
494:
495: for (u = 0; u < dst3->sy; u++, dOffset += dTan) {
496: int iShear = (int)floor(dOffset);
497: gdImageSkewX(dst3, dst2, u, iShear, (dOffset - iShear), clrBack, ignoretransparent);
498: }
499:
500: gdImageDestroy(dst2);
501:
502: return dst3;
503: }
504:
505: gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent)
506: {
507: gdImagePtr pMidImg;
508: gdImagePtr rotatedImg;
509:
510: if (src == NULL) {
511: return NULL;
512: }
513:
514: if (!gdImageTrueColor(src) && (clrBack < 0 || clrBack>=gdImageColorsTotal(src))) {
515: return NULL;
516: }
517:
518: while (dAngle >= 360.0) {
519: dAngle -= 360.0;
520: }
521:
522: while (dAngle < 0) {
523: dAngle += 360.0;
524: }
525:
526: if (dAngle == 90.00) {
527: return gdImageRotate90(src, ignoretransparent);
528: }
529: if (dAngle == 180.00) {
530: return gdImageRotate180(src, ignoretransparent);
531: }
532: if(dAngle == 270.00) {
533: return gdImageRotate270 (src, ignoretransparent);
534: }
535:
536: if ((dAngle > 45.0) && (dAngle <= 135.0)) {
537: pMidImg = gdImageRotate90 (src, ignoretransparent);
538: dAngle -= 90.0;
539: } else if ((dAngle > 135.0) && (dAngle <= 225.0)) {
540: pMidImg = gdImageRotate180 (src, ignoretransparent);
541: dAngle -= 180.0;
542: } else if ((dAngle > 225.0) && (dAngle <= 315.0)) {
543: pMidImg = gdImageRotate270 (src, ignoretransparent);
544: dAngle -= 270.0;
545: } else {
546: return gdImageRotate45 (src, dAngle, clrBack, ignoretransparent);
547: }
548:
549: if (pMidImg == NULL) {
550: return NULL;
551: }
552:
553: rotatedImg = gdImageRotate45 (pMidImg, dAngle, clrBack, ignoretransparent);
554: gdImageDestroy(pMidImg);
555:
556: return rotatedImg;
557: }
558: /* End Rotate function */
559:
560:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>