PHP使用GD庫合併簡單圖片並變動部分顏色
最近看到很多大公司都開始做寵物鍊形式多樣化,最特別的是寵物分有多種部位然後再不同組合並生成出對應的寵物圖片,看起來比較高大尚,不過發現有些是使用SVG向量圖片,這類圖片理論上無失真可以隨意放大效能略受影響,編輯方便容易調整,但操作麻煩,如果直接使用圖片那麼操作會容易些。
php的GD庫提供了很多基礎圖片操作功能,可以分為兩大類:
真彩圖操作:支援直接透明圖片處理,但不支援顏色變換,允許畫入新內容。
調色盤圖操作:支援指定顏色為透明,並且支援顏色變換,允許畫入新內容。
兩種型別的圖片可以相互轉換,如果原圖片有透明塊儘可能避免直接轉為調色盤圖(透明塊容易出現未知異常)但可以合併到調色盤圖中從而保留了原圖的透明,如果在調色盤圖中指定了某個色值為透明則在生成圖片後這個色值為透明的。
如果只使用GD庫在不需要變換圖片顏色的時候基本上不需要使用調色盤,相反需要有變換圖片顏色時則只能使用調色盤。
這裡以生成小怪物為目標來操作變換小怪物的顏色:
首先需要準備5個基本圖片元素:
圖片要求:
1.所有圖片最好全新畫的(最好使用向量圖生成的),所有需要變色的原顏色與其它顏色連線處不能有過渡,否則替換顏色後原連線過渡顏色將被保留,影響美觀。
2.eyes.png 除了眼睛體外全部透明化處理。
3.fleck.png 除了斑紋休外全部透明化處理。
4.mouth.png 除了嘴巴體外全部透明化處理。
5.shadow.png 體型內無顏色透明化處理,體型外全部使用白色。
6.shape.png 不要有透明內容。
7.所有需要替換顏色的色值在其它所所部位最好都不要出現。
下面給一個生成不同顏色寵物的示例程式碼:
$image = imagecreatefrompng('shape.png'); //取體型圖片
list($src_w, $src_h) = getimagesize('shape.png'); //獲取寬高度
imagetruecolortopalette($image, false, 256); //轉換為調色盤影象,只有調色盤才能換顏色
$color_index = imagecolorat($image, 276, 621); //獲取顏色索引值(體型顏色)
imagecolorset($image, $color_index, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); //修改顏色
$color_index = imagecolorat($image, 450, 780); //獲取顏色索引值(肚皮顏色)
imagecolorset($image, $color_index, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); //修改顏色
// 這段處理非常重要,如果直接轉換為真彩圖會造成後續有透明圖片合併異常
// 如果直接使用 **imagepalettetotruecolor** 函式也會有異常,可能是調色盤資料未清除造成的
// 如同把圖片寫到檔案再讀取一樣,得到真彩圖
$_image = imagecreatetruecolor($src_w, $src_h); //建立真彩圖
$color = imagecolorallocate($_image, 255, 255, 255); //分配顏色
imagefill($_image, 0, 0, $color); //填充
imagecopyresampled($_image, $image, 0, 0, 0, 0, $src_w, $src_h, $src_w, $src_h); //合併修改後的圖片
$image = $_image;
/* 斑紋處理 */
$image_fleck = imagecreatefrompng('fleck.png'); //取斑紋圖片
imagecopyresampled($image, $image_fleck, 0, 0, 0, 0, $src_w, $src_h, $src_w, $src_h); //合併
imagetruecolortopalette($image, false, 256); //轉換為調色盤影象,只有調色盤才能換顏色
$color_index = imagecolorat($image, 385, 925); //獲取顏色索引值(斑紋顏色)
imagecolorset($image, $color_index, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); //修改顏色
// 如同把圖片寫到檔案再讀取一樣,得到真彩圖,與上面一樣,如果不這樣處理後續的透明圖合併將會有異常
$_image = imagecreatetruecolor($src_w, $src_h); //建立真彩圖
$color = imagecolorallocate($_image, 255, 255, 255); //分配顏色
imagefill($_image, 0, 0, $color); //填充
imagecopyresampled($_image, $image, 0, 0, 0, 0, $src_w, $src_h, $src_w, $src_h); //合併修改後的圖片
$image = $_image;
/* 體型陰影處理 */
imagecopyresampled($image, imagecreatefrompng('test1/shadow.png'), 0, 0, 0, 0, $src_w, $src_h, $src_w, $src_h);
/* 嘴巴處理 */
imagecopyresampled($image, imagecreatefrompng('test1/mouth.png'), 0, 0, 0, 0, $src_w, $src_h, $src_w, $src_h);
/* 眼睛處理 */
$image_eyes = imagecreatefrompng('eyes.png'); //取斑紋圖片
imagetruecolortopalette($image, false, 256); //轉換為調色盤影象,只有調色盤才能換顏色
imagecopyresampled($image, $image_eyes, 0, 0, 0, 0, $src_w, $src_h, $src_w, $src_h); //合併
$color_index = imagecolorat($image_eyes, 285, 335); //獲取顏色索引值(眼睛顏色)
imagecolorset($image, $color_index, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); //修改顏色
// 如同把圖片寫到檔案再讀取一樣,得到真彩圖,與上面一樣,如果不這樣處理後續的透明圖合併將會有異常
$_image = imagecreatetruecolor($src_w, $src_h); //建立真彩圖
$color = imagecolorallocate($_image, 255, 255, 255); //分配顏色
imagefill($_image, 0, 0, $color); //填充
imagecopyresampled($_image, $image, 0, 0, 0, 0, $src_w, $src_h, $src_w, $src_h); //合併修改後的圖片
$image = $_image;
//新增背景
$color_index = imagecolorat($image, 435, 300); //獲取顏色索引值(背景顏色)
imagefilltoborder($image, 0, 0, $color_index, imagecolorallocate($image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)));
imagesavealpha($image, true); //儲存 alpha 通道資訊,如果圖片中有透明內容則需要
header('Content-type:image/png');
imagepng($image, null, 9);
imagedestroy($image);
注意: 替換圖片顏色時需要取出調色盤顏色的索引值函式 imagecolorat 就是取顏色的索引值(想獲取哪個顏色給出顏色的任意座標值即可),由於我測試時圖片1304 X 1412 所以程式碼中座標值都比較大,還有顏色替換會有鋸齒這是因為畫素點為矩形造成的當圖片有一定大小時不會影響太多美觀。
執行結果如下:
Linux公社的RSS地址 : ofollow,noindex" target="_blank">https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址: https://www.linuxidc.com/Linux/2018-09/154487.htm