Как создать эффект «рыбий глаз» с помощью PHP GD - PullRequest
5 голосов
/ 09 декабря 2010

Есть ли способ сделать эффект FishEye (или преобразование Барреля) на изображении с помощью PHP-GD? Я нашел это с помощью некоторого кода, но мне трудно перенести его на PHP.

Как реализовать эффект объектива "рыбий глаз" (трансформация бочки) в MATLAB?

Ответы [ 2 ]

6 голосов
/ 12 декабря 2010

PHP с GD не может сделать это приемлемым способом, обработка изображения попиксельно будет очень медленной ...

Imagick поддерживает функцию, которая позволяет вам написать собственное выражение ( fximage ), после чего все будет обработано внутри Imagick.

Итак, я нашел способ сделать то, что вы просили в Imagick, я взял выражение из блога "Scott builds Software" - эффект "рыбий глаз" в 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;
?>

В любом случае, имейте в виду, что это все еще медленно, будьте осторожны с тем, что вы делаете с этим ...

2 голосов
/ 27 июня 2011

Но - Возможно с GD и быстро !! по сравнению с ImageMagick
enter image description here Создать новое изображение с размером (2 * SourceWidth) / PI .
Пройдите через каждый пиксель нового изображения и найдите расстояние от центра. d source = hypot (x-centerX, y-centerY)
Найти соответствующее расстояние в исходном изображении с помощью d dest. =2 * r * asin (d source / r) / 2
r - это половина ширины целевого изображения.
См. Примеры с эталонной оценкой: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);
     }
...