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%的差异。

注意:我使用的图片来自相机拍摄,因此没有涉及透明度。
我在Windows XP上使用PHP 5.3.0版本运行了测试
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;
}

//使用方法
$image = rotateImage($image, 'cw');
$image = rotateImage($image, 'ccw');
?>
1
slickdesign.com.au的shaun
7年前
imagerotate() 中的角度是逆时针旋转图像的度数,但虽然使用 '-90' 将图像顺时针旋转 90 度看起来很自然,但最终结果可能会出现轻微的角度偏差,并可能导致旋转后的图像略微模糊,出现背景或边框。过大的角度也可能出现采样问题。

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

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

$rotated = imagerotate( $image, $angle, $color );
?>
1
here.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 中某个地方存在一个长期存在的bug。

我的解决方案如下

<?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(): 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;

}

}

}
?>
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
匿名
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
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优化的整合
只需将其放在任何你想使用imagerotate进行90、180、270度旋转的地方。
<?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
函数 rotate($degrees)
{
if(
function_exists("imagerotate"))
$this->image = imagerotate($this->image, $degrees, 0);
else
{
函数
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
[email protected]
19年前
我喜欢[email protected]实现的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
[email protected]
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.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 );
}
?>
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
如果 ($ignore_transparent == 0) {
$temp = imagecolorallocatealpha($destimg, 255,255, 255, 127);
imagefill($destimg, 0, 0, $temp);
//如果设置了默认颜色或白色或魔术粉红色,则使用透明颜色
如果 ( ($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);
如果 (
$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");

?>
-1
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;
}
?>
-1
[email protected]
13年前
我之前在处理包含透明颜色的png图像时遇到一个问题,但最终找到了一个可行的解决方案。
所以我想分享一下。

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

// 根据相机exif数据自动旋转图像文件
// 如果指定了目标文件,则将其保存到该文件,否则将其显示给用户
// 请注意,当exif数据方向为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);

}
}
}
}

?>
-1
Sam Yong - [email protected]
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
[email protected]
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
[email protected]
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