2013-07-18 101 views
11

的基色我尋覓了很多,我只發現了幾個解決方案(谷歌和計算器,所以請不要標記這個一個是重複的,除非真的有重複的問題),但問題是很難邊緣。是否有任何適當的方式來改變基礎顏色,讓我們說黑色形狀PNG圖像具有透明背景,但保留軟邊緣?腓 - 更換透明的PNG圖像

這是一個例子形象:

enter image description here

我希望它看起來像這樣:

enter image description here

但我發現的解決方案給我這一個:

enter image description here

因爲我將在我的本地主機上使用這個,只爲個人使用,任何可以幫助實現這一目標的PHP庫,我都讚賞。

UPDATE:

這是給我的第3圖像功能:

function LoadPNG($imgname) 
{ 
    $im = imagecreatefrompng ($imgname); 
    imagetruecolortopalette($im,false, 255); 
    $index = imagecolorclosest ($im, 0,0,0); // GET BLACK COLOR 
    imagecolorset($im,$index,0,150,255); // SET COLOR TO BLUE 
    $name = basename($imgname); 
    imagepng($im, getcwd()."/tmp/$name"); // save image as png 
    imagedestroy($im); 
} 
$dir = getcwd()."/img/"; 
$images = glob($dir."/*.png",GLOB_BRACE); 
foreach($images as $image) { 
    LoadPNG($image); 
} 

最初,這個功能是爲GIF圖像(255個色調色板)的解決方案,所以我想這就是爲什麼有硬邊緣。我正在尋找解決方案(對此腳本的改進)來保留PNG圖像的透明度和柔和邊緣。

編輯2:

我發現使用HTML5畫布和JavaScript這裏一個有趣的方法: http://users7.jabry.com/overlord/mug.html

也許有人可以有一個想法,如果甚至有可能如何轉化爲PHP這一點。

新的解決方案

在回答

+0

您可以張貼,導致第3圖像解決一些代碼? – Maximus2012

+0

@ Maximus2012是的,請給我一點時間,我必須找到它,因爲在此期間,我嘗試了許多其他人,但沒有成功。 –

+1

@ Maximus2012更新了我的問題。 –

回答

14

此代碼不會舉例說明問題,但顏色變換是這樣的:

enter image description here

採用ALPHA信道的圖像的,以確定着色。對於其他的效果,只是玩弄imagecolorallocatealpha()

function colorizeBasedOnAplhaChannnel($file, $targetR, $targetG, $targetB, $targetName) { 

    $im_src = imagecreatefrompng($file); 

    $width = imagesx($im_src); 
    $height = imagesy($im_src); 

    $im_dst = imagecreatefrompng($file); 

    // Note this: 
    // Let's reduce the number of colors in the image to ONE 
    imagefilledrectangle($im_dst, 0, 0, $width, $height, 0xFFFFFF); 

    for($x=0; $x<$width; $x++) { 
     for($y=0; $y<$height; $y++) { 

      $alpha = (imagecolorat($im_src, $x, $y) >> 24 & 0xFF); 

      $col = imagecolorallocatealpha($im_dst, 
       $targetR - (int) (1.0/255.0 * $alpha * (double) $targetR), 
       $targetG - (int) (1.0/255.0 * $alpha * (double) $targetG), 
       $targetB - (int) (1.0/255.0 * $alpha * (double) $targetB), 
       $alpha 
       ); 

      if (false === $col) { 
       die('sorry, out of colors...'); 
      } 

      imagesetpixel($im_dst, $x, $y, $col); 

     } 

    } 

    imagepng($im_dst, $targetName); 
    imagedestroy($im_dst); 

} 

unlink(dirname (__FILE__) . '/newleaf.png'); 
unlink(dirname (__FILE__) . '/newleaf1.png'); 
unlink(dirname (__FILE__) . '/newleaf2.png'); 

$img = dirname (__FILE__) . '/leaf.png'; 
colorizeBasedOnAplhaChannnel($img, 0, 0, 0xFF, 'newleaf1.png'); 
colorizeBasedOnAplhaChannnel($img, 0xFF, 0, 0xFF, 'newleaf2.png'); 
?> 

Original 
<img src="leaf.png"> 
<br /> 
<img src="newleaf1.png"> 
<br /> 
<img src="newleaf2.png"> 
+1

如果我是正確的(小圖像,所以我看不到完美),有更深的邊緣,但這是迄今爲止最好的基於PHP的解決方案。謝謝你的努力,我會接受這個答案。 –

0

第三圖像看起來不正常,因爲imagetruecolortopalette($im,true, 255);呈現一個醜陋的形象:由於第二圖像不

enter image description here

看起來不錯,第三個看起來也不漂亮。

代碼:

<?php 
unlink(dirname (__FILE__) . '/newleaf.png'); 
unlink(dirname (__FILE__) . '/newleaf1.png'); 

function LoadPNG($imgname) 
{ 
    $im = imagecreatefrompng ($imgname); 
    imagetruecolortopalette($im,true, 255); 

    imagepng($im, 'newleaf1.png'); // save image as png 

    $index = imagecolorclosest ($im, 0,0,0); // GET BLACK COLOR 
    imagecolorset($im,$index,0,150,255); // SET COLOR TO BLUE 
    $name = basename($imgname); 
    imagepng($im, 'newleaf.png'); // save image as png 
    imagedestroy($im); 
} 

$img = dirname (__FILE__) . '/leaf.png'; 
LoadPNG($img); 

?> 

Original 
<img src="leaf.png"> 
<br />After make truecolortopalette($im,true, 255); 
<img src="newleaf1.png"> 
<br />Thus.. 
<img src="newleaf.png"> 
+0

就像我一樣。你有更好的渲染解決方案嗎? –

+0

@NikolaR。不幸的是,我目前無法提供解決方案。太晚了......可能是明天。有趣的案例... – SteAp

+1

謝謝,我感謝! –

1

正如我已經告訴了,我花了很多時間尋找什麼,我發現迄今是使用HTML5畫布,JavaScript和Ajax。

只有我使用的庫是JavaScript庫jQuery的,但它是可選的。代碼可以很容易地重寫爲使用普通的JavaScript。

工作原理:

1)從JS其中ajax.php返回所有文件

2的陣列中提取數據)的js然後循環直通文件列表,並對每個項目

執行 change(src,color)

3)js函數從源中加載圖像,替換它的顏色並將一個img元素添加到#Cell並顯示它(用於調試)。

4)change()還要求save(src,filename,cname)功能 5)js函數save(src,filename,cname)發送AJAX請求與圖像數據和ajax.php保存圖像服務器。

所以這裏的代碼:

ajax.php

<?php 
$r = $_REQUEST; 
$act = $r['action']; 
if($act == "get_all") { 
    $js = ""; 
    $dir = getcwd()."/img/"; 
    $images = glob($dir."/*.png",GLOB_BRACE); 
    foreach($images as $image) { 
     $name = basename($image); 
     $js[] = $name; 
    } 
    echo json_encode($js); 
    die(); 
} 
elseif($act == "save") { 
    $img = $r['file']; 
    $name = $r['name']; 
    $color = $r['color']; 
    $dir = "results/$color"; 
    if(!file_exists($dir) || !is_dir($dir)) mkdir($dir,777,true); 
    $file = $dir."/$name"; 
    file_put_contents($file,file_get_contents("data://".$img)); 
    if(file_exists($file)) echo "Success"; 
    else echo $file; 
    die(); 
} 

的index.php(HTML只)

<!doctype html> 
     <html> 
<head> 
    <script src="jquery.js" type="text/javascript"></script> 
    <script src="demo.js" type="text/javascript"></script> 
</head> 
<body> 
<div id="ctrl"> 
    <input type="text" id="color" value="#666666" placeholder="Color in HEX format (ex. #ff0000)" /> 
    <input type="text" id="cname" value="grey" placeholder="Color name (destionation dir name)" /> 
    <button type="button" id="doit">Change</button> 
</div> 
<div id="Cell"> 

</div> 
</body> 

</html> 

demo.js

$(document).ready(function() { 
    $(document).on("click","#doit",function() { 
     var c = $("#color"); 
     if(c.val() != "") { 
      $("#Cell").html(""); 
      $.post("ajax.php",{ action: "get_all" },function(s) { 
       var images = $.parseJSON(s); 
       $.each(images, function(index, element) { 
        change(images[index], c.val()); 
       }); 
      }); 
     } 
    }); 
}); 
function change(src,color) { 
    var myImg = new Image(); 
    myImg.src = "img/"+src; 
    myImg.onload = function() { 
     var canvas = document.createElement("canvas"); 
     var ctx = canvas.getContext("2d"); 
     ctx.drawImage(myImg,0,0); 
     var imgd = ctx.getImageData(0, 0, myImg.width, myImg.height); 
     canvas.height = myImg.height; 
     canvas.width = myImg.width; 
     var new_color = HexToRGB(color); 
     // console.log(imgd) 
     for (i = 0; i <imgd.data.length; i += 4) { 
      imgd.data[i] = new_color.R; 
      imgd.data[i+1] = new_color.G; 
      imgd.data[i+2] = new_color.B; 
     } 
     ctx.putImageData(imgd, 0, 0); 
     var newImage=new Image() 
     newImage.src=canvas.toDataURL("image/png"); 
     $(newImage).css("margin","5px"); 
     $(newImage).attr('data-title',src); 
     $("#Cell").append(newImage); 
     var c = $("#cname"); 
     if(c.val() == "") c.val("temp"); 
     save(newImage.src,src, c.val()); 
    }; 
} 
function save(src,filename,cname) { 
    $.post("ajax.php", { action: "save", file: src, name: filename, color: cname },function(s) { 
     console.log(s); 
    }) 
} 
function HexToRGB(Hex) 
{ 
    var Long = parseInt(Hex.replace(/^#/, ""), 16); 
    return { 
     R: (Long >>> 16) & 0xff, 
     G: (Long >>> 8) & 0xff, 
     B: Long & 0xff 
    }; 
} 

我已經測試過它,爲了重新着色和保存420個24x24圖片,它花了不到10秒(在localhost上)(420個異步ajax調用)。一旦原始圖像被緩存,它會更快地完成。圖像質量與原始圖像保持一致。

同樣,這個解決方案是我個人使用的,所以代碼非常不受管理,我相信它可以得到改進,但是在這裏你可以繼續 - 因爲它是有效的。

2

擴展的answer from SteAp,我有需要還可以調整基礎上的RGBA目標色每個像素的透明度。

我還修復了有黑邊的問題 - 這是每個像素的顏色由原始阿爾法等級調整的結果,而不是僅僅調整它自己的阿爾法。

// R,G,B = 0-255 range 
// A = 0.0 to 1.0 range 
function colorizeBasedOnAplhaChannnel($file, $targetR, $targetG, $targetB, $targetA, $targetName) { 
    $im_src = imagecreatefrompng($file); 

    $width = imagesx($im_src); 
    $height = imagesy($im_src); 

    $im_dst = imagecreatefrompng($file); 

    // Turn off alpha blending and set alpha flag 
    imagealphablending($im_dst, false); 
    imagesavealpha($im_dst, true); 

    // Fill transparent first (otherwise would result in black background) 
    imagefill($im_dst, 0, 0, imagecolorallocatealpha($im_dst, 0, 0, 0, 127)); 

    for ($x=0; $x<$width; $x++) { 
     for ($y=0; $y<$height; $y++) { 
      $alpha = (imagecolorat($im_src, $x, $y) >> 24 & 0xFF); 

      $col = imagecolorallocatealpha($im_dst, 
       $targetR - (int) (1.0/255.0 * (double) $targetR), 
       $targetG - (int) (1.0/255.0 * (double) $targetG), 
       $targetB - (int) (1.0/255.0 * (double) $targetB), 
       (($alpha - 127) * $targetA) + 127 
      ); 

      if (false === $col) { 
       die('sorry, out of colors...'); 
      } 

      imagesetpixel($im_dst, $x, $y, $col); 
     } 
    } 

    imagepng($im_dst, $targetName); 
    imagedestroy($im_dst); 
} 
2

使用SteAp的接受代碼作爲起點(因爲它我沒有管理爲達到透明性,只是一個白色背景),我適應所述代碼,其結果是這樣的:

<?php 

function colorizeKeepAplhaChannnel($inputFilePathIn, $targetRedIn, $targetGreenIn, $targetBlueIn, $outputFilePathIn) { 
    $im_src = imagecreatefrompng($inputFilePathIn); 
    $im_dst = imagecreatefrompng($inputFilePathIn); 
    $width = imagesx($im_src); 
    $height = imagesy($im_src); 

    // Note this: FILL IMAGE WITH TRANSPARENT BG 
    imagefill($im_dst, 0, 0, IMG_COLOR_TRANSPARENT); 
    imagesavealpha($im_dst,true); 
    imagealphablending($im_dst, true); 

    $flagOK = 1; 
    for($x=0; $x<$width; $x++) { 
     for($y=0; $y<$height; $y++) { 
      $rgb = imagecolorat($im_src, $x, $y); 
      $colorOldRGB = imagecolorsforindex($im_src, $rgb); 
      $alpha = $colorOldRGB["alpha"]; 
      $colorNew = imagecolorallocatealpha($im_src, $targetRedIn, $targetGreenIn, $targetBlueIn, $alpha); 

      $flagFoundColor = true; 
      // uncomment next 3 lines to substitute only 1 color (in this case, BLACK/greys) 
/* 
      $colorOld = imagecolorallocatealpha($im_src, $colorOldRGB["red"], $colorOldRGB["green"], $colorOldRGB["blue"], 0); // original color WITHOUT alpha channel 
      $color2Change = imagecolorallocatealpha($im_src, 0, 0, 0, 0); // opaque BLACK - change to desired color 
      $flagFoundColor = ($color2Change == $colorOld); 
*/ 

      if (false === $colorNew) { 
       //echo("FALSE COLOR:$colorNew alpha:$alpha<br/>"); 
       $flagOK = 0; 
      } else if ($flagFoundColor) { 
       imagesetpixel($im_dst, $x, $y, $colorNew); 
       //echo "x:$x y:$y col=$colorNew alpha:$alpha<br/>"; 
      } 
     } 
    } 
    $flagOK2 = imagepng($im_dst, $outputFilePathIn); 

    if ($flagOK && $flagOK2) { 
     echo ("<strong>Congratulations, your conversion was successful </strong><br/>new file $outputFilePathIn<br/>"); 
    } else if ($flagOK2 && !$flagOK) { 
     echo ("<strong>ERROR, your conversion was UNsuccessful</strong><br/>Please verify if your PNG is truecolor<br/>input file $inputFilePathIn<br/>"); 
    } else if (!$flagOK2 && $flagOK) { 
     $dirNameOutput = dirname($outputFilePathIn)."/"; 
     echo ("<strong>ERROR, your conversion was successful, but could not save file</strong><br/>Please verify that you have PERMISSION to save to directory $dirName <br/>input file $inputFilePathIn<br/>"); 
    } else { 
     $dirNameOutput = dirname($outputFilePathIn)."/"; 
     echo ("<strong>ERROR, your conversion was UNsuccessful AND could not save file</strong><br/>Please verify if your PNG is truecolor<br/>Please verify that you have PERMISSION to save to directory $dirName <br/>input file $inputFilePathIn<br/>"); 
    } 

    echo ("TargetName:$outputFilePathIn wid:$width height:$height CONVERTED:|$flagOK| SAVED:|$flagOK2|<br/>"); 
    imagedestroy($im_dst); 
    imagedestroy($im_src); 
} 




$targetRed = 0; 
$targetGreen = 180; 
$targetBlue = 0; 

//$inputFileName = 'frameSquareBlack_88x110.png'; 
$inputFileName = 'testMe.png'; 
$dirName = "../img/profilePics/"; 
$nameTemp = basename($inputFileName, ".png"); 
$outputFileName = $nameTemp."_$targetRed"."_$targetGreen"."_$targetBlue.png"; 
$inputFilePath = $dirName.$inputFileName; 
$outputFilePath = $dirName.$outputFileName; 

//echo "inputFileName:$inputFilePath<br>outputName:$outputFilePath<br>"; 
colorizeKeepAplhaChannnel($inputFilePath, $targetRed, $targetGreen, $targetBlue, $outputFilePath); 
?> 
<br/><br/> 
Original <br/> 
<img src="<?php echo $inputFilePath; ?>"> 
<br /><br />Colorized<br/> 
<img src="<?php echo $outputFilePath; ?>"> 
<br /> 

enter image description here

這種變化改變了這一切的顏色來選擇顏色(不只是黑色的,一個簡單的如果能解決這個問題 - 取消註釋3所示在功能上線,你會做到這一點)

enter image description here

爲了便於說明,在這種情況下,下面的圖片中使用(因爲leaf.png是單色的,具有透明度): enter image description here