2013-03-21 36 views
5

Tôi đã thử nghiệm với thư viện GD để mô phỏng hiệu ứng muliply của Photoshop, nhưng tôi chưa tìm được giải pháp làm việc.Nhân bộ lọc với thư viện GD của PHP

Theo Wikipedia, sự pha trộn nhân chế độ:

[...] nhân với số lượng cho mỗi điểm ảnh của lớp trên cùng với các điểm ảnh tương ứng cho các lớp dưới cùng. Kết quả là một hình ảnh tối hơn.

Có ai biết cách nào để đạt được điều này bằng PHP không? Bất kì sự trợ giúp nào đều được đánh giá cao.

Trả lời

13

Bạn cần phải thực hiện tất cả các điểm ảnh của hình ảnh của bạn, sau đó nhân lên mỗi giá trị RGB với màu nền của bạn/255 (đó là công thức Photoshop). Ví dụ, một file JPG với nền đỏ lọc màu nhân, lưu lại dưới dạng tập tin PNG cho kết quả tốt hơn:

<?php 
$filter_r=216; 
$filter_g=0; 
$filter_b=26; 
$suffixe="_red"; 
$path=YOURPATHFILE; 

if(is_file($path)){ 
    [email protected]($path); 
    $new_path=substr($path,0,strlen($path)-4).$suffixe.".png"; 

    $imagex = imagesx($image); 
    $imagey = imagesy($image); 
    for ($x = 0; $x <$imagex; ++$x) { 
     for ($y = 0; $y <$imagey; ++$y) { 
      $rgb = imagecolorat($image, $x, $y); 
      $TabColors=imagecolorsforindex ($image , $rgb); 
      $color_r=floor($TabColors['red']*$filter_r/255); 
      $color_g=floor($TabColors['green']*$filter_g/255); 
      $color_b=floor($TabColors['blue']*$filter_b/255); 
      $newcol = imagecolorallocate($image, $color_r,$color_g,$color_b); 
      imagesetpixel($image, $x, $y, $newcol); 
     } 
    } 

    imagepng($image,$new_path); 
} 
?> 
+0

Tuyệt vời, cảm ơn bạn rất nhiều! Điều đó dường như cung cấp chính xác funcionality như bộ lọc nhân của Photoshop. – heintore

+0

Tôi đã sử dụng điều này trong một ví dụ khác, nhưng tôi thấy việc triển khai này thực sự chậm. Cách nhanh hơn là sử dụng bộ lọc hình ảnh với IMG_FILTER_COLORIZE. Đầu tiên, đảo ngược giá trị màu RGB dự định, sau đó đảo ngược hình ảnh bằng bộ lọc hình ảnh ($ image, IMG_FILTER_NEGATE), sau đó áp dụng màu đảo ngược cho hình ảnh ngược, sau đó đảo ngược lại hình ảnh. Xem tại đây http://stackoverflow.com/questions/26005991/php-gd-multiply-image-colors-with-tint-color/26250684#26250684 –

+0

Hoạt động tuyệt vời! Tôi cập nhật nó một chút để nhân hai hình ảnh, không chỉ là một hình ảnh với một màu sắc: http://codepad.org/BSawY5ex –

0

Bạn đã cố gắng sử dụng php manual?

Đối với những người tìm cách để áp dụng hiệu ứng 'nhân' trên hình ảnh như một trong Photoshop (thường b & w những người thân), bạn có thể đạt được điều đó với bộ lọc IMG_FILTER_COLORIZE.

<?php 
function multiplyColor(&$im, $color = array(255, 0, 0)) { 
    //get opposite color 
    $opposite = array(255 - $color[0], 255 - $color[1], 255 - $color[2]); 

    //now we subtract the opposite color from the image 
    imagefilter($im, IMG_FILTER_COLORIZE, -$opposite[0], -$opposite[1], -$opposite[2]); 
} 
?> 
+0

Tôi đã cố gắng triển khai hàm đó, nhưng m y thử nghiệm cho thấy rằng nó đã không tạo ra kết quả tương tự như bộ lọc nhân của Photoshop. Nó sẽ có vẻ tự nhiên để cung cấp một màu nền để nhân chống lại, và không chỉ trừ đi màu sắc đối diện. – heintore

+0

Khái niệm đằng sau là hữu ích trong việc sản xuất chính xác những gì photoshop làm. Tôi đã thử nghiệm nó và những hình ảnh giống hệt nhau. –

5

Tôi đã tìm kiếm Multiply sự pha trộn giữa hai hình ảnh cũng và không thể tìm thấy bất kỳ nguồn gốc giải pháp php cho nó. Có vẻ như cách duy nhất (hiện tại) là "đặt theo cách thủ công" pixel, pixel-by-pixel. Đây là mã của tôi mà Multiply pha trộn giữa hai hình ảnh, giả sử rằng hình ảnh có cùng kích thước. Bạn có thể điều chỉnh nó để xử lý các kích cỡ khác nhau nếu bạn muốn.

function multiplyImage($dst,$src) 
{ 
    $ow = imagesx($dst); 
    $oh = imagesy($dst); 

    $inv255 = 1.0/255.0; 

    $c = imagecreatetruecolor($ow,$oh); 
    for ($x = 0; $x <$ow; ++$x) 
    { 
     for ($y = 0; $y <$oh; ++$y) 
     { 
      $rgb_src = imagecolorsforindex($src,imagecolorat($src, $x, $y)); 
      $rgb_dst = imagecolorsforindex($dst,imagecolorat($dst, $x, $y)); 
      $r = $rgb_src['red'] * $rgb_dst['red']*$inv255; 
      $g = $rgb_src['green'] * $rgb_dst['green']*$inv255; 
      $b = $rgb_src['blue'] * $rgb_dst['blue']*$inv255; 
      $rgb = imagecolorallocate($c,$r,$g,$b); 
      imagesetpixel($c, $x, $y, $rgb); 
     } 
    } 
    return $c; 
} 

Chức năng trả về đối tượng hình ảnh, do đó bạn phải đảm bảo chụp ảnh sau khi sử dụng xong.

Nên có giải pháp thay thế bằng cách sử dụng hỗn hợp lớp phủ native-php, cho thấy 50% pixel màu xám của hình ảnh đích sẽ bị ảnh hưởng bởi pixel nguồn. Về lý thuyết, nếu bạn cần trộn hai ảnh đen trắng (không có tông màu xám), nếu bạn thiết lập độ tương phản của ảnh đích sao cho màu trắng sẽ trở thành 50% -gray, và sau đó chồng lên nhau nguồn ảnh trên nó, nên cho bạn một cái gì đó tương tự như nhân. Nhưng đối với hình ảnh màu hoặc hình ảnh thang độ xám, điều này sẽ không hoạt động - phương pháp trên dường như là tùy chọn duy nhất.

2

Tôi đã được đưa vào chủ đề này khi tôi cần kết hợp hai hình ảnh trong GD. Có vẻ như không có mã cụ thể cho điều đó vì vậy tôi sẽ chỉ để lại điều này ở đây cho khách truy cập trong tương lai vào trang này.

Đây là một ngã ba từ câu trả lời của colivier hỗ trợ nhân hỗn hợp của hai hình ảnh.

Hai hình ảnh không cần phải có cùng kích thước NHƯNG hình ảnh lớp phủ sẽ được thay đổi kích thước và cắt thành kích thước của lớp dưới cùng. Tôi đã thực hiện một hàm trợ giúp fit để làm điều đó nhưng đừng bận tâm với điều đó.

imagecolorat trả lại màu cơ bản, ngay cả với PNG có độ trong suốt. Tức là, 50% màu đen (hiển thị là (128, 128, 128)) sẽ được trả về là (0, 0, 0, 64) 64 là giá trị alpha. Mã này xem xét tính mờ và chuyển đổi màu mờ sang các giá trị màu có thể nhìn thấy.

// bottom layer 
$img1 = imagecreatefromjpeg(realpath(__DIR__.'/profilePic.jpg')); 

// top layer 
$img2 = imagecreatefrompng(realpath(__DIR__.'/border2.png')); 
imagealphablending($img2, false); 
imagesavealpha($img2, true); 

$imagex = imagesx($img1); 
$imagey = imagesy($img1); 

$imagex2 = imagesx($img2); 
$imagey2 = imagesy($img2); 

// Prereq: Resize img2 to match img1, cropping beyond the aspect ratio 
$w1 = max(min($imagex2, $imagex), $imagex); 
$h1 = max(min($imagey2, $imagey), $imagey); 

$w_using_h1 = round($h1 * $imagex2/$imagey2); 
$h_using_w1 = round($w1 * $imagey2/$imagex2); 

if ($w_using_h1 > $imagex) { 
    fit($img2, $imagex, $imagey, 'HEIGHT', true); 
} 
fit($img2, $imagex, $imagey, 'WIDTH', true); 

// Actual multiply filter 
for ($x = 0; $x < $imagex; ++$x) { 
    for ($y = 0; $y < $imagey; ++$y) { 
     $rgb1 = imagecolorat($img1, $x, $y); 
     $rgb2 = imagecolorat($img2, $x, $y); 
     $idx1 = imagecolorsforindex($img1, $rgb1); 
     $idx2 = imagecolorsforindex($img2, $rgb2); 

     // Shift left 8, then shift right 7 
     // same as multiply by 256 then divide by 128 
     // approximate multiply by 255 then divide by 127 
     // This is basically multiply by 2 but, expanded to show that 
     // we are adding a fraction of white to the translucent image 
     // $adder = ($idx2['alpha'] <<8>> 7); 
     $adder = ($idx2['alpha'] << 1); 
     $rmul = min(255, $idx2['red'] + $adder); 
     $gmul = min(255, $idx2['green'] + $adder); 
     $bmul = min(255, $idx2['blue'] + $adder); 

     $color_r = floor($idx1['red'] * $rmul/255); 
     $color_g = floor($idx1['green'] * $gmul/255); 
     $color_b = floor($idx1['blue'] * $bmul/255); 

     $newcol = imagecolorallocatealpha($img1, $color_r, $color_g, $color_b, 0); 
     imagesetpixel($img1, $x, $y, $newcol); 
    } 
} 
imagejpeg($img1, __DIR__.'/out.jpg'); 



/** 
* Fits an image to a $w x $h canvas 
* 
* @param type $w Target width 
* @param type $h Target height 
* @param int $fit_which Which dimension to fit 
* @param bool $upscale If set to true, will scale a smaller image to fit the given dimensions 
* @param bool $padded If set to true, will add padding to achieve given dimensions 
* 
* @return Image object 
*/ 
function fit(&$img, $w, $h, $fit_which = 'BOTH', $upscale = false, $padded = true) { 

    if (!in_array($fit_which, array('WIDTH', 'HEIGHT', 'BOTH'))) { 
     $fit_which = 'BOTH'; 
    } 
    $w0 = imagesx($img); 
    $h0 = imagesy($img); 

    if (!$upscale && $w0 <= $w && $h0 <= $h) 
     return $this; 

    if ($padded) { 
     $w1 = max(min($w0, $w), $w); 
     $h1 = max(min($h0, $h), $h); 
    } 
    else { 
     $w1 = min($w0, $w); 
     $h1 = min($h0, $h); 
    } 
    $w_using_h1 = round($h1 * $w0/$h0); 
    $h_using_w1 = round($w1 * $h0/$w0); 

    // Assume width, crop height 
    if ($fit_which == 'WIDTH') { 
     $w2 = $w1; 
     $h2 = $h_using_w1; 
    } 
    // Assume height, crop width 
    elseif ($fit_which == 'HEIGHT') { 
     $w2 = $w_using_h1; 
     $h2 = $h1; 
    } 
    elseif ($fit_which == 'BOTH') { 
     if (!$padded) { 
      $w2 = $w = min($w, $w_using_h1); 
      $h2 = $h = min($h, $h_using_w1); 
     } 
     else { 
      // Extend vertically 
      if ($h_using_w1 <= $h) { 
       $w2 = $w1; 
       $h2 = $h_using_w1; 
      } 
      // Extend horizontally 
      else { 
       $w2 = $w_using_h1; 
       $h2 = $h1; 
      } 
     } 
    } 

    $im2 = imagecreatetruecolor($w, $h); 
    imagealphablending($im2, true); 
    imagesavealpha($im2, true); 

    $transparent = imagecolorallocatealpha($im2, 255, 255, 255, 127); 
    imagefill($im2, 0, 0, $transparent); 

    imagealphablending($img, true); 
    imagesavealpha($img, true); 
    // imagefill($im, 0, 0, $transparent); 

    imagecopyresampled($im2, $img, ($w - $w2)/2, ($h - $h2)/2, 0, 0, $w2, $h2, $w0, $h0); 

    $img = $im2;  
} 
0

Nếu sử dụng với hình ảnh png và alpha phải được khỏe mạnh và hoạt động rất tốt

$filter_r=215; 
 
    $filter_g=5; 
 
    $filter_b=5; 
 
    $alpha=70; 
 
    $suffixe="_red"; 
 
    $path="./img/foto_220_590.png"; 
 
    if(is_file($path)){ 
 
     $image=imagecreatefrompng($path); 
 
     $new_path=substr($path,0,strlen($path)-4).$suffixe.".png"; 
 

 
     echo $imagex = imagesx($image); 
 
     echo $imagey = imagesy($image); 
 
     for ($x = 0; $x <$imagex; ++$x) { 
 
      for ($y = 0; $y <$imagey; ++$y) { 
 
       $rgb = imagecolorat($image, $x, $y); 
 
       $TabColors=imagecolorsforindex ($image , $rgb); 
 
       $color_r=floor($TabColors['red']*$filter_r/255); 
 
       $color_g=floor($TabColors['green']*$filter_g/255); 
 
       $color_b=floor($TabColors['blue']*$filter_b/255); 
 
       //$newcol = imagecolorallocate($image, $color_r,$color_g,$color_b); 
 
       // this new alpha 
 
       $newcol = imagecolorallocatealpha($image, $color_r,$color_g,$color_b,$alpha); 
 
       imagesetpixel($image, $x, $y, $newcol); 
 
      } 
 
     } 
 
     imagepng($image,$new_path);

0

tôi cập nhật kịch bản @colivier để có thể myltiply hai hình ảnh, và không chỉ hình ảnh có màu:

/** 
* Multiply $pathToDst and $pathToSrc to $resultPath 
* 
* @param string $pathToDst 
* @param string $pathToSrc 
* @param string $resultPath 
*/ 
function multiply($pathToDst, $pathToSrc, $resultPath) { 
    switch (pathinfo($pathToDst, PATHINFO_EXTENSION)) { 
     case "gif" : 
      $resourceDst = imagecreatefromgif($pathToDst); 
      break; 
     case "png" : 
      $resourceDst = imagecreatefrompng($pathToDst); 
      break; 
     default : 
      $resourceDst = imagecreatefromjpeg($pathToDst); 
      break; 
    } 

    switch (pathinfo($pathToSrc, PATHINFO_EXTENSION)) { 
     case "gif" : 
      $resourceSrc = imagecreatefromgif($pathToSrc); 
      break; 
     case "png" : 
      $resourceSrc = imagecreatefrompng($pathToSrc); 
      break; 
     default : 
      $resourceSrc = imagecreatefromjpeg($pathToSrc); 
      break; 
    } 

    for ($x = 0; $x < 400; ++$x) { 
     for ($y = 0; $y < 400; ++$y) { 
      $TabColorsFlag = imagecolorsforindex($resourceDst, imagecolorat($resourceDst, $x, $y)); 
      $TabColorsPerso = imagecolorsforindex($resourceSrc, imagecolorat($resourceSrc, $x, $y)); 

      $color_r = floor($TabColorsFlag['red'] * $TabColorsPerso['red']/255); 
      $color_g = floor($TabColorsFlag['green'] * $TabColorsPerso['green']/255); 
      $color_b = floor($TabColorsFlag['blue'] * $TabColorsPerso['blue']/255); 
      imagesetpixel($resourceDst, $x, $y, imagecolorallocate($resourceSrc, $color_r, $color_g, $color_b)); 
     } 
    } 

    imagepng($resourceDst, $resultPath, 0); 
    imagedestroy($resourceDst); 
    imagedestroy($resourceSrc); 
}