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,就像它在图表上标记的那样(也称为gf),并且矩形的高度标记为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 三角形图像裁剪的主要内容,如果未能解决你的问题,请参考以下文章

从图像中裁剪出三角形

使用 PHP (GD) 进行图像裁剪

我需要一些帮助在 PHP (GD) 中裁剪图像

PHP GD - 围绕任何给定点裁剪图像

PHP 使用 GD 创建动态图像

在 iPhone 中裁剪图像的某些部分(以某种形状)