php使用GD庫合併簡單圖片並變動部分顏色

最近看到很多大公司都開始做寵物鍊形式多樣化,最特別的是寵物分有多種部位然後再不同組合並生成出對應的寵物圖片,看起來比較高大尚,不過發現有些是使用SVG矢量圖片,這類圖片理論上無失真可以隨意放大性能略受影響,編輯方便容易調整,但操作麻煩,如果直接使用圖片那麼操作會容易些。

php的GD庫提供了很多基礎圖片操作功能,可以分爲兩大類:

真彩圖操作:支持直接透明圖片處理,但不支持顏色變換,允許畫入新內容。
調色板圖操作:支持指定顏色爲透明,並且支持顏色變換,允許畫入新內容。

兩種類型的圖片可以相互轉換,如果原圖片有透明塊儘可能避免直接轉爲調色板圖(透明塊容易出現未知異常)但可以合併到調色板圖中從而保留了原圖的透明,如果在調色板圖中指定了某個色值爲透明則在生成圖片後這個色值爲透明的。

如果只使用GD庫在不需要變換圖片顏色的時候基本上不需要使用調色板,相反需要有變換圖片顏色時則只能使用調色板。

這裏以生成小怪物爲目標來操作變換小怪物的顏色:

首先需要準備5個基本圖片元素:

php使用GD庫合併簡單圖片並變動部分顏色

圖片要求:

  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 所以代碼中座標值都比較大,還有顏色替換會有鋸齒這是因爲像素點爲矩形造成的當圖片有一定大小時不會影響太多美觀。

執行結果如下:

php使用GD庫合併簡單圖片並變動部分顏色

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章