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 个注释

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);
?>
Mike Knoop
15 年前
不要被误导,以为此函数会原地旋转图像资源句柄。虽然文档目前没有指定返回值,但我发现以下返回值是正确的

"成功时返回图像资源标识符,错误时返回 FALSE。"

只需确保你正在执行类似于...
<?php
$rotated_img
= imagerotate($src_img, 45, $color)
?>

-Mike
henzeberkheij at gmail dot com
12 年前
请记住,此函数是逆时针旋转的。如果你想顺时针旋转 90 度,你必须告诉 imagerotate 逆时针旋转 270 度。

$angle = 360-$angle;
xavtak at gmail dot com
13 年前
我在这里对三种旋转图像的方法进行了基准测试。

我使用了一张 1600 x 1200 的 jpeg 图片,它在磁盘上复制了十次。我循环遍历它们,使用这三种方法中的任何一种应用 CW 旋转。

第一个算法(“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% 的差异。

注意:我使用的图片是从相机拍摄的,所以没有涉及透明度。
我在 Windows XP 上使用 PHP 版本 5.3.0 运行了这些测试
xarris_ at hotmail dot com
8 年前
imagerotate() 的一个问题是它可能需要比可用内存更多的内存。它在我的脚本中失败了,所以我尝试使用 ini_set('memory_limit', '256M') 来增加它
现在一切都正常工作了。
joseluis at pellicer dot org
15 年前
关于 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);
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;
}

?>
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;
}
}

?>
AJenbo
15 年前
我修改了 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');
?>
shaun at slickdesign dot com dot au
6 年前
imagerotate() 中的角度是图像逆时针旋转的度数,但是,虽然使用 '-90' 将图像顺时针旋转 90 度看起来很自然,但最终结果可能会出现轻微的角度,并且可能会导致旋转后的图像出现轻微的模糊,以及背景或边框。过大的角度也可能出现采样问题。

防止这些问题的最简单方法是确保所有角度都在 0 到 360 之间。

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

$rotated = imagerotate( $image, $angle, $color );
?>
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;
}
?>
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);
?>
david at horizon-nigh dot org
15 年前
由于某些原因,我无法使“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(): could not find imagemagick binary, original image returned', 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 conversion failed, original image returned', E_USER_WARNING );
return $source_image;

}

} else {

//trigger_error( 'imagerotate(): could not write to ' . $file1 . ', original image returned', E_USER_WARNING );
return $source_image;

}

}

}
?>
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);
}
}
?>
foi02 at cartefoi dot net
15 年前
对于那些在 Ubuntu 上寻找 GD 库的人,我在我的服务器上放了一份副本:http://www.cartefoi.net/compl_compl_2.php
找到它真的很难,有人给了我他的。非常感谢他(留言在上面)。
Anonymous
15 年前
抱歉,之前的类包含一个错误,旋转后的原始图像会移动 1 像素并得到不想要的“边框”。

仔细阅读了本地辩论后,我使用 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
Bert Vandeghinste
15 年前
我现在使用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)); ?>
cbl25
15 年前
以下是一个简单的函数,用于将非正方形图像顺时针旋转 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;
}
?>
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);
}
}
?>
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);
}
}
?>
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; }}
?>
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 是以顺时针方向表示的角度。
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);
}
}
?>
wulff at fyens dot dk
19 年前
我喜欢 darren at lucidtone dot com 实现的 rotateImageBicubic 函数。但是它只是剪掉了图像中超出原始图像部分。

我修复了这个问题,尽管我承认我的解决方案有点天真。但它可能对某人有用。

另外,他的 bicubic 实现在我的机器上无法正常工作,所以我把它去掉了。如果你需要它,只需要从上面复制粘贴就可以了。

<?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);
}

?>
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);
?>
Borszczuk
19 年前
以下是一个函数,它实现了直角(90 度的倍数 - 90、180、270)旋转,如果你需要一个旋转,但缺少本机的 imagerotate(),或者你不想像 imagerotate() 那样将非正方形图像缩小。正如你可能注意到的,它不是一个自包含函数,因为 180 度旋转是通过 ImageFlip() 函数处理的,以获得性能提升。使用的 ImageFlip() 函数在此处发布:https://php.net/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 );
}
?>
jon at driestone dot com
19 年前
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);
}
}
}
?>
dev at imglib dot endofinternet dot net
14 年前
您可以通过更改来为您的 png 图像添加透明背景
<?php
if ($ignore_transparent == 0) {
imagefill($destimg, 0, 0, imagecolorallocatealpha($destimg, 255,255, 255, 127));
imagesavealpha($destimg, true);
}
?>
to
<?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);
}
?>
gglockner AT NOSPAMdwaffler DOT com
15 年前
如果您打算手动进行旋转而不是使用 imagerotate 函数,您可以使用 imagecopy 函数复制单个像素,而不是确定像素颜色并设置像素。这不仅更短、更简洁,而且它也适用于非真彩色图像(在我的系统上,imagecolorat 在处理非真彩色图像时会失败)。
m dot quinton at gmail dot com
17 年前
对于大型文件,如果缺少 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 -");
}

?>
simon_nuttall at hotmail dot com
18 年前
以下内容可能会有用。它将图像中最大的中心圆提取到指定大小的正方形中,并可以选择旋转。正方形的其余部分将设置为透明,因此可用于在其他图像上绘制。我将其命名为“双筒望远镜效果”,因为在一些老式电视节目中,每当他们展示有人通过双筒望远镜看东西时,屏幕上就会显示一个带有黑色边缘的大圆形图像。

<?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, "This is a sample image to illustrate the binocular effect", imagecolorallocate($im, 192, 0, 0));
$img=image_binocular_effect($src, 72, 50);
ImagePNG($img,"test.png");

?>
darren at lucidtone dot com
19 年前
这是一个适用于没有 imagerotate() 函数的服务器的便捷函数。它基于 ron at korving dot demon dot nl 在 imagecopyresampled 手册页面上的评论。

我对透明度的处理还没有完全搞懂,但这个函数似乎能够正常处理。它不会调整大小以适应边界,它只旋转,并且你将丢失图像框外部的任何内容。

双三次模式非常慢。

如果你希望能够更改背景颜色,请传入一种颜色并在指定位置使用它。我使用的代码行只是将其设置为透明。

<?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;
}
?>
kraeh at gmx dot net
13 年前
我遇到了一个包含透明颜色的 png 图像的问题,但我找到了一个适合我的解决方案。
所以我想我会分享它。

<?php
$angle
=45;
$im=imagerotate($im, $angle, -1);
imagealphablending($im, true);
imagesavealpha($im, true);
?>
TNTcode
6 年前
<?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自动旋转图像(在编辑之前)
// 使用imagemagik,它有一个简单的选项
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);

}
}
}
}

?>
Sam Yong - hellclanner at live dot com
12 年前
请注意,从imagerotate()函数返回的图像资源与您的原始图像资源完全不同。

<?php

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

?>

这将输出

resource(2, gd)
resource(3, gd)
Leo
13 年前
// 角度以度为单位,顺时针,允许的值从 0 到 360 度
function rotateImage ($image, $angle)
{
if ( ($angle < 0) || ($angle > 360) )
{
exit ("Error, angle passed out of range: [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;
}
fernando_empresarial at ig dot com dot br
15 年前
<?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);
?>
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