function imagerotate(&$srcImg, $angle, $bgcolor, $ignore_transparent = 0) { function rotateX($x, $y, $theta) { return $x * cos($theta) - $y * sin($theta); } function rotateY($x, $y, $theta) { return $x * sin($theta) + $y * cos($theta); } $srcw = imagesx($srcImg); $srch = imagesy($srcImg); if ($angle == 0) { return $srcImg; } // Convert the angle to radians $theta = deg2rad($angle); // Calculate the width of the destination image. $temp = array(rotateX(0, 0, 0 - $theta), rotateX($srcw, 0, 0 - $theta), rotateX(0, $srch, 0 - $theta), rotateX($srcw, $srch, 0 - $theta)); $minX = floor(min($temp)); $maxX = ceil(max($temp)); $width = $maxX - $minX; // Calculate the height of the destination image. $temp = array(rotateY(0, 0, 0 - $theta), rotateY($srcw, 0, 0 - $theta), rotateY(0, $srch, 0 - $theta), rotateY($srcw, $srch, 0 - $theta)); $minY = floor(min($temp)); $maxY = ceil(max($temp)); $height = $maxY - $minY; $destimg = imagecreatetruecolor($width, $height); imagefill($destimg, 0, 0, imagecolorallocate($destimg, 0, 255, 0)); // sets all pixels in the new image for ($x = $minX; $x < $maxX; $x++) { for ($y = $minY; $y < $maxY; $y++) { // fetch corresponding pixel from the source image $srcX = round(rotateX($x, $y, $theta)); $srcY = round(rotateY($x, $y, $theta)); if ($srcX >= 0 && $srcX < $srcw && $srcY >= 0 && $srcY < $srch) { $color = imagecolorat($srcImg, $srcX, $srcY); } else { $color = $bgcolor; } imagesetpixel($destimg, $x - $minX, $y - $minY, $color); } } return $destimg; }
/** * imagerotate() does not appear in PHP with non-bundled GD libraries. * Because this is written in PHP, it is much slower than the bundled version. * * @param resource $srcImg an image resource * @param float $angle rotation angle, in degrees * @param int $bgColor specifies the color of the uncovered zone after the rotation * @param int $ignoreTransparent if set and non-zero, transparent colors are ignored. Default: 0. * @return resource image resource for the rotated image * @access private */ private function imagerotate($srcImg, $angle, $bgColor, $ignoreTransparent = 0) { function rotateX($x, $y, $theta) { return $x * cos($theta) - $y * sin($theta); } function rotateY($x, $y, $theta) { return $x * sin($theta) + $y * cos($theta); } $srcW = imagesx($srcImg); $srcH = imagesy($srcImg); // Normalize angle $angle %= 360; if ($angle == 0) { if ($ignoreTransparent == 0) { imagesavealpha($srcImg, true); } return $srcImg; } // Convert the angle to radians $theta = deg2rad($angle); $minX = $maxX = $minY = $maxY = 0; // Standard case of rotate if (abs($angle) == 90 || abs($angle) == 270) { $width = $srcH; $height = $srcW; if ($angle == 90 || $angle == -270) { $minX = 0; $maxX = $width; $minY = -$height + 1; $maxY = 1; } else { if ($angle == -90 || $angle == 270) { $minX = -$width + 1; $maxX = 1; $minY = 0; $maxY = $height; } } } else { if (abs($angle) === 180) { $width = $srcW; $height = $srcH; $minX = -$width + 1; $maxX = 1; $minY = -$height + 1; $maxY = 1; } else { // Calculate the width of the destination image $temp = array(rotateX(0, 0, 0 - $theta), rotateX($srcW, 0, 0 - $theta), rotateX(0, $srcH, 0 - $theta), rotateX($srcW, $srcH, 0 - $theta)); $minX = floor(min($temp)); $maxX = ceil(max($temp)); $width = $maxX - $minX; // Calculate the height of the destination image $temp = array(rotateY(0, 0, 0 - $theta), rotateY($srcW, 0, 0 - $theta), rotateY(0, $srcH, 0 - $theta), rotateY($srcW, $srcH, 0 - $theta)); $minY = floor(min($temp)); $maxY = ceil(max($temp)); $height = $maxY - $minY; } } $destImg = imagecreatetruecolor($width, $height); if ($ignoreTransparent == 0) { imagefill($destImg, 0, 0, imagecolorallocatealpha($destImg, 255, 255, 255, 127)); imagesavealpha($destImg, true); } // Sets all pixels in the new image for ($x = $minX; $x < $maxX; $x++) { for ($y = $minY; $y < $maxY; $y++) { // Fetch corresponding pixel from the source image $srcX = round(rotateX($x, $y, $theta)); $srcY = round(rotateY($x, $y, $theta)); if ($srcX >= 0 && $srcX < $srcW && $srcY >= 0 && $srcY < $srcH) { $color = imagecolorat($srcImg, $srcX, $srcY); } else { $color = $bgColor; } imagesetpixel($destImg, $x - $minX, $y - $minY, $color); } } return $destImg; }