PHP Conference Japan 2024

imagerotate

(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)

imagerotate以指定的角度旋轉影像

描述

imagerotate(GdImage $image, float $angle, int $background_color): GdImage|false

使用指定的 angle 角度(以度為單位)旋轉 image 影像。

旋轉中心是影像的中心,旋轉後的影像尺寸可能會與原始影像不同。

參數

image

一個 GdImage 物件,由影像建立函數(例如 imagecreatetruecolor())傳回。

angle

旋轉角度,以度為單位。旋轉角度被解釋為影像逆時針旋轉的度數。

background_color

指定旋轉後未覆蓋區域的顏色

傳回值

成功時傳回旋轉後影像的影像物件,失敗時傳回 false

更新日誌

版本 描述
8.3.0 已完全移除未使用的 ignore_transparent
8.0.0 成功時,此函數現在會傳回 GDImage 實例;先前傳回的是 resource
8.0.0 image 現在需要 GdImage 實例;先前需要有效的 gd resource
8.0.0 未使用的 ignore_transparent 現在需要 bool;先前需要 int

範例

範例 #1 以 180 度旋轉影像

此範例將影像旋轉 180 度 - 上下顛倒。

<?php
// 檔案和旋轉
$filename = 'test.jpg';
$degrees = 180;

// 內容類型
header('Content-type: image/jpeg');

// 載入
$source = imagecreatefromjpeg($filename);

// 旋轉
$rotate = imagerotate($source, $degrees, 0);

// 輸出
imagejpeg($rotate);

// 釋放記憶體
imagedestroy($source);
imagedestroy($rotate);
?>

以上範例會輸出類似以下的內容

Output of example : Rotate an image 180 degrees

注意

注意:

此函數會受到 imagesetinterpolation() 設定的插值方法影響。

另請參閱

新增註解

使用者貢獻的註解 38 個註解

33
meisterix at gmx dot com
12 年前
經過一些網路搜尋和個人嘗試與失敗後,我成功地旋轉 PNG 影像,同時保留 alpha 通道透明度(半透明)。

<?php
$filename
= 'YourFile.png';
$rotang = 20; // 旋轉角度
$source = imagecreatefrompng($filename) or die('Error opening file '.$filename);
imagealphablending($source, false);
imagesavealpha($source, true);

$rotation = imagerotate($source, $rotang, imageColorAllocateAlpha($source, 0, 0, 0, 127));
imagealphablending($rotation, false);
imagesavealpha($rotation, true);

header('Content-type: image/png');
imagepng($rotation);
imagedestroy($source);
imagedestroy($rotation);
?>
4
Mike Knoop
15 年前
不要被誤導,以為此函數會就地旋轉影像資源控制代碼。雖然文件目前沒有指定和傳回值,但我發現以下傳回值為真

「成功時傳回影像資源識別碼,錯誤時傳回 FALSE。」

只要確保您正在執行類似以下的操作...
<?php
$rotated_img
= imagerotate($src_img, 45, $color)
?>

-Mike
10
henzeberkheij at gmail dot com
12 年前
請記住,此函數會逆時針旋轉。如果您想順時針旋轉 90 度,您必須告訴 imagerotate 逆時針旋轉 270 度。

$angle = 360-$angle;
8
xavtak at gmail dot com
14 年前
我已經針對此處描述的三種旋轉影像的方法進行了效能基準測試。

我使用了一張 1600 x 1200 的 jpeg 圖片,該圖片在磁碟上複製了十次。我迴圈遍歷它們,以使用任一方法套用順時針旋轉。

第一個演算法(「imagesetpixel」演算法)
<?php
function CWRotation($image)
{
$w = imagesx($image);
$h = imagesy($image);
$result = @imagecreatetruecolor($h, $w);
if(
$result)
{
for (
$i = 0; $i < $w; $i++)
for (
$j = 0; $j < $h; $j++)
{
$ref = imagecolorat($image, $i, $j);
imagesetpixel($result, ($h - 1) - $j, $i, $ref);
}
}
return
$result;
}
?>

第二種演算法(「imagecopy」演算法)
<?php
function CWRotation($image)
{
$w = imagesx($image);
$h = imagesy($image);
$result = @imagecreatetruecolor($h, $w);
if(
$result)
{
for (
$i = 0; $i < $w; $i++)
for (
$j = 0; $j < $h; $j++)
imagecopy($result, $image, ($h - 1) - $j, $i, $i, $j, 1, 1);
}
return
$result;
}
?>

第三種演算法(「imagerotate」演算法)
<?php
function CWRotation($image)
{
return
imagerotate($image, 270, 0);
}
?>

在迴圈的每個步驟中,會載入圖片,旋轉,然後將副本寫入磁碟。

以下是結果
imagesetpixel 演算法:10 張圖片在 29 秒內處理完成
imagecopy 演算法:10 張圖片在 26 秒內處理完成
imagerotate 演算法:10 張圖片在 2 秒內處理完成(這裡沒有打錯)

將圖片寫入磁碟讓我能夠控制結果。每一張結果圖片都相同(使用 winmerge 測試)。

結論:imagerotate 比其他「自製」演算法快得多。
我執行了幾次測試,看看 imagesetpixel 和 imagecopy 之間的差異是否是由於我電腦的獨立活動造成的,但我總是得到 10% 的差異。

注意:我使用的圖片是從相機拍攝的,因此不涉及透明度。
我使用 PHP 5.3.0 版本在 Windows XP 上執行了測試。
4
xarris_ at hotmail dot com
9 年前
imagerotate() 的一個問題是它可能需要比可用記憶體更多的記憶體。它在我的腳本中失敗了,所以我嘗試使用 ini_set('memory_limit', '256M') 來增加它
現在一切運作正常。
1
joseluis at pellicer dot org
16 年前
關於 david at horizon-nigh 的旋轉函數無法運作的問題,我發現了錯誤。
我注意到 x1 和 y1 沒有被使用,因此,在迴圈遍歷每個像素並轉換它時,將

$x2 = $x * cos($theta) - $y * sin($theta);
$y2 = $x * sin($theta) + $y * cos($theta);

改為

$x2 = $x1 * cos($theta) - $y1 * sin($theta);
$y2 = $x1 * sin($theta) + $y1 * cos($theta);
1
kmrohe at letsco dot de
14 年前
作為 GD rotateImage() 函數的替代方案,這是一種以逆時針方向旋轉 90 度 *且不會* 損失透明度的簡單方法

<?php

function rotateImage($image) {
$width = imagesx($image);
$height = imagesy($image);
$newImage= imagecreatetruecolor($height, $width);
imagealphablending($newImage, false);
imagesavealpha($newImage, true);
for(
$w=0; $w<$width; $w++)
for(
$h=0; $h<$height; $h++) {
$ref = imagecolorat($image, $w, $h);
imagesetpixel($newImage, $h, ($width-1)-$w, $ref);
}
return
$newImage;
}

?>
1
krteczek01 at gmail dot com
15 年前
嗨,我已將函數重寫為具有靜態方法的類別。此解決方案的優點是能夠在腳本執行期間多次呼叫。

<?php
/*
未完成的 imagerotate 替代方案。ignore_transparent 參數實際上會被忽略。:)
此外,應該有一些用於 90、180 和 270 度的標準函式,因為它們很容易更快地實作。
*/

if(!function_exists("imagerotate")) {
function
imagerotate(&$srcImg, $angle, $bgcolor, $ignore_transparent = 0) {
return
imagerotateEquivalent::rotate(&$srcImg, $angle, $bgcolor, $ignore_transparent);
}
}

class
imagerotateEquivalent {

static private function
rotateX($x, $y, $theta){
return
$x * cos($theta) - $y * sin($theta);
}

static private function
rotateY($x, $y, $theta){
return
$x * sin($theta) + $y * cos($theta);
}

public static function
rotate(&$srcImg, $angle, $bgcolor, $ignore_transparent = 0) {

$srcw = imagesx($srcImg);
$srch = imagesy($srcImg);

if(
$angle == 0) return $srcImg;

// 將角度轉換為弧度
$theta = deg2rad ($angle);

// 計算目標影像的寬度。
$temp = array ( self::rotateX(0, 0, 0-$theta),
self::rotateX($srcw, 0, 0-$theta),
self::rotateX(0, $srch, 0-$theta),
self::rotateX($srcw, $srch, 0-$theta)
);
$minX = floor(min($temp));
$maxX = ceil(max($temp));
$width = $maxX - $minX;

// 計算目標影像的高度。
$temp = array ( self::rotateY(0, 0, 0-$theta),
self::rotateY($srcw, 0, 0-$theta),
self::rotateY(0, $srch, 0-$theta),
self::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));

// 設定新影像中的所有像素
for($x=$minX;$x<$maxX;$x++) {
for(
$y=$minY;$y<$maxY;$y++)
{
// 從來源影像中取得對應的像素
$srcX = round(self::rotateX($x, $y, $theta));
$srcY = round(self::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;
}
}

?>
1
AJenbo
16 年前
我修改了 cbl25 的函式,使其能夠順時針或逆時針旋轉影像。

<?php
function rotateImage($image, $direction) {
$direction = strtolower($direction);
$degrees = $direction == 'cw' ? 270 : ($direction == 'ccw' ? 90 : NULL);
if(!
$degrees)
return
$image;
$width = imagesx($image);
$height = imagesy($image);
$side = $width > $height ? $width : $height;
$imageSquare = imagecreatetruecolor($side, $side);
imagecopy($imageSquare, $image, 0, 0, 0, 0, $width, $height);
imagedestroy($image);
$imageSquare = imagerotate($imageSquare, $degrees, 0, -1);
$image = imagecreatetruecolor($height, $width);
$x = $degrees == 90 ? 0 : ($height > $width ? 0 : ($side - $height));
$y = $degrees == 270 ? 0 : ($height < $width ? 0 : ($side - $width));
imagecopy($image, $imageSquare, 0, 0, $x, $y, $height, $width);
imagedestroy($imageSquare);
return
$image;
}

//Usage
$image = rotateImage($image, 'cw');
$image = rotateImage($image, 'ccw');
?>
1
shaun at slickdesign dot com dot au
7 年前
imagerotate() 中的角度是逆時針旋轉影像的度數,但雖然使用 '-90' 將影像順時針旋轉 90 度似乎很自然,但最終結果可能會以稍微傾斜的角度出現,並可能導致旋轉後的影像出現輕微模糊,帶有背景或邊框。過大的角度也可能會出現取樣問題。

防止這些問題的最簡單方法是確保所有角度都在 0 到 360 之間。

<?php
while ( $angle < 0 ) { $angle += 360; }
while (
$angle >= 360 ) { $angle -= 360; }

$rotated = imagerotate( $image, $angle, $color );
?>
1
anon at here dot com
15 年前
我很驚訝地發現竟然沒有人做任何有效的旋轉函式。由於我的網路主機需要一個,所以我很快地寫了一個。可能有人會想擴展它,使其與 imagerotate 相符。

此外,imagerotate 真的會逆時針旋轉嗎?否則,這也應該修改。

<?php
if(!function_exists("imagerotate")) {
function
imagerotate(&$srcImg, $angle, $bgcolor, $ignore_transparent = 0) {
return
imagerotateEquivalent(&$srcImg, $angle, $bgcolor, $ignore_transparent);
}
}

/*
未完成的 imagerotate 替代方案。ignore_transparent 參數目前被忽略。:)
此外,應該針對 90、180 和 270 度建立一些標準函式,因為它們比較容易更快實作。
*/
function imagerotateEquivalent(&$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;

// 將角度轉換為弧度
$theta = deg2rad ($angle);


// 計算目標影像的寬度。
$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;

// 計算目標影像的高度。
$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));

// 設定新影像中的所有像素
for($x=$minX;$x<$maxX;$x++) {
for(
$y=$minY;$y<$maxY;$y++)
{
// 從來源影像中擷取對應的像素
$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;
}
?>
2
sjef at bosman dot fr
15 年前
我想要繪製一個透明的 GIF 圖片,並以 URL 中指定的角度顯示在頁面上。
<img src="image.php?angle=90" type="image/gif">

我使用了原生的 imagerotate(),但在 90、180 等角度時,舊的背景顏色會變成不透明。顯然,GD 某處存在一個錯誤,而且已經存在很久了。

以下是我的解決方案

<?php
$height
= 100;
$width = 100;
$lsize= $width/2;
$angle= $_GET["angle"];

// 避免錯誤:
if(($angle%90)==0)
$angle+= 0.001;

$image_p = imagecreatetruecolor($width, $height);
$trans = imagecolorallocate($image_p, 254, 0, 0);
imagefill($image_p, 0, 0, $trans);
imagecolortransparent($image_p, $trans);

$black = imagecolorallocate($image_p, 1, 1, 1);
$red = imagecolorallocate($image_p, 255, 0, 0);
$white = imagecolorallocate($image_p, 255, 255, 255);

// 在此繪製圖形
imageline($image_p, 3, $lsize, $lsize/2, $lsize, $black);

$image_r= imagerotate($image_p, -$angle, $trans, 0);
$w= imagesx($image_r);
$h= imagesy($image_r);
$image_s = imagecreatetruecolor($width, $height);
imagecopyresized($image_s, $image_r, 0, 0, ($w-$width)/2, ($h-$height)/2, $width, $height, $width, $height);
$trans = imagecolorallocate($image_s, 254, 0, 0);
imagecolortransparent($image_s, $trans);
imagegif($image_s);
?>
2
david at horizon-nigh dot org
16 年前
我不知道為什麼 'the dot thawk' 或 'pilot' 的替換方法對我無效,所以這是我的替換方法。它使用 ImageMagick;必須安裝二進制檔,而且你可能需要修改搜尋路徑。(我沒有使用 PHP 的 ImageMagick 支援,原因是我個人因素。)

<?php
/**
* imagerotate()
* Debian php5-gd 套件由於某些複雜原因不包含 imagerotate()。
*
* @param int $angle - 與 PHP 內建函式相同
* @param $bgd_color - 未實作,顯然永遠為 #FFFFFF
*
* @return 與 PHP 內建函式相同
*/
if ( !function_exists( 'imagerotate' ) ) {

function
imagerotate( $source_image, $angle, $bgd_color ) {

$angle = 360-$angle; // GD 逆時針旋轉,imagick 順時針旋轉

foreach ( array( '/usr/bin', '/usr/local/bin', '/opt/local/bin', '/sw/bin' ) as $path ) {

if (
file_exists( $path . '/convert' ) ) {
$imagick = $path . '/convert';
if (
$path == '/opt/local/bin' ) {
$imagick = 'DYLD_LIBRARY_PATH="" ' . $imagick; // 與 MacPorts 和 MAMP 的一些衝突
}
break;
}

}

if ( !isset(
$imagick ) ) {

//trigger_error( 'imagerotate(): 找不到 imagemagick 二進制檔,傳回原始圖片', E_USER_WARNING );
return $source_image;

}

$file1 = '/tmp/imagick_' . rand( 10000,99999 ) . '.png';
$file2 = '/tmp/imagick_' . rand( 10000,99999 ) . '.png';

if ( @
imagepng( $source_image, $file1 ) ) {

exec( $imagick . ' -rotate ' . $angle . ' ' . $file1 . ' ' . $file2 );

if (
file_exists( $file2 ) ) {

$new_image = imagecreatefrompng( $file2 );
unlink( $file1 );
unlink( $file2 );
return
$new_image;

} else {

//trigger_error( 'imagerotate(): imagemagick 轉換失敗,傳回原始圖片', E_USER_WARNING );
return $source_image;

}

} else {

//trigger_error( 'imagerotate(): 無法寫入 ' . $file1 . ',傳回原始圖片', E_USER_WARNING );
return $source_image;

}

}

}
?>
2
the dot thawk+phpnet at gmail dot com
16 年前
回覆 pilot at myupb dot com 於 2008 年 5 月 31 日 02:23
---

我不確定你為什麼要定義自己的 PI,而不是使用內建的常數,以及為什麼你要手動將角度轉換為弧度。 可能有速度問題,但這是完全相同的程式碼,只有這個小差異。

<?php
if(!function_exists("imagerotate")) {
function
imagerotate(&$srcImg, $angle, $transparentColor = null) {
$srcw = imagesx($srcImg);
$srch = imagesy($srcImg);

if(
$angle == 0) return $srcImg;

// 將角度轉換為弧度
$theta = deg2rad ($angle);

// 取得圖片的中心點 (原點)
$originx = $srcw / 2;
$originy = $srch / 2;

// 新圖片的像素陣列
$pixels = array();
$minx = 0;
$maxx = 0;
$miny = 0;
$maxy = 0;
$dstw = 0;
$dsth = 0;

// 迴圈遍歷每個像素並進行轉換
for($x=0;$x<$srcw;$x++) {
for(
$y=0;$y<$srch;$y++) {
list(
$x1, $y1) = translateCoordinate($originx, $originy, $x, $y, false);

$x2 = $x * cos($theta) - $y * sin($theta);
$y2 = $x * sin($theta) + $y * cos($theta);

// 儲存像素顏色
$pixels[] = array($x2, $y2, imagecolorat($srcImg, $x, $y));

// 檢查邊界
if($x2 > $maxx) $maxx = $x2;
if(
$x2 < $minx) $minx = $x2;
if(
$y2 > $maxy) $maxy = $y2;
if(
$y2 < $miny) $miny = $y2;
}
}

// 決定新圖片的大小
$dstw = $maxx - $minx + 1;
$dsth = $maxy - $miny + 1;

// 建立新圖片
$dstImg = imagecreatetruecolor($dstw, $dsth);

// 使用透明顏色填充背景
if($transparentColor == null) $transparentColor = imagecolorallocate($dstImg, 1, 2, 3);
imagecolortransparent($dstImg, $transparentColor);
imagefilledrectangle($dstImg, 0, 0, $dstw + 1, $dsth + 1, $transparentColor);

// 取得新的原點
$neworiginx = -$minx;
$neworiginy = -$miny;

// 填入像素
foreach($pixels as $data) {
list(
$x, $y, $color) = $data;
list(
$newx, $newy) = translateCoordinate($neworiginx, $neworiginy, $x, $y);
imagesetpixel($dstImg, $newx, $newy, $color);
}

return
$dstImg;
}

/**
* 使用電腦系統的原點座標,在數學座標系統和電腦座標系統之間進行轉換,反之亦然
*
* @param int $originx
* @param int $originy
* @param int $x
* @param int $y
* @param bool $toComp
* @return array(int $x, int $y)
*/
function translateCoordinate($originx, $originy, $x, $y, $toComp=true) {
if(
$toComp) {
$newx = $originx + $x;
$newy = $originy - $y;
} else {
$newx = $x - $originx;
$newy = $originy - $y;
}

return array(
$newx, $newy);
}
}
?>
1
foi02 at cartefoi dot net
16 年前
對於那些正在尋找 Ubuntu 的 GD 函式庫的人,我在我的伺服器上留了一份副本:http://www.cartefoi.net/compl_compl_2.php
它很難找到,有人給了我一份。非常感謝他(上面的訊息)。
0
Anonymous
15 年前
抱歉,之前的類別包含一個錯誤,原始圖片在旋轉後會移動 1px 並產生不必要的「邊框」。

在仔細閱讀了本地討論後,我使用了 Dave Richards 的建議,編寫了一個新的函式。使用它,圖片只能旋轉 90°(預設)、180° 和 270°,但很少需要更多...。

該函式會返回 False,或旋轉後的圖片。
<?php
if(!function_exists("imagerotate")) {
function
imagerotate($srcImg, $angle, $bgcolor, $ignore_transparent = 0) {
return
rotateImage($srcImg, $angle);
}
}

function
rotateImage($img1, $rec) {
$wid = imagesx($img1);
$hei = imagesy($img1);
switch(
$rec) {
case
270:
$img2 = @imagecreatetruecolor($hei, $wid);
break;
case
180:
$img2 = @imagecreatetruecolor($wid, $hei);
break;
default :
$img2 = @imagecreatetruecolor($hei, $wid);
}
if(
$img2) {
for(
$i = 0;$i < $wid; $i++) {
for(
$j = 0;$j < $hei; $j++) {
$ref = imagecolorat($img1,$i,$j);
switch(
$rec) {
case
270:
if(!@
imagesetpixel($img2, ($hei - 1) - $j, $i, $ref)){
return
false;
}
break;
case
180:
if(!@
imagesetpixel($img2, $i, ($hei - 1) - $j, $ref)) {
return
false;
}
break;
default:
if(!@
imagesetpixel($img2, $j, ($wid - 1) - $i, $ref)) {
return
false;
}
}
}
}
return
$img2;
}
return
false;
}
?>

Petr
0
Bert Vandeghinste
16 年前
我現在使用 David 的程式碼,並做了一些變更以取得透明效果。

我執行 convert 兩次

<?php
exec
( $imagick . ' -background \'#555555\' -rotate ' . $angle . ' ' . $file1 . ' ' . $file2 );
exec( $imagick . ' -transparent \'#555555\' -transparent-color \'#555555\' ' . $file2 . ' ' . $file3 );
?>

然後在我旋轉 $output 之後使用這個
<?php imagecolortransparent($output, imagecolorallocatealpha($output, 85, 85, 85, 127)); ?>
0
cbl25
16 年前
這是一個簡單的函數,可以將非正方形的圖片順時針旋轉 90 度。

<?php
function rotateImage($imageResource)
{
$width = imagesx($imageResource);
$height = imagesy($imageResource);
$side = $width > $height ? $width : $height;
$squareImage = imagecreatetruecolor($side, $side);
imagecopy($squareImage,$imageResource,0,0,0,0,$width,$height);
$squareImage = imagerotate($squareImage,270,0,-1);
$imageResource = imagecreatetruecolor($height, $width);
$x = $height > $width ? 0 : $side - $height;
imagecopy($imageResource,$squareImage,0,0,$x,0,$height,$width);
return
$imageResource;
}
?>
0
pilot at myupb dot com
16 年前
在發布後不久,我被告知有一個非常好的演算法來計算旋轉後的新像素位置,並認為這將是一個很好的改進。希望這能幫助任何需要完整實作的人。

注意:我用 3Mb 的照片測試了該函數,它似乎可以完美運作,沒有任何品質損失。

<?php
if(!function_exists("imagerotate")) {
function
imagerotate(&$srcImg, $angle, $transparentColor = null) {
$srcw = imagesx($srcImg);
$srch = imagesy($srcImg);

if(
$angle == 0) return $srcImg;

// 將角度轉換為弧度
$pi = 3.141592654;
$theta = $angle * $pi / 180;

// 取得圖片的原點 (中心點)
$originx = $srcw / 2;
$originy = $srch / 2;

// 新圖片的像素陣列
$pixels = array();
$minx = 0;
$maxx = 0;
$miny = 0;
$maxy = 0;
$dstw = 0;
$dsth = 0;

// 迴圈遍歷每個像素並轉換它
for($x=0;$x<$srcw;$x++) {
for(
$y=0;$y<$srch;$y++) {
list(
$x1, $y1) = translateCoordinate($originx, $originy, $x, $y, false);

$x2 = $x * cos($theta) - $y * sin($theta);
$y2 = $x * sin($theta) + $y * cos($theta);

// 儲存像素顏色
$pixels[] = array($x2, $y2, imagecolorat($srcImg, $x, $y));

// 檢查邊界
if($x2 > $maxx) $maxx = $x2;
if(
$x2 < $minx) $minx = $x2;
if(
$y2 > $maxy) $maxy = $y2;
if(
$y2 < $miny) $miny = $y2;
}
}

// 決定新圖片的大小
$dstw = $maxx - $minx + 1;
$dsth = $maxy - $miny + 1;

// 建立新圖片
$dstImg = imagecreatetruecolor($dstw, $dsth);

// 用透明顏色填充背景
if($transparentColor == null) $transparentColor = imagecolorallocate($dstImg, 1, 2, 3);
imagecolortransparent($dstImg, $transparentColor);
imagefilledrectangle($dstImg, 0, 0, $dstw + 1, $dsth + 1, $transparentColor);

// 取得新的原點
$neworiginx = -$minx;
$neworiginy = -$miny;

// 填入像素
foreach($pixels as $data) {
list(
$x, $y, $color) = $data;
list(
$newx, $newy) = translateCoordinate($neworiginx, $neworiginy, $x, $y);
imagesetpixel($dstImg, $newx, $newy, $color);
}

return
$dstImg;
}

/**
* 使用電腦系統的原點座標,在數學座標系統和電腦座標系統之間轉換,或反之亦然。
*
* @param int $originx
* @param int $originy
* @param int $x
* @param int $y
* @param bool $toComp
* @return array(int $x, int $y)
*/
function translateCoordinate($originx, $originy, $x, $y, $toComp=true) {
if(
$toComp) {
$newx = $originx + $x;
$newy = $originy - $y;
} else {
$newx = $x - $originx;
$newy = $originy - $y;
}

return array(
$newx, $newy);
}
}
?>
0
pilot at myupb dot com
16 年前
感謝那些貢獻 90、180 和 270 度旋轉程式碼的人。我需要一個完整的實作,所以我自己寫了一個。我絕不認為這是最好的方法,我只是為自己快速拼湊出來的。對我來說似乎效果不錯。

注意:我不希望圖片在旋轉時被縮小,因此這個實作會保持原始圖片的大小,而只是旋轉它。

<?php
if(!function_exists("imagerotate")) {
function
imagerotate(&$srcImg, $angle, $transparentColor = null) {
$srcw = imagesx($srcImg);
$srch = imagesy($srcImg);

if(
$angle == 0) return $srcImg;

// Convert the angle to radians
$pi = 3.141592654;
$theta = $angle * $pi / 180;

// Get the origin (center) of the image
$originx = $srcw / 2;
$originy = $srch / 2;

// The pixels array for the new image
$pixels = array();
$minx = 0;
$maxx = 0;
$miny = 0;
$maxy = 0;
$dstw = 0;
$dsth = 0;

// Loop through every pixel and transform it
for($x=0;$x<$srcw;$x++) {
for(
$y=0;$y<$srch;$y++) {
list(
$x1, $y1) = translateCoordinate($originx, $originy, $x, $y, false);

$theta1 = 0;
$noTranslate = false;

// Determine the angle of original point
if($x1 > 0 && $y1 > 0) {
// Quadrant 1
$theta1 = atan($y1/$x1);
} elseif(
$x1 < 0 && $y1 > 0) {
// Quadrant 2
$theta1 = $pi - atan($y1/abs($x1));
} elseif(
$x1 < 0 && $y1 < 0) {
// Quadrant 3
$theta1 = $pi + atan($y1/$x1);
} elseif(
$x1 > 0 && $y1 < 0) {
// Quadrant 4
$theta1 = 2 * $pi - atan(abs($y1)/$x1);
} elseif(
$x1 == 0 && $y1 > 0) {
$theta1 = $pi / 2;
} elseif(
$x1 == 0 && $y1 < 0) {
$theta1 = 3 * $pi / 2;
} elseif(
$x1 > 0 && $y1 == 0) {
$theta1 = 0;
} elseif(
$x1 < 0 && $y1 == 0) {
$theta1 = $pi;
} else {
// Only case left should be $x1 == 0 && $y1 == 0
$noTranslate = true;
}

// Translate the position
if(!$noTranslate) {
// Calculate the new angle
$theta2 = $theta1 + $theta;

// Make sure theta2 is in between 0 - 2pi
while($theta2 < 0) $theta2 += 2 * $pi;
while(
$theta2 > (2 * $pi)) $theta2 -= 2 * $pi;

$radius = sqrt($x1*$x1 + $y1*$y1);

$x2 = ($radius * cos($theta2));
$y2 = ($radius * sin($theta2));
} else {
$x2 = $x1;
$y2 = $y1;
}

// Store the pixel color
$pixels[] = array($x2, $y2, imagecolorat($srcImg, $x, $y));

// Check our boundaries
if($x2 > $maxx) $maxx = $x2;
if(
$x2 < $minx) $minx = $x2;
if(
$y2 > $maxy) $maxy = $y2;
if(
$y2 < $miny) $miny = $y2;
}
}

// Determine the new image size
$dstw = $maxx - $minx + 1;
$dsth = $maxy - $miny + 1;

// Create our new image
$dstImg = imagecreatetruecolor($dstw, $dsth);

// Fill the background with our transparent color
if($transparentColor == null) $transparentColor = imagecolorallocate($dstImg, 1, 2, 3);
imagecolortransparent($dstImg, $transparentColor);
imagefilledrectangle($dstImg, 0, 0, $dstw + 1, $dsth + 1, $transparentColor);

// Get the new origin
$neworiginx = -$minx;
$neworiginy = -$miny;

// Fill in the pixels
foreach($pixels as $data) {
list(
$x, $y, $color) = $data;
list(
$newx, $newy) = translateCoordinate($neworiginx, $neworiginy, $x, $y);
imagesetpixel($dstImg, $newx, $newy, $color);
}

return
$dstImg;
}

/**
* Translates from mathematical coordinate system to computer coordinate system using
* origin coordinates from the computer system or visa versa
*
* @param int $originx
* @param int $originy
* @param int $x
* @param int $y
* @param bool $toComp
* @return array(int $x, int $y)
*/
function translateCoordinate($originx, $originy, $x, $y, $toComp=true) {
if(
$toComp) {
$newx = $originx + $x;
$newy = $originy - $y;
} else {
$newx = $x - $originx;
$newy = $originy - $y;
}

return array(
$newx, $newy);
}
}
?>
0
achilles
16 年前
優化自 2007 年 2 月 23 日 04:21 的整合
只要將它放在任何您想要使用 90、180、270 度 imagerotate 的地方即可。
<?php
if(!function_exists("imagerotate")) {
function
imagerotate($src_img, $angle) {
$src_x = imagesx($src_img);
$src_y = imagesy($src_img);
if (
$angle == 180) {
$dest_x = $src_x;
$dest_y = $src_y; }
elseif (
$src_x <= $src_y) {
$dest_x = $src_y;
$dest_y = $src_x; }
elseif (
$src_x >= $src_y) {
$dest_x = $src_y;
$dest_y = $src_x; }

$rotate=imagecreatetruecolor($dest_x,$dest_y);
imagealphablending($rotate, false);

switch (
$angle) {
case
270:
for (
$y = 0; $y < ($src_y); $y++) {
for (
$x = 0; $x < ($src_x); $x++) {
$color = imagecolorat($src_img, $x, $y);
imagesetpixel($rotate, $dest_x - $y - 1, $x, $color); }}
break;
case
90:
for (
$y = 0; $y < ($src_y); $y++) {
for (
$x = 0; $x < ($src_x); $x++) {
$color = imagecolorat($src_img, $x, $y);
imagesetpixel($rotate, $y, $dest_y - $x - 1, $color); }}
break;
case
180:
for (
$y = 0; $y < ($src_y); $y++) {
for (
$x = 0; $x < ($src_x); $x++) {
$color = imagecolorat($src_img, $x, $y);
imagesetpixel($rotate, $dest_x - $x - 1, $dest_y - $y - 1, $color); }}
break;
default:
$rotate = $src_img; }
return
$rotate; }}
?>
0
qrgames at NOSPAMTYrushyo dot com
17 年前
當複製合併到另一個影像時,`imagerotate` 似乎對處理透明度非常挑剔。您可以使用 GD 函式庫的其他透明度功能來掩蓋 `imagerotate` 的錯誤,但是這只有在影像的左上角在所有旋轉角度都透明時才有效,因此請讓影像比它需要的稍大一些。這已經使用 png32 測試過,但對於 png8 並不完全有效,因為在旋轉後的影像周圍會產生雜訊。

<?php

$imgImage
= imagecreatefrompng("image.png");
$colBlack = imagecolorallocate($imgImage, 0, 0, 0);
$imgImage = imagerotate($imgImage, 360 - $intHeading, 0);
imagefill($imgImage, 0, 0, $colBlack);
imagecolortransparent($imgImage, $colBlack);
imagecopymerge($imgOriginalImage , $imgImage, $intX, $intY, 0, 0, $intHeight, $intWidth, 100);
imagedestroy($imgImage);

?>

注意:`$intHeading` 是以順時針方向的度數表示 :)
0
Thomaschaaf
17 年前
<?php
function rotate($degrees)
{
if(
function_exists("imagerotate"))
$this->image = imagerotate($this->image, $degrees, 0);
else
{
function
imagerotate($src_img, $angle)
{
$src_x = imagesx($src_img);
$src_y = imagesy($src_img);
if (
$angle == 180)
{
$dest_x = $src_x;
$dest_y = $src_y;
}
elseif (
$src_x <= $src_y)
{
$dest_x = $src_y;
$dest_y = $src_x;
}
elseif (
$src_x >= $src_y)
{
$dest_x = $src_y;
$dest_y = $src_x;
}

$rotate=imagecreatetruecolor($dest_x,$dest_y);
imagealphablending($rotate, false);

switch (
$angle)
{
case
270:
for (
$y = 0; $y < ($src_y); $y++)
{
for (
$x = 0; $x < ($src_x); $x++)
{
$color = imagecolorat($src_img, $x, $y);
imagesetpixel($rotate, $dest_x - $y - 1, $x, $color);
}
}
break;
case
90:
for (
$y = 0; $y < ($src_y); $y++)
{
for (
$x = 0; $x < ($src_x); $x++)
{
$color = imagecolorat($src_img, $x, $y);
imagesetpixel($rotate, $y, $dest_y - $x - 1, $color);
}
}
break;
case
180:
for (
$y = 0; $y < ($src_y); $y++)
{
for (
$x = 0; $x < ($src_x); $x++)
{
$color = imagecolorat($src_img, $x, $y);
imagesetpixel($rotate, $dest_x - $x - 1, $dest_y - $y - 1, $color);
}
}
break;
default:
$rotate = $src_img;
};
return
$rotate;
}
$this->image = imagerotate($this->image, $degrees);
}
}
?>
0
wulff at fyens dot dk
19 年前
我喜歡 darren at lucidtone dot com 實作的 rotateImageBicubic 函式。但它只是將圖片超出原始圖片的部分裁切掉。

我修正了這個問題,儘管我承認我的解決方案有點天真。但它可能對某些人有所幫助。

此外,他的雙立方實作在我的機器上是壞掉的,所以我把它省略了,如果你需要它,只需從上面複製貼上即可。

<?php

// $src_img - 一個 GD 影像資源
// $angle - 順時針旋轉的角度,以度為單位
// 傳回一個 GD 影像資源
// 用法:
// $im = imagecreatefrompng('test.png');
// $im = imagerotate($im, 15);
// header('Content-type: image/png');
// imagepng($im);
function imageRotate($src_img, $angle, $bicubic=false) {

// 將度數轉換為弧度
$angle = $angle + 180;
$angle = deg2rad($angle);

$src_x = imagesx($src_img);
$src_y = imagesy($src_img);

$center_x = floor($src_x/2);
$center_y = floor($src_y/2);

$cosangle = cos($angle);
$sinangle = sin($angle);

$corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));

foreach(
$corners as $key=>$value) {
$value[0]-=$center_x; //將座標轉換為旋轉的中心點
$value[1]-=$center_y;
$temp=array();
$temp[0]=$value[0]*$cosangle+$value[1]*$sinangle;
$temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
$corners[$key]=$temp;
}

$min_x=1000000000000000;
$max_x=-1000000000000000;
$min_y=1000000000000000;
$max_y=-1000000000000000;

foreach(
$corners as $key => $value) {
if(
$value[0]<$min_x)
$min_x=$value[0];
if(
$value[0]>$max_x)
$max_x=$value[0];

if(
$value[1]<$min_y)
$min_y=$value[1];
if(
$value[1]>$max_y)
$max_y=$value[1];
}

$rotate_width=round($max_x-$min_x);
$rotate_height=round($max_y-$min_y);

$rotate=imagecreatetruecolor($rotate_width,$rotate_height);
imagealphablending($rotate, false);
imagesavealpha($rotate, true);

//將中心重置為我們影像的中心
$newcenter_x = ($rotate_width)/2;
$newcenter_y = ($rotate_height)/2;

for (
$y = 0; $y < ($rotate_height); $y++) {
for (
$x = 0; $x < ($rotate_width); $x++) {
// 旋轉...
$old_x = round((($newcenter_x-$x) * $cosangle + ($newcenter_y-$y) * $sinangle))
+
$center_x;
$old_y = round((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
+
$center_y;

if (
$old_x >= 0 && $old_x < $src_x
&& $old_y >= 0 && $old_y < $src_y ) {

$color = imagecolorat($src_img, $old_x, $old_y);
} else {
// 這一行設定背景顏色
$color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
}
imagesetpixel($rotate, $x, $y, $color);
}
}

return(
$rotate);
}

?>
-1
c kelley at ca - cycleworks dot com
14 年前
請注意,在下面的旋轉函式中,只有 beau 的函式對我有效。不確定是否因為我的來源影像,但在旋轉時,背景變成了藍色。

下面的程式碼片段是我用來準備 UPS 運輸標籤的。UPS xml api 會傳回 base64 編碼的 gif,但它是側向的,以便列印在 8.5x11「信紙」頁面的上半部分。我們將其儲存在資料庫中並發送到標籤印表機,因此需要旋轉它...

下面更遠的其他程式碼不會使背景變成藍色,但是它確實使影像離開畫布約 50%。此外,imagecolorallocate() 函式有一個範例描述如何設定背景顏色。這對我不起作用。即使藍色背景是 #0000ff,使用該程式碼也不起作用,我必須使用下面的透明技巧。

GD 影像函式可能還在起步階段,但它很好地提醒我 php 是多麼強大!此外,ubuntu apache 使用者需要 apt-get install php5-gd 才能取得 gd 函式。

<?php
$image
=imagecreatefromgif( 'data://text/plain;base64,'.$this->shipmentLabelGraphicImage );
$image=$this->rotateImage($image, 90); // 注意:rotateImage 會將背景變成藍色!
$blue = imagecolorallocate($image, 0, 0, 255);
imagecolortransparent($image, $blue); // 將藍色設為透明,讓圖片不會看起來很奇怪
imagepng($image,$this->shipmentTrackingNumber.".png");
echo
'<P><img src="'.$this->shipmentTrackingNumber.'.png"></P>';
imagedestroy($image);
?>
0
Borszczuk
19 年前
這裡有一個函數,可以實作直角旋轉(90 度的倍數 - 90、180、270 度),如果您需要但沒有內建的 imagerotate() 或您不希望非正方形的圖像像使用 imagerotate() 一樣縮小。您可能已經注意到它不是一個自包含的函數,因為 180 度旋轉是由 ImageFlip() 函數處理以提高效能。使用的 ImageFlip() 函數發佈在這裡:https://php.dev.org.tw/imagecopy,在我的 2005 年 1 月 5 日 04:30 的評論中。

請注意:在旋轉 0 度時,會傳回 imgSrc 的處理,如果您無條件地 imagedestroy() 它,可能會導致問題。為了解決這個問題,您應該在適當的位置新增 imagecopy($imgDest, $imgSrc, 0,0, 0,0,$srcX, $srcY),我故意省略了它以節省記憶體資源。

<?php

// $imgSrc - 來源圖像的 GD 圖像處理
// $angle - 旋轉角度。需要是正整數
// 角度應為 0、90、180、270,但如果您給其他值,它
// 會被四捨五入到最接近的直角(例如 52->90 度,
// 96->90 度)
// 傳回旋轉後的圖像的 GD 圖像處理。
function ImageRotateRightAngle( $imgSrc, $angle )
{
// 確保我們得到真正的直角(如果不是,我們選擇最接近的一個)
$angle = min( ( (int)(($angle+45) / 90) * 90), 270 );

// 沒有必要處理
if( $angle == 0 )
return(
$imgSrc );

// 來源圖像的尺寸
$srcX = imagesx( $imgSrc );
$srcY = imagesy( $imgSrc );

switch(
$angle )
{
case
90:
$imgDest = imagecreatetruecolor( $srcY, $srcX );
for(
$x=0; $x<$srcX; $x++ )
for(
$y=0; $y<$srcY; $y++ )
imagecopy($imgDest, $imgSrc, $srcY-$y-1, $x, $x, $y, 1, 1);
break;

case
180:
$imgDest = ImageFlip( $imgSrc, IMAGE_FLIP_BOTH );
break;

case
270:
$imgDest = imagecreatetruecolor( $srcY, $srcX );
for(
$x=0; $x<$srcX; $x++ )
for(
$y=0; $y<$srcY; $y++ )
imagecopy($imgDest, $imgSrc, $y, $srcX-$x-1, $x, $y, 1, 1);
break;
}

return(
$imgDest );
}
?>
0
jon at driestone dot com
20 年前
imagerotate 不會保留 Alpha 通道,因此如果您想旋轉 PNG,您需要發揮
創意。我沒有看到任何從圖像中檢索 Alpha 資訊的命令(據我所知,)
,所以您必須事先做一些手動操作。在我的情況下,我建立了一個
第二個 PNG 檔案,將 Alpha 儲存為 RGB 資料,並手動將資料從來源
複製到目的地。

<?php
function alpha_rotate($dst,$src,$rotate,$offsetX,$offsetY){

$top = imagecreatefrompng("image_processing/shadow.png");
$top_alpha = imagecreatefrompng("image_processing/shadow_alpha.png");

imagecopyresampled($top,$src,0,0,0,0,100,100,100,100);

$top = imagerotate($top,$rotate,0x000000);
$top_alpha = imagerotate($top_alpha,$rotate,0x000000);


for (
$theX=0;$theX<imagesx($top);$theX++){
for (
$theY=0;$theY<imagesy($top);$theY++){

$rgb = imagecolorat($top,$theX,$theY);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;

$rgb = imagecolorat($top_alpha,$theX,$theY);
$a = $rgb & 0xFF;
$a = 127-floor($a/2);

$myColor = imagecolorallocatealpha($top,$r,$g,$b,$a);
imagesetpixel($dst,($theX+$offsetX),($theY+$offsetY),$myColor);
}
}
}
?>
-1
dev at imglib dot endofinternet dot net
15 年前
你可以透過修改以下程式碼,為你的 PNG 圖片新增透明背景:
<?php
if ($ignore_transparent == 0) {
imagefill($destimg, 0, 0, imagecolorallocatealpha($destimg, 255,255, 255, 127));
imagesavealpha($destimg, true);
}
?>
改成
<?php
if ($ignore_transparent == 0) {
$temp = imagecolorallocatealpha($destimg, 255,255, 255, 127);
imagefill($destimg, 0, 0, $temp);
//如果設定的預設顏色是白色或魔術粉紅,則使用透明色
if ( ($bgcolor == 0) || ($bgcolor == 16777215) || ($bgcolor == 16711935) ) {
$bgcolor = $temp;
}
imagesavealpha($destimg, true);
}
?>
-1
gglockner AT NOSPAMdwaffler DOT com
15 年前
如果你要手動旋轉圖片,而不是使用 `imagerotate` 函式,你可以使用 `imagecopy` 函式來複製單個像素,而不是取得像素顏色再設定像素。這樣不僅程式碼更簡潔,而且也適用於非真彩色圖像(在我的系統上,`imagecolorat` 在處理非真彩色圖像時會失敗)。
-1
m dot quinton at gmail dot com
18 年前
對於 `imagerotate` 無法處理的大型檔案,在可能的情況下,你可以使用 ImageMagick 的 "convert" 命令。以下是一個範例腳本:

<?php

error_reporting
(E_ALL);

header("Content-type: image/png");

$file = 'images/test/imgp2498.jpg';

image_rotate_with_convert($file, 90);

function
image_rotate_with_convert($file, $angle){
passthru("convert -rotate $angle $file -");
}

?>
-1
simon_nuttall at hotmail dot com
19 年前
以下程式碼可能很有用。它可以將圖片中心最大的圓形區域提取到指定大小的正方形中,並可選擇旋轉。正方形的其餘部分會設為透明,因此適用於覆蓋在其他圖片上。我將其命名為雙筒望遠鏡效果,因為在一些舊的電視節目中,當他們顯示有人在看雙筒望遠鏡時,螢幕會顯示一個帶有黑色邊緣的巨大圓形影像。

<?php

function image_binocular_effect($src, $bearing, $out_square) {
// 來源圖像會被重新取樣以符合指定的正方形,並依方位角順時針旋轉。
// 會保留圖像內最大的圓形,其餘部分設為透明。
$out = imagecreatetruecolor($out_square, $out_square);
$width=imagesx($src);
$height=imagesy($src);
$square=min($width, $height);
imagecopyresampled($out, $src, 0, 0, ($width - $square)/2 , ($height - $square)/2, $out_square, $out_square, $square, $square);

$mask = imagecreatetruecolor($out_square, $out_square);
$black = ImageColorAllocate ($mask, 0, 0, 0);
$white = ImageColorAllocate ($mask, 255, 255, 255);
imagefilledrectangle($mask , 0, 0, $out_square, $out_square, $white);
$centrexy=$out_square / 2;
imagefilledellipse($mask, $centrexy, $centrexy, $out_square, $out_square, $black);
ImageColorTransparent($mask, $black);
imagecopymerge($out, $mask, 0, 0, 0, 0, $out_square, $out_square, 100);
if (
$bearing != 0) {
$rotated_img=imagerotate($out , 360-$bearing, $white);
// 只移除旋轉後的寬度
$rotated_map_width = imagesx($rotated_img);
$rotated_map_height = imagesy($rotated_img);
imagecopy($out, $rotated_img, 0, 0, ($rotated_map_width - $out_square) / 2, ($rotated_map_height - $out_square) / 2, $out_square, $out_square);
}
ImageColorTransparent($out, $white);
return
$out;
}

// 建立一個範例圖像來展示效果,但在真實照片上看起來會更好。

$src = imagecreatetruecolor(200, 50);
imagefilledrectangle($src, 0, 0, 200, 50, imagecolorallocate($src, 255, 255, 255));
ImageString($src, 3, 10, 10, "這是一個範例圖像,用於說明雙筒鏡效果", imagecolorallocate($im, 192, 0, 0));
$img=image_binocular_effect($src, 72, 50);
ImagePNG($img,"test.png");

?>
-1
darren at lucidtone dot com
19 年前
這是一個方便的函式,適用於那些伺服器上沒有 imagerotate() 的人。它是基於 ron at korving dot demon dot nl 在 imagecopyresampled 的手冊頁上的註解。

我對於處理透明度仍未 100% 掌握,但這個函式似乎可以正常處理。它不會調整大小以符合邊界,它只會旋轉,而超出影像框的任何內容都會遺失。

雙立方模式很慢。

如果您想要能夠更改背景顏色,請傳入顏色並在指定的位置使用它。我使用的那行程式碼只是將它設定為透明。

<?php
// $src_img - GD 圖像資源
// $angle - 順時針旋轉角度,以度為單位
// 傳回 GD 圖像資源
// 用法:
// $im = imagecreatefrompng('test.png');
// $im = imagerotate($im, 15);
// header('Content-type: image/png');
// imagepng($im);
function imageRotateBicubic($src_img, $angle, $bicubic=false) {

// 將角度轉換為弧度
$angle = $angle + 180;
$angle = deg2rad($angle);

$src_x = imagesx($src_img);
$src_y = imagesy($src_img);

$center_x = floor($src_x/2);
$center_y = floor($src_y/2);

$rotate = imagecreatetruecolor($src_x, $src_y);
imagealphablending($rotate, false);
imagesavealpha($rotate, true);

$cosangle = cos($angle);
$sinangle = sin($angle);

for (
$y = 0; $y < $src_y; $y++) {
for (
$x = 0; $x < $src_x; $x++) {
// 旋轉...
$old_x = (($center_x-$x) * $cosangle + ($center_y-$y) * $sinangle)
+
$center_x;
$old_y = (($center_y-$y) * $cosangle - ($center_x-$x) * $sinangle)
+
$center_y;

if (
$old_x >= 0 && $old_x < $src_x
&& $old_y >= 0 && $old_y < $src_y ) {
if (
$bicubic == true) {
$sY = $old_y + 1;
$siY = $old_y;
$siY2 = $old_y - 1;
$sX = $old_x + 1;
$siX = $old_x;
$siX2 = $old_x - 1;

$c1 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY2));
$c2 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY));
$c3 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY2));
$c4 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY));

$r = ($c1['red'] + $c2['red'] + $c3['red'] + $c4['red'] ) << 14;
$g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6;
$b = ($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue'] ) >> 2;
$a = ($c1['alpha'] + $c2['alpha'] + $c3['alpha'] + $c4['alpha'] ) >> 2;
$color = imagecolorallocatealpha($src_img, $r,$g,$b,$a);
} else {
$color = imagecolorat($src_img, $old_x, $old_y);
}
} else {
// 這行設定背景顏色
$color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
}
imagesetpixel($rotate, $x, $y, $color);
}
}
return
$rotate;
}
?>
-1
kraeh at gmx dot net
13 年前
我曾經遇到 PNG 圖片包含透明顏色的問題,但找到了對我有效的解決方案。
所以我想我可以分享一下

<?php
$angle
=45;
$im=imagerotate($im, $angle, -1);
imagealphablending($im, true);
imagesavealpha($im, true);
?>
-2
TNTcode
7 年前
<?php

// 根據相機的 EXIF 資料自動旋轉圖片檔案
// 如果指定了目標檔案,則將檔案儲存於該處,否則將顯示給使用者
// 請注意,已經處於正常方向的圖片將會跳過 (當 EXIF 資料 Orientation = 1 時)

if(!function_exists("gd_auto_rotate")){
function
gd_auto_rotate($original_file, $destination_file=NULL){

$original_extension = strtolower(pathinfo($original_file, PATHINFO_EXTENSION));
if(isset(
$destination_file) and $destination_file!=''){
$destination_extension = strtolower(pathinfo($destination_file, PATHINFO_EXTENSION));
}

// 嘗試使用 gd 自動旋轉圖片 (在編輯之前)
// 使用 ImageMagick 有個簡單的選項
if(function_exists("exif_read_data")){

$exif_data = exif_read_data($original_file);
$exif_orientation = $exif_data['Orientation'];

// 值 1 = 正常 ?! 跳過 ?!

if($exif_orientation=='3' or $exif_orientation=='6' or $exif_orientation=='8'){

$new_angle[3] = 180;
$new_angle[6] = -90;
$new_angle[8] = 90;

// 載入圖片
if($original_extension == "jpg" or $original_extension == "jpeg"){
$original_image = imagecreatefromjpeg($original_file);
}
if(
$original_extension == "gif"){
$original_image = imagecreatefromgif($original_file);
}
if(
$original_extension == "png"){
$original_image = imagecreatefrompng($original_file);
}

$rotated_image = imagerotate($original_image, $new_angle[$exif_orientation], 0);

// 如果沒有設定目標檔案,則顯示圖片
if(!$destination_file){
header('Content-type: image/jpeg');
imagejpeg($rotated_image, NULL, 100);
}

// 如果指定了目標檔案,則儲存較小的圖片檔案
if($destination_extension == "jpg" or $destination_extension=="jpeg"){
imagejpeg($rotated_image, $destination_file,100);
}
if(
$destination_extension == "gif"){
imagegif($rotated_image, $destination_file);
}
if(
$destination_extension == "png"){
imagepng($rotated_image, $destination_file,9);
}

imagedestroy($original_image);
imagedestroy($rotated_image);

}
}
}
}

?>
-1
Sam Yong - hellclanner at live dot com
13 年前
請注意,從 imagerotate() 函式返回的圖片資源與您的原始圖片資源完全不同。

<?php

$res
= imagecreatetruecolor(100, 200);
$res2 = imagerotate($res, 90, 0);
var_dump($res, $res2);

?>

這將輸出

resource(2, gd)
resource(3, gd)
-1
Leo
14 年前
// 角度以度為單位,順時針方向,允許值從 0 到 360 度
function rotateImage ($image, $angle)
{
if ( ($angle < 0) || ($angle > 360) )
{
exit ("錯誤,傳入的角度超出範圍:[0,360]");
}

$width = imagesx ($image);
$height = imagesy ($image);

$dstImage = imagecreatetruecolor ($width, $height);

if ( ($angle == 0) || ($angle == 360) )
{
// 直接複製圖片到輸出
imagecopy ($dstImage, $image, 0, 0, 0, 0, $width, $height);
}
else
{
$centerX = floor ($width / 2);
$centerY = floor ($height / 2);

// 執行目標圖片的所有像素並填充它們
for ($dstImageX = 0; $dstImageX < $width; $dstImageX++)
{
for ($dstImageY = 0; $dstImageY < $height; $dstImageY++)
{
// 計算以圖片中心為中心的座標系統中的像素座標
$x = $dstImageX - $centerX;
$y = $centerY - $dstImageY;

if ( ($x == 0) && ($y == 0) )
{
// 我們位於圖片中心,此像素應照原樣複製
$srcImageX = $x;
$srcImageY = $y;
}
else
{
$r = sqrt ($x * $x + $y * $y); // 半徑 - 從圖片中心到目前點的絕對距離

$curAngle = asin ($y / $r); // 目前點的角度 [rad]

if ($x < 0)
{
$curAngle = pi () - $curAngle;
}

$newAngle = $curAngle + $angle * pi () / 180; // 新角度 [rad]

// 計算以圖片中心為中心的座標系統中的新點座標(旋轉後)
$newXRel = floor ($r * cos ($newAngle));
$newYRel = floor ($r * sin ($newAngle));

// 轉換為圖片絕對座標
$srcImageX = $newXRel + $centerX;
$srcImageY = $centerY - $newYRel;
}

$pixelColor = imagecolorat ($image, $srcImageX, $srcImageY); // 取得來源像素顏色

imagesetpixel ($dstImage, $dstImageX, $dstImageY, $pixelColor); // 寫入目標像素
}
}
}

return $dstImage;
}
-1
fernando_empresarial at ig dot com dot br
16 年前
<?php
$urlImage
= "images/image.png";
$urlNewImage = "images/imageNew.png";

$src_img = imagecreatefrompng($urlImage);
$originalX = imagesx($src_img);
$originalY = imagesy($src_img);
$dst_img = imagecreatetruecolor(640,480);


$imageRotate = imagerotate($src_img,20,-1);

imagepng($imageRotate,$urlNewImage);
imagedestroy($dst_img);
imagedestroy($src_img);
?>
-2
dave dot richards at gmail dot com
15 年前
Kae Cyphet 先前發布的文章中,有一個小錯誤。

當設定新圖片的像素時,座標偶爾必須使用寬度 ($wid) 和高度 ($hei)。 這些值必須減 1,因為座標從 0 開始 (而不是 1),因此它們只會到 $wid - 1 和 $hei - 1 (而不是 $wid 和 $hei)。

以下是第一個函式的範例,以展示這一點

<?php
function rotate_right90($im)
{
$wid = imagesx($im);
$hei = imagesy($im);
$im2 = imagecreatetruecolor($hei,$wid);

for(
$i = 0;$i < $wid; $i++)
{
for(
$j = 0;$j < $hei; $j++)
{
$ref = imagecolorat($im,$i,$j);
imagesetpixel($im2,($hei - 1) - $j,$i,$ref);
}
}
return
$im2;
}
?>

除了這些非常有用的函數之外!
To Top