如何使用 PHP GD 创建鱼眼效果

发布于 2024-10-07 04:18:35 字数 219 浏览 3 评论 0 原文

有没有办法使用 PHP-GD 对图像进行 FishEye(或桶形变换)效果? 我通过一些代码发现了这一点,但我很难将其移植到 PHP。

如何在 MATLAB 中实现鱼眼镜头效果(桶形变换) ?

Is there a way to do a FishEye (or Barrel transformation) effect on a image with PHP-GD?
I found this with some code, but I have a hard time porting it to PHP.

How can I implement a fisheye lens effect (barrel transformation) in MATLAB?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

聚集的泪 2024-10-14 04:18:35

PHP 和 GD 无法以可接受的方式完成这样的事情,逐像素处理图像会非常慢...

Imagick 确实支持一个函数,使您能够编写自己的表达式(fximage),之后一切都将在 Imagick 内部处理。

所以我找到了一种方法来完成您在 Imagick 中所要求的操作,我从 “Scott 构建软件”博客 - imagick 中的鱼眼效果。您可以在他的博客中阅读该表达式的完整解释。有关此功能的更多文档可在官方 ImageMagick 站点上找到,您可以在那里了解如何可以构建自己的表达式。

请注意,关于返回值的 PHP 文档是不正确的,我也在那里发表了评论。该函数返回实际的 Imagick 对象。

所以这是你的代码:

<?php
/* Create new object */
$im = new Imagick();
/* Create new checkerboard pattern */
$im->newPseudoImage(100, 100, "pattern:checkerboard");
/* Set the image format to png */
$im->setImageFormat('png');
/* Fill background area with transparent */
$trans = Imagick::VIRTUALPIXELMETHOD_TRANSPARENT;
$im->setImageVirtualPixelMethod($trans);
/* Activate matte */
$im->setImageMatte(true);

/* This is the expression that define how to do the fisheye effect */
$distort_expression = 
'kk=w*0.5;
ll=h*0.5;
dx=(i-kk);
dy=(j-ll);
aa=atan2(dy,dx);
rr=hypot(dy,dx);
rs=rr*rr/hypot(kk,ll);
px=kk+rs*cos(aa);
py=ll+rs*sin(aa);
p{px,py}';

/* Perform the distortion */ 
$im = $im->fxImage($distort_expression);

/* Ouput the image */   
header("Content-Type: image/png");
echo $im;
?>

无论如何,请记住这仍然很慢,无论你做什么,都要小心......

PHP with GD can't do such a thing in an acceptable way, processing an image pixel-by-pixel will be really slow...

Imagick does support a function that enable you to write your own expression (fximage), after that everything will be handled internally within Imagick.

So I've find a way to do what you've requested in Imagick, I've taked the expression from "Scott builds Software" blog - fisheye effect in imagick. You can read the full explanation of the expression in his blog. Further documentation of this function is available at the official ImageMagick site, you can learn there how you can build your own expressions.

Please note that the PHP documentation about the return value is incorrect, I've also commented there. The function return the actual Imagick object.

So here is your code:

<?php
/* Create new object */
$im = new Imagick();
/* Create new checkerboard pattern */
$im->newPseudoImage(100, 100, "pattern:checkerboard");
/* Set the image format to png */
$im->setImageFormat('png');
/* Fill background area with transparent */
$trans = Imagick::VIRTUALPIXELMETHOD_TRANSPARENT;
$im->setImageVirtualPixelMethod($trans);
/* Activate matte */
$im->setImageMatte(true);

/* This is the expression that define how to do the fisheye effect */
$distort_expression = 
'kk=w*0.5;
ll=h*0.5;
dx=(i-kk);
dy=(j-ll);
aa=atan2(dy,dx);
rr=hypot(dy,dx);
rs=rr*rr/hypot(kk,ll);
px=kk+rs*cos(aa);
py=ll+rs*sin(aa);
p{px,py}';

/* Perform the distortion */ 
$im = $im->fxImage($distort_expression);

/* Ouput the image */   
header("Content-Type: image/png");
echo $im;
?>

Anyway, keep in mind that this is still slow, be careful with whatever you do with that...

坏尐絯℡ 2024-10-14 04:18:35

但是 - 与 ImageMagick 相比,可以使用 GD 并且速度更快!!
输入图像描述在这里>><br />
创建大小为 <i>(2*SourceWidth)/PI</i> 的新图像。<br />
遍历新图像的每个像素并找到距中心的距离。<br />
<i>d<sub>源</sub>=hypot(x-centerX,y-centerY)</i><br />
通过 <i>d<sub>dest.</sub>=2*r*asin(d<sub>source</sub>/r)/2</i><br /> 找到源图像中对应的距离<br />
<i>r</i> 是目标图像的半宽。<br />
请参阅带有基准标记的示例:<a href=http://meindesign.net/picture2bubble/picture2bubble.php

function fisheye($infilename,$outfilename){
     $im=imagecreatefrompng($infilename);
     $ux=imagesx($im);//Source imgage width(x) 
     $uy=imagesy($im);//Source imgage height(y) 
     $umx=$ux/2;//Source middle
     $umy=$uy/2;
     if($ux>$uy)$ow=2*$uy/pi();//Width for the destionation image
     else $ow=2*$ux/pi();
     $out=imagecreatetruecolor($ow+1,$ow+1); 
     $trans=imagecolortransparent($out,ImageColorAllocate($out,0,0,0));
     imagefill($im,1,1,$trans); 
     for($c=0;$c<imagecolorstotal($im);$c++){//Copy palette
        $col=imagecolorsforindex($im,$c);
        imagecolorset($out,$c,$col[red],$col[green],$col[blue]);
        }
     $om=$ow/2;//destination middle
     for($x=0;$x<=$ow;++$x){//Loop X in destination image
        for($y=0;$y<=$ow;++$y){//Loop y in destination image
           $otx=$x-$om;//X in relation to the middle
           $oty=$y-$om;//Y in relation to the middle
           $oh=hypot($otx,$oty);//distance
           $arc=(2*$om*asin($oh/$om))/(2);
           $factor=$arc/$oh;
           if($oh<=$om){//if pixle inside radius
             $color=imagecolorat($im,round($otx*$factor+$umx),round($oty*$factor+$umy));
             $r = ($color >> 16) & 0xFF;
             $g = ($color >> 8) & 0xFF;
             $b = $color & 0xFF;
             $temp=imagecolorexact($out, $r, $g, $b);
             imagesetpixel($out,$x,$y,$temp);
             }
           }
        }
     imagepng($out,$outfilename);
     }

But - It is possible with GD and fast!! in comparison with ImageMagick
enter image description here
Create a new image with the size of (2*SourceWidth)/PI.
Walk trough each pixel of the new image and find the distance from the center.
dsource=hypot(x-centerX,y-centerY)
Find the corresponding distance in the source image by ddest.=2*r*asin(dsource/r)/2
r is the half width of the destination image.
See examples with bench mark: http://meindesign.net/picture2bubble/picture2bubble.php

function fisheye($infilename,$outfilename){
     $im=imagecreatefrompng($infilename);
     $ux=imagesx($im);//Source imgage width(x) 
     $uy=imagesy($im);//Source imgage height(y) 
     $umx=$ux/2;//Source middle
     $umy=$uy/2;
     if($ux>$uy)$ow=2*$uy/pi();//Width for the destionation image
     else $ow=2*$ux/pi();
     $out=imagecreatetruecolor($ow+1,$ow+1); 
     $trans=imagecolortransparent($out,ImageColorAllocate($out,0,0,0));
     imagefill($im,1,1,$trans); 
     for($c=0;$c<imagecolorstotal($im);$c++){//Copy palette
        $col=imagecolorsforindex($im,$c);
        imagecolorset($out,$c,$col[red],$col[green],$col[blue]);
        }
     $om=$ow/2;//destination middle
     for($x=0;$x<=$ow;++$x){//Loop X in destination image
        for($y=0;$y<=$ow;++$y){//Loop y in destination image
           $otx=$x-$om;//X in relation to the middle
           $oty=$y-$om;//Y in relation to the middle
           $oh=hypot($otx,$oty);//distance
           $arc=(2*$om*asin($oh/$om))/(2);
           $factor=$arc/$oh;
           if($oh<=$om){//if pixle inside radius
             $color=imagecolorat($im,round($otx*$factor+$umx),round($oty*$factor+$umy));
             $r = ($color >> 16) & 0xFF;
             $g = ($color >> 8) & 0xFF;
             $b = $color & 0xFF;
             $temp=imagecolorexact($out, $r, $g, $b);
             imagesetpixel($out,$x,$y,$temp);
             }
           }
        }
     imagepng($out,$outfilename);
     }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文