PHP GD 三角形图像裁剪
Posted
技术标签:
【中文标题】PHP GD 三角形图像裁剪【英文标题】:PHP GD Triangle Image Crop 【发布时间】:2013-06-11 16:48:58 【问题描述】:我注意到有一些脚本将尝试执行此操作,但没有一个非常适合我的情况。
我收集了一些我发现的脚本来尝试提出正确的解决方案。
但是我现在遇到了 2 个问题。
-
图像未居中。
三角形的边长不相等。
演示在http://owenmelbourne.com/triangle.php
代码是
$src = imagecreatefromjpeg ('http://uat.eruptedevents.secureping.co.uk/media/images/upload/1200/154.jpg');
// Get image width/height
$srcWidth = imagesx ($src);
$srcHeight = imagesy ($src);
// Get centre position
$centreX = floor ($srcWidth / 2);
$centreY = floor ($srcHeight / 2);
// Set new image size and start x/y
$destWidth = $srcWidth;
$destHeight = $srcHeight;
$destSX = 0;
$destSY = $centreY;
// Create the image
$square = 500;
if( $srcWidth >= $srcHeight )
$square = $srcHeight;
else
$square = $srcWidth;
$shift = array ("left" => 0, "top" => 0);
$shift["left"] = ( $srcWidth / 4 ) * -1;
$shift["top"] = ( $srcHeight / 4 ) * -1;
$dest = imagecreatetruecolor ($square, $square);
// Copy from source
imagecopy ($dest, $src, $shift["left"], $shift["top"], 0, 0, $destWidth, $destHeight);
// OK... we now have the correctly sized rectangle copied over from the source image
// Lets cut it down and turn it into the triangle we want by removing the other triangles
// We remove the area by defining another colour as transparent and creating shapes with that colour
$colRed = imagecolorallocatealpha ($dest, 255, 0, 0, 0);
$blue = imagecolorallocatealpha ($dest, 0, 0, 244, 0);
imagecolortransparent ($dest, $colRed);
$sidelength = $square;
imagefilledpolygon ($dest, array (
0, 0,
$square/2, 0,
0, $square
), 3, $colRed);
imagefilledpolygon ($dest, array (
$square, 0,
$square, $square,
$square/2, 0
), 3, $colRed);
$dest2 = imagecreatetruecolor ($square, $square);
// Output new image
header ('Content-Type: image/png');
imagepng ($dest);
// Clean up
imagedestroy ($thumbNail);
imagedestroy ($dest);
我将如何从中间截取一个完美的三角形并将其作为图像返回?
非常感谢
【问题讨论】:
设置$square = 500
的目的是什么,因为之后您直接用源的较大尺寸覆盖它。你想要一个 500px 的正方形吗? $shift
偏移量计算看起来也很狡猾。
是旧代码,我一直在试图弄清楚,所以就留在那里,但不,我希望三角形尽可能大。并且 $shift 计算很可能是狡猾的!我绝不是一个能做比乘法表更多的数学家:P - 这里可能有很多错误,但我以前从未做过,这就是为什么它一团糟!
那么您的目标是什么,请确保在问题中非常清楚,因为很难从代码中分辨出它目前的情况。您是否想要一个基于平面的三角形切口,其顶点位于图像的中点,与原始尺寸相同?
我想输出一个二维三角形,其填充作为背景图像。如此处所示 - owenmelbourne.com/triangle.php 但是,我希望三角形的所有边都等长,因此三角形的中心点也是原始图像的中心点。我希望三角形与原始图像一样大。这更有意义吗?谢谢你
是的,这是有道理的,三角形是否必须向上,即。有特定的方向吗?
【参考方案1】:
矩形中的等边三角形
是的,假设您想要一个矩形内的最大等边三角形,其平面平行于水平轴,即。最上面的点,那么根据矩形的纵横比有两种情况。
横向矩形(宽>高)
在这种情况下,矩形的高度是限制因素。
任务是确定三角形边的长度,并用它找到三角形的两个底点的位置,从矩形的中点取一半的长度。
如果我们将三角形长度称为e
,就像它在图表上标记的那样(也称为g
和f
),并且矩形的高度标记为a
,那么快速了解一下三角函数状态那:
sin 60 = opp / hyp = a / e = sqrt(3) / 2
所以
e = 2a / sqrt(3)
图中的水平边我们可以称为b
,中点显然在b / 2
,所以三角形底边的点在[ (b / 2) ± (e / 2) , 0 ]
。
要执行裁剪,请执行以下步骤:
创建与源大小相同的新图像 将整个目的地填充为透明 从三角形的两个基点之间的源复制一个矩形,整个高度,到相同的位置 目的地 从三角形的两个基点到与上面平行的矩形的顶部,在两侧用透明填充三角形 它们到矩形顶部的中点
纵向矩形(宽度
在这种情况下,宽度是限制因素。
因此三角形边的长度就是矩形的宽度,所以这是已知的。需要计算的是三角形的高度。
如果我们称高度为H
,如图所示,宽度为b
,如前所述,那么简单的三角函数表示:
sin 60 = opp / hyp = H / b = sqrt(3) / 2
所以
H = b x sqrt(3) / 2
图中的垂直边我们可以称为a
,中点在a / 2
,所以三角形底边的点在[ 0 , (a / 2) + (H / 2) ]
和[ b , (a / 2) + (H / 2) ]
,三角形的尖端三角形E
位于[ (b / 2) , (a / 2) - (H / 2) ]
。
要执行裁剪,请执行以下步骤,(最初是两个 步骤与之前相同):
创建与源大小相同的新图像 将整个目的地填充为透明 从三角形
E
的底部和尖端之间的全宽源复制一个矩形到目标中的相同位置 从三角形的两个基点到三角形的尖端E
上的点用两边的透明填充三角形 与E
相同高度的边缘与基点在同一侧 有问题的三角形
注意。在你有一个正方形的情况下,任何一个计算都应该工作,尽管景观计算对我来说似乎更简单,所以我会使用它。
代码
改编自你自己的,所以不是我通常的编码风格,但它有效。花了一段时间,因为透明度在 GD 中有点让人头疼。
原创
裁剪 (使用下面的代码创建)
<?php
// Acquire image
$src = imagecreatefromjpeg ('http://i.stack.imgur.com/YlnCJ.jpg');
// Get image width/height
$srcWidth = imagesx ($src);
$srcHeight = imagesy ($src);
// Get centre position
$centreX = floor ($srcWidth / 2);
$centreY = floor ($srcHeight / 2);
// Calculate triangle length (base) and points
if ( $srcWidth >= $srcHeight )
$base = (2 * $srcHeight) / sqrt(3);
$points = array( 'a' => array( 'x' => $centreX - ( $base / 2 ),
'y' => $srcHeight ),
'b' => array( 'x' => $centreX + ( $base / 2 ),
'y' => $srcHeight ),
'c' => array( 'x' => $centreX,
'y' => 0 ) );
else
$base = $srcWidth;
$height = $base * sqrt(3) / 2;
$points = array( 'a' => array( 'x' => 0,
'y' => $centreY + ( $height / 2 ) ),
'b' => array( 'x' => $srcWidth,
'y' => $centreY + ( $height / 2 ) ),
'c' => array( 'x' => $centreX,
'y' => $centreY - ( $height / 2 ) ) );
// Create destination, same size as source
$dest = imagecreatetruecolor ($srcWidth, $srcHeight);
// Setup full alpha handling for pngs (8-bit)
imagealphablending ($dest, false);
imagesavealpha ($dest, true);
// Define a transparent colour
$colTrans = imagecolorallocatealpha ($dest, 255, 255, 255, 127);
// If old png transparency was used, setting the transparency colour
// would be needed, with 8-bit it is not
// imagecolortransparent ($dest, $colTrans);
// Make the image transparent
imagefill ($dest, 0, 0, $colTrans);
// Copy from source just the rectangle flush with the triangle
imagecopy ($dest, $src, // Images
$points['a']['x'], $points['c']['y'], // Destination x,y
$points['a']['x'], $points['c']['y'], // Source x,y
$points['b']['x'] - $points['a']['x'], // Width
$points['a']['y'] - $points['c']['y']); // Height
// Fill out the triangles within that area not wanted with transparent
// Left side
imagefilledpolygon ($dest, array( $points['a']['x'], $points['a']['y'],
$points['c']['x'], $points['c']['y'],
$points['a']['x'], $points['c']['y'] ),
3, $colTrans);
// Right side
imagefilledpolygon ($dest, array( $points['b']['x'], $points['b']['y'],
$points['c']['x'], $points['c']['y'],
$points['b']['x'], $points['c']['y'] ),
3, $colTrans);
// Output new image
header ('Content-Type: image/png');
imagepng ($dest);
// Clean up
imagedestroy ($src);
imagedestroy ($dest);
【讨论】:
哇,谢谢你的解释真的很有帮助!试图用你的笔记弄清楚,然后注意到你已经添加了代码,非常感谢你!非常感谢! 很好,这不是一件不寻常的事情,因此值得在网站上为它提供一个体面的答案。 完全,我相信这将对其他人有所帮助,我可能会发布一个稍微修改过的图像,其中最终图像会裁剪到三角形的底部以避免多余的间距。 是的,很容易做到,只需将新的图像尺寸调整为点之间的距离。$destWidth = $points['b']['x'] - $points['a']['x']
和 $destHeight = $points['a']['y'] - $points['c']['y']
,然后将 imagecopy()
目标 x/y 更改为 0, 0
。应该这样做。
啊,这些点还需要从它们中减去 $points['a']['x']
/ $points['c']['y']
以进行三角形擦除。【参考方案2】:
ImageArtist 是 GD 的一个包装器,可以让我编写的开发人员更轻松。您可以使用它来创建任何类型的多边形
$triangle = new Triangle("http://i.stack.imgur.com/YlnCJ.jpg");
$triangle->setPointA(50,0,true);
$triangle->setPointB(100,100,true);
$triangle->setPointC(0,100,true);
$triangle->build();
$triangle->dump(); //this is for debugging only read documentation for more operations
最终输出是这样的
【讨论】:
以上是关于PHP GD 三角形图像裁剪的主要内容,如果未能解决你的问题,请参考以下文章