本篇文章更新時間:2019/02/16
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~
如果本站內容對你有幫助,歡迎使用 BFX Pay 加密貨幣 或 新台幣 贊助支持。
寫過程式處理影像的人,在 Photoshop 上操作過後應該會很讚嘆,那是一個敬佩!至少做影像處理研究過的我是這樣XD
今天來嘗試解決一個 issue 就是用 PHP 寫影像合成,整個需求的演算法還算簡單,就把一張目標圖合成在底圖左側透明區塊而已。
流程:
- 先將目標圖縮放配合底圖
- 建立空白圖層,並將縮放後目標圖先行填入左側
- 再將底圖蓋上
首先會遇到縮圖的部分,程式碼如下:
function resizeImage($filename, $max_width, $max_height) {
list($orig_width, $orig_height) = getimagesize($filename);
$width = $orig_width;
$height = $orig_height;
//原圖比設定縮圖高還高
if ($height > $max_height) {
//先依照比例縮放寬
$width = ($max_height / $height) * $width;
//指定高為縮圖高
$height = $max_height;
}
//如果目前的寬還是比設定縮圖寬還寬
if ($width > $max_width) {
//把高也依照比例再縮放
$height = ($max_width / $width) * $height;
//指定寬為縮圖寬
$width = $max_width;
}
//建立空白畫布
$image_p = imagecreatetruecolor($width, $height);
//把圖片載入
$image = imagecreatefrompng($filename);
//複製並重新取樣
imagecopyresampled($image_p, $image, 0, 0, 0, 0,
$width, $height, $orig_width, $orig_height);
//清除檔案描述子
imagedestroy($image);
return $image_p;
}
說明都在程式碼中,是參考自 PHP 文件
而第二與三步驟的盡在不言中程式碼如下:
$uid = time();
header("Content-type: image/png");
//從臉書來的圖
$dst = "profile.jpg"; //預設
//臉書圖的資訊
$dst_im = isset($_GET['p']) ? imagecreatefromstring(file_get_contents($_GET['p'])) : imagecreatefromjpeg($dst);
if ($dst_im === false) {
return;
}
$dst_path = $uid . '_new_dst.png';
imagepng($dst_im, $dst_path); //另存成png檔案
$dst_info = getimagesize($dst_path);
//要合成的底圖
$src = "cover.png"; //預設
//合成底圖的資訊
$src_im = isset($_GET['c']) ? imagecreatefromstring(file_get_contents($_GET['c'])) : imagecreatefrompng($src);
if ($src_im === false) {
return;
}
$src_path = $uid . '_new_src.png';
imagepng($src_im, $src_path); //另存成png檔案
$src_info = getimagesize($src_path);
//縮圖到印製的大小
$resize_dst = resizeImage($dst_path, $src_info[0], $src_info[1]);
$resize_dst_path = $uid . '_resize_dst.png';
imagepng($resize_dst, $resize_dst_path); //另存成png檔案
$resize_dst_info = getimagesize($resize_dst_path);
//建立新的一張空白圖
$show = imagecreatetruecolor($src_info[0], $src_info[1]);
//先複製來源圖到新圖層的左邊
imagecopy($show, $resize_dst, 0, 0, 0, 0, $src_info[0], $src_info[1]);
//是否要做覆蓋?取決於底圖是否有透明特別挖空對應
if (isset($_GET['o'])) {
imagecopy($show, $src_im, 0, 0, 0, 0, $src_info[0], $src_info[1]);
} else {
//再複製合成底圖的右半邊到新圖層的右半邊,起始點是來源圖的寬
imagecopy($show, $src_im, $resize_dst_info[0], 0, $resize_dst_info[0], 0, $src_info[0], $src_info[1]);
}
//输出合成圖(直接顯示的做法)
imagepng($show);
//或輸出合成圖至檔案
//imagepng($show, $uid . '_show.png');
//釋放檔案描述子
imagedestroy($resize_dst);
imagedestroy($src_im);
imagedestroy($show);
//移除暫存檔
unlink($dst_path);
unlink($src_path);
unlink($resize_dst_path);
恩..從描述不難看出在搞什麼鬼!?XD
這僅是一個雛形,我只有把中間合成方式加點參數切換,其他像是圖形是否需要位移以及是誰去覆蓋誰都還可以根據需求調整。
網路上還有示意參考的做法:Merging two images with PHP 這個解答寫的滿乾淨俐落,直接用 imagecopymerge
方式做合併,而我的做法採用拼貼,中間多一步驟是建立空白畫布來塞出新圖。
不過方法八九不離十,調整一些寫法就能變化成很多用途囉!