在PHP裡很好的使用ImageMagick---convert篇

Drl龍發表於2018-09-19

[原文連結]duanruilong.github.io/blog/2018/0…

ImageMagick 包括一組命令列工具來操作圖片,之前的ImageMagick實現base64圖片的邏輯在伺服器端可能會造成溢位的事故,所以在接下的文章裡會介紹另外一種好的實現方式就是----convert命令。使用命令格式的形式去生成圖片和大小的裁剪資料格式的轉換。

PHP

基本命令與格式

1、基本命令

  • magick: 建立、編輯影象,轉換影象格式,以及調整影象大小、模糊、裁切、除去雜點、抖動 ( dither )、繪圖、翻轉、合併、重新取樣等。

  • convert: 等同於 magick 命令。

  • identify: 輸出一個或多個影象檔案的格式和特徵資訊,如解析度、大小、尺寸、色彩空間等。

  • mogrify: 與 magick 功能一樣,不過不需要指定輸出檔案,自動覆蓋原始影象檔案。

  • composite: 將一個圖片或多個圖片組合成新圖片。

  • montage: 組合多個獨立的影象來建立合成影象。每個影象都可以用邊框,透明度等特性進行裝飾。

  • compare: 從數學和視覺角度比較源影象與重建影象之間的差異。

  • display:在任何 X server 上顯示一個影象或影象序列。

  • animate: 在任何 X server 上顯示影象序列。

  • import: 儲存 X server 上的任何可見視窗並把它作為影象檔案輸出。可以捕捉單個視窗,整個螢幕或螢幕的任意矩形部分。

  • conjure:解釋並執行 MSL ( Magick Scripting Language ) 寫的指令碼。

  • stream: 一個輕量級工具,用於將影象或部分影象的一個或多個畫素元件流式傳輸到儲存裝置。在處理大影象或原始畫素元件時很有用。

2、命令格式

基本命令的使用,遵循 Unix 風格的標準格式,例如 command [options] input_image output_image

將一張寬高 300x300 的圖片 goods.png 轉換成 200x200 的goods.jpg,可以這樣用

convert -resize 200x200 goods.png goods.jpg

複製程式碼

開始繪製生成圖片

一些前期引數

1、入參


$item_img='https://img.alicdn.com/bao/uploaded/i1/1750208593/TB1rgM3hhtnkeRjSZSgXXXAuXXa_!!0-item_pic.jpg';
$item_title='測試字型';
$shop_title='測試店鋪';
$shop_img='http://q.aiyongbao.com/item/web/images/qap_img/mobile/userAvatar.png';
$qr_img='https://img.alicdn.com/tfscom/TB1uJDStYZnBKNjSZFKwu3GOVXa.png';
$numid_share='0000000';
$qr_title='長按識別二維碼';

// 對寶貝標題裁剪
$drawtitone=mb_substr($item_title,0,13, 'utf-8');
$drawtittow=mb_substr($item_title,13,13, 'utf-8');
$drawtitthree=mb_substr($item_title,26,13, 'utf-8');
$time_date = time(); // 時間戳
$workDir = '/data/tmp/'.$numid_share.'_con'.$time_date; // 目標路徑---->指定一個資料夾儲存生成圖片過程裡的圖片

複製程式碼

2、先下載素材檔案

我們這裡需要一個拼接圖片的連結,所以先下載到之前的建立的資料夾下,因為這些素材圖片只是為了最後的拼接,最後可以完全刪除。


$item_img_down = $workDir.'/itemimage.jpg';
$shop_img_down = $workDir.'/shopimage.jpg';
$qr_img_down = $workDir.'/qrimage.jpg';
// 下載寶貝主圖
\NetworkUtils::curlDownload($item_img, $item_img_down);
// 下載店鋪圖片
\NetworkUtils::curlDownload($shop_img, $shop_img_down);
// 下載二維碼
\NetworkUtils::curlDownload($qr_img, $qr_img_down);

複製程式碼

\NetworkUtils::curlDownload($item_img, $item_img_down); 下載$item_img儲存在目標路徑資料夾下的$workDir.'/itemimage.jpg'路徑。

3、指定字型和顏色

$fontFamily = '/usr/share/fonts/chinese/msyh.ttf';
$fontColor = '#333333';
$fontColor_shoptitle = '#999999';
$fontColor_qrtitlt = '#666666';
複製程式碼

4、建立一個底圖

建立一個750x1046白色的底圖,我們可以在上面繪製文字

// 建立一個底圖(並且加上一些文字)

$back_img=$workDir.'/bg.jpg'; //要生成的圖片的路徑---->可以在伺服器端看到
$back_cmds="convert 'xc:[750x1046!]' -background white -font {$fontFamily} -draw 'text 580,994 \"{$qr_title}\"' -fill \"{$fontColor_qrtitlt}\" 
            -pointsize 20 -draw 'text 114,990 \"{$shop_title}\"' -font {$fontFamily} -pointsize 22 -fill '#999999' {$workDir}/bg.jpg";
$result_back_cmds = \SystemCommon::runningCmd($back_cmds);  

複製程式碼

這裡需要注意一下文字的繪製命令順序,否則會出現沒有生效的問題。 -font {$fontFamily} -draw 'text 580,994 \"{$qr_title}\"' -fill \"{$fontColor_qrtitlt}\" -pointsize 20

解釋一下:

  • xc:[100x40!]: 設定畫布大小的一種簡寫方式,方括號裡寫入畫布寬高,注意要加 !
  • -fill 'rgba(0, 0, 0, 0)':設定了文字的填充顏色
  • text 114,990: 對文字進行定位
  • -font:指定字型
  • -pointsize:指定文字的字型大小
  • -draw:繪圖選項,text 宣告繪製文字, 0,0 宣告文字距離圖片左上角的偏移值,繪製文字的格式為 text x,y string,當然還可以繪製其他型別,諸如圓 ( circle )、折線 ( polyline )

繼續新增文字:

$back_img_shoptitle=$workDir.'/btitle.jpg'; //要生成的圖片的路徑
$back_cmds_shoptitle="convert -draw 'text 40,820 \"{$drawtitone}\"' -font {$fontFamily} -pointsize 32 -fill \"{$fontColor}\" -draw 'text 40,866 \"{$drawtittow}\"' 
                    -font {$fontFamily} -pointsize 32 -fill \"{$fontColor}\" -draw 'text 40,912 \"{$drawtitthree}\"' -font {$fontFamily} -pointsize 32 -fill \"{$fontColor}\"  
                    {$back_img} {$workDir}/btitle.jpg";
$result_back_cmds_shoptitle = \SystemCommon::runningCmd($back_cmds_shoptitle);  

複製程式碼

效果: (白色的背景可能顯示不是很好)

convert

5、拼接圖片

現在就可以在之前得到的圖片上拼接所需要的圖片了

 // 在底圖上合併商品主圖
$back_img_itemimg='/data/tmp/' . md5(microtime(true)).'.jpg';  //要生成的圖片的路徑
$geometryX = "+" . 0; // 定位
$geometryY = "+" . 0; // 定位
$customPicPos = "northwest";
$back_cmds_itemimg = "convert {$back_img_shoptitle} {$workDir}/item_img_mag.jpg -gravity {$customPicPos} -geometry {$geometryX}{$geometryY} 
                    -compose over -composite -antialias -set colorspace sRGB -colorspace sRGB {$workDir}/result.jpg";
$result_back_cmds_itemimg = \SystemCommon::runningCmd($back_cmds_itemimg); 

複製程式碼

解釋一下:

  • -geometry: 設定文字在圖片裡的排列方式 ( 類似 CSS 裡的 align-items + justify-content ),center 表示水平垂直都居中,其他值還可以是:NorthWest, North, NorthEast, West, East, SouthWest, South, SouthEast,不記大小寫
  • composite: 將一個圖片或多個圖片組合成新圖片。

這裡是把{$workDir}/item_img_mag.jpg路徑的圖片繪製到之前繪製文字的圖片上$back_img_shoptitle,最終得到的圖片儲存路徑是在{$workDir}/result.jpg

讓我們繼續操作圖片

// 合併二維碼 
$geometryXshop = "+" . 40;
$geometryYshop = "+" . 950;
$back_cmds_shopimg = "convert {$workDir}/result.jpg {$workDir}/shop_img_mag.jpg -gravity {$customPicPos} -geometry {$geometryXshop}{$geometryYshop} -compose over -composite -antialias -set colorspace sRGB -colorspace sRGB {$workDir}/result1.jpg";
$result_back_cmds_shopimg = \SystemCommon::runningCmd($back_cmds_shopimg);  

// 合併店鋪圖示
$geometryXqr = "+" . 520;
$geometryYqr = "+" . 784;
$back_cmds_qrimg = "convert {$workDir}/result1.jpg {$workDir}/qr_img_mag.jpg -gravity {$customPicPos} -geometry {$geometryXqr}{$geometryYqr} -compose over -composite -antialias -set colorspace sRGB -colorspace sRGB {$workDir}/result2.jpg";
$result_back_cmds_qrimg = \SystemCommon::runningCmd($back_cmds_qrimg);  

複製程式碼

效果:

convert

發現圖片並不是我們預期的效果,拼接我們也設定了圖片的大小,但是沒有起作用,嘗試過不同的方案後決定在拼接之前把圖片統一放大為需要拼接的尺寸來操作。

6、放大拼接圖片尺寸

需要對多拼接的圖片都進行操作

 // 看來需要先放大主圖
$item_img_m="convert -resize '750x766!' {$item_img_down} {$workDir}/item_img_mag.jpg";
$item_img_mag = \SystemCommon::runningCmd($item_img_m);  
// 看來需要先放大二維碼
$shop_img_m="convert -resize 64x64 {$shop_img_down} {$workDir}/shop_img_mag.jpg";
$shop_img_mag = \SystemCommon::runningCmd($shop_img_m);  
// 看來需要先放大店鋪圖示
$qr_img_m="convert -resize 200x200 {$qr_img_down} {$workDir}/qr_img_mag.jpg";
$qr_img_mag = \SystemCommon::runningCmd($qr_img_m);  

複製程式碼

-resize 延伸解讀

IamgeMagick 提供了幾種符號來定義縮放

convert -resize '150x100!' goods.jpg thumbnail.jpg

convert -resize '150x100>' goods.jpg thumbnail.jpg

convert -resize '150x100<' goods.jpg thumbnail.jpg

複製程式碼
  • !:不管圖片寬高如何,都縮放成 150x100 這樣的尺寸。
  • >:只有寬高均大於 150x100 的圖片才縮放成該尺寸 ( 按比例取最大值 ),小於的圖片不做處理。
  • <:與 > 功能相反

縮放對比

convert

這樣的結果也不是我們需要的

convert

只有convert -resize '750x766!' {$item_img_down} {$workDir}/item_img_mag.jpg這樣固定尺寸之後可以得到:

convert

7、圖片轉換為 base64格式

我們最後同樣的以base64格式輸出給前端

$stdout = trim($result_back_cmds_qrimg["stdout"]);
$Return = array();
if (empty($stdout) || strpos($result_back_cmds_qrimg["stderr"], "identify") != false) {  // runningCmd執行成功
    $dest_img = $workDir.'/result2.jpg';
    // /*圖片轉換為 base64格式編碼*/
    $base64_image = '';
    $image_info = getimagesize($dest_img);
    $image_data = fread(fopen($dest_img, 'r'), filesize($dest_img));
    $base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data));

    $Return['data']=$base64_image;
    $Return['dest_img']=$dest_img;
    $Return['type']='success';
    $Return['msg']=1;
    return $Return;
}
$Return['data']='';
$Return['msg']=2;
return $Return;

複製程式碼

$workDir.'/result2.jpg是我們最終的拼接圖片,至於資料夾下的其他圖片,可以選擇刪除。我們只要得到結果就好了。

(小姐姐拼接圖)

convert

這次convert命令的介紹是以解讀整個方法的形式,對拼接的開始進行到結尾生成最終的圖片,希望對大家有力所能及的幫助。

歡迎光顧個人部落格Blog

相關文章