2012-01-20 12 views
6

Potrzebuję zrobić ten efekt z php. Wiem, że IMG_FILTER_PIXELATE w filtrze obrazu PHP. Ale muszę go wygładzić i wygładzić? jak w tym obrazie:Piksel obrazu PHP?

image

Efekt ten będzie żadnej obraz przesłany przez użytkownika stają się piksele, a krawędź obrazu stają się czerwone (wiem IMG_FILTER_EDGEDETECT ale nie wiem jak go używać do zmiany krawędzi kolor).

Nie mam pojęcia, jak to zrobić.

+3

obrazu łączyłeś wygląd, jakby pochodził z filtra Photoshopa. Prawdopodobnie nie będziesz w stanie odtworzyć tego dokładnego wyglądu bez jakiegoś ładnego programowania manipulacji z ostrym obrazem. Czy możesz utworzyć zestaw przykładowych obrazów, jeden "przed" i jeden "po", który pokazuje dokładny efekt, którego szukasz? – Charles

+0

Dla efektu pixelate, myślę, że to jest jak patchworkowy filtr w Photoshopie. Jak mogę to zrobić? – just2cya

+0

http://www.flickr.com/photos/[email protected]/6729984045/ Tworzę to przy użyciu tekstury patchworku Photoshopa, a dla dolnego obrazu używam zamieniać kolor. – just2cya

Odpowiedz

14

Jako ostatnia odpowiedź była teoretyczna i wydawało się, że nie dość, że stworzyliśmy praktyczny przykład:
Uwaga: To jest daleko od "idealnej" i idealnej funkcji efektu pikselu, ale spełnia swoją funkcję. Możesz go edytować zgodnie z własnymi potrzebami.

<?php 
/* Function to make pixelated images 
* Supported input: .png .jpg .jpeg .gif 
* 
* 
* Created on 24.01.2011 by Henrik Peinar 
*/ 


/* 
* image - the location of the image to pixelate 
* pixelate_x - the size of "pixelate" effect on X axis (default 10) 
* pixelate_y - the size of "pixelate" effect on Y axis (default 10) 
* output - the name of the output file (extension will be added) 
*/ 
function pixelate($image, $output, $pixelate_x = 20, $pixelate_y = 20) 
{ 
    // check if the input file exists 
    if(!file_exists($image)) 
     echo 'File "'. $image .'" not found'; 

    // get the input file extension and create a GD resource from it 
    $ext = pathinfo($image, PATHINFO_EXTENSION); 
    if($ext == "jpg" || $ext == "jpeg") 
     $img = imagecreatefromjpeg($image); 
    elseif($ext == "png") 
     $img = imagecreatefrompng($image); 
    elseif($ext == "gif") 
     $img = imagecreatefromgif($image); 
    else 
     echo 'Unsupported file extension'; 

    // now we have the image loaded up and ready for the effect to be applied 
    // get the image size 
    $size = getimagesize($image); 
    $height = $size[1]; 
    $width = $size[0]; 

    // start from the top-left pixel and keep looping until we have the desired effect 
    for($y = 0;$y < $height;$y += $pixelate_y+1) 
    { 

     for($x = 0;$x < $width;$x += $pixelate_x+1) 
     { 
      // get the color for current pixel 
      $rgb = imagecolorsforindex($img, imagecolorat($img, $x, $y)); 

      // get the closest color from palette 
      $color = imagecolorclosest($img, $rgb['red'], $rgb['green'], $rgb['blue']); 
      imagefilledrectangle($img, $x, $y, $x+$pixelate_x, $y+$pixelate_y, $color); 

     }  
    } 

    // save the image 
    $output_name = $output .'_'. time() .'.jpg'; 

    imagejpeg($img, $output_name); 
    imagedestroy($img); 
} 


pixelate("test.jpg", "testing"); 


?> 

Jest to przykładowa funkcja do tworzenia pikselowego efektu na obrazach. Oto przykład rezultaty korzystania z tej funkcji:
oryginalny:

Pixelated 5px:

piksele 10px:

piksele 20px:

+0

Och, dziękuję. Ale potrzebuję, żeby to było jak w \t flickr.com/photos/[email protected]/6729984045, Stworzyłem to używając tekstury patchworku Photoshopa. Na tym obrazku wygląda na to, że każdy kwadrat jest wytłoczony. Czy to możliwe? – just2cya

+0

Zasadniczo ... musisz zmienić ciemność zewnętrznych pikseli kwadratu ... to więcej pracy i niestety nie mam czasu, aby napisać scenariusz teraz. –

+0

W końcu używam twojego skryptu i dodam ten skrypt z http://stackoverflow.com/questions/9106893/php-emboss-with-color/9107056#9107056 Dziękuję! – just2cya

1

Tu idzie teoretycznie:
Masz zdjęcie:

RGBRGBRGBRGB
GBRGBRGBRGBR
GBRGBRGBRRGB
BGRGBGRGGRBG

Take kolor pierwszego piksela i ustawić ten sam kolor na placu obok piksele (zarówno w dół, jak i w prawo). Następnie wybierz kolor 5-go piksela (jako że 4 na początku mają już ten sam kolor). Jeśli skończysz w pierwszym wierszu, przejdź +3 wiersze w dół i zacznij od nowa.

Więc dostaniesz:
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB

W PHP można użyć następujących funkcji, aby w ten sposób:
http://php.net/manual/en/function.imagecolorat.php aby wybrać kolor piksela
http://php.net/manual/en/function.imagecolorset.php do ustaw kolor piksela, aby uzyskać szeroką szerokość obrazu
http://php.net/manual/en/function.imagesy.php get wysokość obrazu

użycie pętli thru pikseli obrazu

+0

Cześć, dziękuję za odpowiedź. Mogę dokonać zamiany koloru za pomocą tych funkcji, o których wspomniałeś. Teraz muszę znaleźć sposób na efekt pixellate. Czy jest jakiś pomysł? – just2cya

+0

Cały post dotyczył tego, jak uzyskać efekt pixellate ... jak mógłbyś tego przegapić? :) Zrobię przykładowy skrypt z komentarzami. Zaczekaj na nową odpowiedź/komentarz. –

2

Dziękuję za odpowiedź . Użyłem twojej funkcji i dodałem kolejną pętlę, aby zmienić kolor zewnętrznego piksela kwadratów za pomocą funkcji o nazwie imagelinethick w http://www.php.net/manual/en/function.imageline.php.Więc stało się:

<?php 
$image = imagecreatefromjpeg('Penguins.jpg'); 
$imagex = imagesx($image); 
$imagey = imagesy($image); 

$pixelate_y=10; 
$pixelate_x=10; 
$height=$imagey; 
$width=$imagex; 
for($y = 0;$y < $height;$y += $pixelate_y+1) 
{ 
    for($x = 0;$x < $width;$x += $pixelate_x+1) 
    { 
    // get the color for current pixel 
    $rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y)); 

    // get the closest color from palette 
    $color = imagecolorclosest($image, $rgb['red'], $rgb['green'], $rgb['blue']); 

    imagefilledrectangle($image, $x, $y, $x+$pixelate_x, $y+$pixelate_y, $color); 
    } 
} 


for($y = 0;$y < $height;$y += $pixelate_y+1) 
{ 
for($x = 0;$x < $width;$x += $pixelate_x+1) 
{ 
    //make a border line for each square 
    $rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y)); 
    $color = imagecolorclosest($image, 123, 123, 123); 
    imagelinethick($image, $x, $y, $x, $y+$pixelate_y, $color, 1); 
    imagelinethick($image, $x, $y, $x+$pixelate_x, $y, $color, 2); 
}  
} 

function imagelinethick($image, $x1, $y1, $x2, $y2, $color, $thick = 1) 
{ 
    /* this way it works well only for orthogonal lines 
    imagesetthickness($image, $thick); 
    return imageline($image, $x1, $y1, $x2, $y2, $color); 
    */ 
    if ($thick == 1) { 
     return imageline($image, $x1, $y1, $x2, $y2, $color); 
    } 
$t = $thick/2 - 0.5; 
if ($x1 == $x2 || $y1 == $y2) { 
    return imagefilledrectangle($image, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color); 
} 
$k = ($y2 - $y1)/($x2 - $x1); //y = kx + q 
$a = $t/sqrt(1 + pow($k, 2)); 
$points = array(
    round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a), 
    round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a), 
    round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a), 
    round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a), 
); 
imagefilledpolygon($image, $points, 4, $color); 
return imagepolygon($image, $points, 4, $color); 
} 

header("Content-Type: image/JPEG"); 
imageJPEG($image, "", 75); 

?> 

Rezultatem jest tak: http://www.flickr.com/photos/[email protected]/6759029339/

Ale myślę, że to nadal potrzebują poprawy, aby uczynić go bardziej płynne.

+0

Ktoś może pomóc? – just2cya

0

To jest moja próba rozwiązania problemu.

Możesz zmienić rozmiar bloku pikseli i zastosować efekt rozmycia, który zmiękcza efekt na obrazach o wysokim kontraście. Może być powolny na dużych obrazach z małymi rozmiarami bloków pikseli.

Skrypty przechowuje kolory odpowiednich pikseli w tablicy. Następnie wytłacza obraz, zmienia wymagany kontrast, pikseluje obraz za pomocą funkcji imagefilter(), a następnie (jeśli ustawiono poprawianie kafelków) ponownie wytłocza (zwiększa to efekt 3D na końcowych płytkach). Jeśli rozmycie jest wymagane, skrypt zastosuje rozmycie Gaussa. Następnie skrypt rysuje wypełnione kwadraty za pomocą tablicy kolorów, aby utworzyć kolorowy piksel w obrębie wytłaczanych obramowań płytek.

function pixelatemboss($image,$blockwidth=10,$blur=5,$tileenhance="true",$contrast=0,$negate="true") 
{ 
    if($blockwidth>1) 
    { 
     imagefilter($image,IMG_FILTER_CONTRAST,$contrast); 

     for($x=1;$x<imagesx($image);$x=$x+$blockwidth) 
     { 
      for($y=1;$y<imagesy($image);$y=$y+$blockwidth) 
      { 
       $color[$x][$y]=imagecolorat($image,$x,$y); 
      } 
     } 

     imagefilter($image,IMG_FILTER_EMBOSS); 
     imagefilter($image,IMG_FILTER_CONTRAST,$contrast); 
     imagefilter($image,IMG_FILTER_PIXELATE,$blockwidth,false); 
     if($tileenhance=="true") 
     { 
      imagefilter($image,IMG_FILTER_EMBOSS); 
     } 
     for($b=0;$b<$blur;$b++) 
     { 
      imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR); 
     } 
     for($x=1;$x<imagesx($image);$x=$x+$blockwidth) 
     { 
      for($y=1;$y<imagesy($image);$y=$y+$blockwidth) 
      { 
       $rgb=$color[$x][$y]; 
       $r = ($rgb >> 16) & 0xFF; 
       $g = ($rgb >> 8) & 0xFF; 
       $b = $rgb & 0xFF; 
       $col=imagecolorallocate($image,$r,$g,$b); 
       imagefilledrectangle($image,$x,$y,$x+($blockwidth-2),$y+($blockwidth-2),$col); 
      } 
     } 
    } 
    return $image; 
} 
0

Uwaga dla PHP 5.4 i aż trzeba użyć:

imageJPEG($image, NULL, 75); 

Nie można już podać NULL za pomocą podwójny cudzysłów (jak ten przykład):

imageJPEG($image, "", 75); 
Powiązane problemy