root/ext/gd/libgd/gd_rotate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gdImageSkewX
  2. gdImageSkewY
  3. gdImageRotate90
  4. gdImageRotate180
  5. gdImageRotate270
  6. gdImageRotate45
  7. gdImageRotate

   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 
 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) */
 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) */
 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 
 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 

/* [<][>][^][v][top][bottom][index][help] */