2010-12-09 15 views
5

¿Hay alguna forma de realizar un efecto de ojo de pez (o transformación de barril) en una imagen con PHP-GD? Encontré esto con un poco de código, pero tengo dificultades para portarlo a PHP.Cómo crear un efecto ojo de pez con PHP GD

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

+0

ya sea que usted tiene que poner en práctica el ojo de pez algo en sí directamente, lo que va a ser SLOOOWWWW. O busca otra forma de hacerlo. Como macro'n en photoshop con exec() o similar ... No conozco a nadie que haya hecho esto ... – DampeS8N

+0

Si tiene conocimientos de programación C, puede descargar el código fuente * gd * e implementarlo una nueva característica, ¡y publícala! Ese código es tan viejo ... De todos modos, si encuentras una solución, ¡por favor publícala! También tengo curiosidad por saber ... ¿Cuál es tu sistema operativo? –

+0

Es factible, pero implica más que el código MATLAB. PHP no es muy adecuado para la aritmética de bytes y es probable que necesite una matriz de 3 capas (R, G, B). Así que también sugiero recurrir a 'exec (imagemagick)'. – mario

Respuesta

2

Pero - Es posible con GD y rápido !! en comparación con ImageMagick
enter image description here Cree una nueva imagen con el tamaño de (2 * SourceWidth)/PI.
Camine a través de cada píxel de la nueva imagen y encuentre la distancia desde el centro. d fuente = hypot (x-centerx, y-centery)
encontrar la distancia correspondiente imagen de origen por d dest. = 2 * r * asin (d fuente/r)/2
r es la mitad de la anchura de la imagen de destino.
Ver ejemplos con marca de banco: 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); 
    } 
6

PHP con GD no puede hacer tal cosa en una forma aceptable, procesando un píxel por píxel de la imagen va a ser muy lento ...

Imagick es compatible con una función que permite usted debe escribir su propia expresión (fximage), después de eso todo será manejado internamente dentro de Imagick.

Así que he encontrado una manera de hacer lo que ha solicitado en Imagick, he tomado la expresión de "Scott builds Software" blog - fisheye effect in imagick. Puedes leer la explicación completa de la expresión en su blog. Puede obtener más documentación sobre esta función en el sitio oficial ImageMagick, donde puede aprender cómo puede crear sus propias expresiones.

Tenga en cuenta que la documentación de PHP sobre el valor de retorno es incorrecta, también he comentado allí. La función devuelve el objeto Imagick real.

Así que aquí es su código:

<?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; 
?> 

De todos modos, tenga en cuenta que esto sigue siendo lento, tener cuidado con lo que haces con ese ...

+0

¡Muchas gracias! ¡Eres mi héroe! :RE – Daantje