Annotation of embedaddon/php/ext/gd/libgd/gd_rotate.c, revision 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>