首頁 web前端 H5教程 JS的圖片處理與合成詳解

JS的圖片處理與合成詳解

Mar 27, 2018 pm 03:41 PM
javascript 合成 詳解

這次帶給大家JS的圖片處理與合成詳解,JS圖片處理與合成的注意事項有哪些,以下是實戰案例,一起來看一下。

引言

圖片處理現在已經成為了我們生活中的剛需,想必大家也常有這方面的需求。實際前端業務中,也常常會有很多的項目需要用到圖片加工處理。由於過去一段時間公司的業務需求,讓我在這方面積累了一些乾貨,趁著年後這段時間總結成一系列文章與大家分享,希望能對各位努力中的前端童鞋帶來啟發和幫助

本系列分成以下4個部分:

  1. 基礎型別圖片處理技術之縮放與裁切;

  2. ##基礎型別圖片處理技術之圖片合成;

  3. 基礎類型圖片處理技術之文字合成;

  4. ##演算法類型圖片處理技術;
  5. 透過這些積累,我封裝了幾個項目中常用的功能:

圖片合成: Example Git 圖片裁剪: Example Git 人像摳除: Example Git

嘮叨完這些老套路後,我們開始起飛!

首先,我在這裡將前端圖片處理暫且分成兩種類型:基礎類型與演算法類型;

基礎類型的圖片處理技術: 圖片縮放,旋轉,添加邊框,圖片合成,拼圖等業務都屬於基礎類型的圖片處理,其區分點在於無需使用像素級別的演算法,而是透過計算改變圖片的尺寸及位置等來改造圖片。例如常用的貼紙功能:

演算法類型的圖片處理: 這類型的圖片處理複雜度較高,特點是透過像素層級演算法對圖片的像素點進行

RGBA

通道值等進行改造,例如我們使用photshop或美圖秀等工具對圖片進行的美顏/ 濾鏡/ 黑白/ 摳圖/ 模糊等操作,這類型的重點主要在於演算法和效能層面。例如常用的妝容功能:

本系列首先從基礎型別處理開啟我們的旅程。基礎類型的圖片處理在實際專案中有著大量的使用場景,主要是運用

canvas

的能力來完成,不存在效能和相容性問題,能夠達到線上運行標準。我在這裡將基礎類型的圖片處理大致的分成以下幾種類型,這些類型基本上能涵蓋日常所有業務場景:

    圖片的縮放;
  • #圖片的裁切;
  • 圖片的合成;
  • #圖片與圖片的合成,例如貼紙,邊框,浮水印等;為圖片添加文字;為圖片添加基礎幾何圖形;

Tips: 我已將該類型的圖片處理場景封裝成了一個插件,基本上能應付所有這類型圖片處理的需求,GIT地址(歡迎探討);

在介紹具體的功能前,由於圖片的繪製完全的依賴於圖片的加載,因此先來了解一些前置知識。

1、圖片的跨域

首先,圖片載入並繪製涉及了圖片的跨域問題,因此如果是一張在線的圖片,需要在圖片伺服器上設定跨域頭,並且在前端載入圖片之前將

<img>

標籤的crossOrigin設定為*,否則繪製到畫布的時候會報跨域的錯誤。 Tips: 這裡累積了一些小坑,可以跟大家分享下:

  1. #crossOrigin

    需要嚴格設置,既只有是線上圖片時,才設置,而本地路徑或base64時,則一定不能設置,否則在某些系統下會報錯,導致圖片加載失敗;

    ##當當項目為本機套件環境時,例如內建於
  2. App
  3. 時,

    crossOrigin值無效,webview的安全機制會導致無論該值設定與否,都會報跨域的錯誤。解決方法是:需要將所有圖片轉換成base64才能正確繪製;

  4. crossOrigin值一定要在圖片載入之前設置,即為<img>賦值src之前進行設置,否則無效;

2、圖片的載入

#由於canvas的繪製需要的是已經載入完成的圖片,我們需要確保繪製的素材圖片是已經載入完成的,因此我們需要使用<img>onload事件,可以使用html中已存在的圖片,或是用js建立一個圖片物件:

function loadImage(image, loader, error){
 // 创建 image 对象加载图片;
 let img = new Image();
 
 // 当为线上图片时,需要设置 crossOrigin 属性;
 if(image.indexOf('http') == 0)img.crossOrigin = '*';
 img.onload = () => {
 loaded(img);
 
 // 使用完后清空该对象,释放内存;
 setTimeout(()=>{
  img = null;
 },1000);
 };
 img.onerror = () => {
 error('img load error');
 };
 img.src = image;
}
登入後複製

介紹圖片載入的前置知識後,我們先來看最簡單的圖片處理---縮放與裁切!

Tips: 相信大家閱讀本文時,如果對canvas不太了解,可以查詢下對應的API文件即可,本文不再對 canvas基礎API做詳細解說。

一、圖片的縮放

圖片的縮放最常見的場景是做圖片的壓縮。在保證圖片清晰的前提下透過合理地縮小圖片尺寸,能大大的降低圖片的大小。在實際應用場景中,有著廣泛的用途。例如圖片上傳時,使用者自主上傳的圖片可能是一張非常大的尺寸,例如現在手機所拍攝的照片尺寸經常能達到1920*2560的尺寸,大小可能超過5M。而在專案中,我們可能不需要用到這麼大的尺寸,此時對圖片的壓縮能大大的優化載入速度和節省頻寬;

1、新建一個canvas畫布,將寬高設定為需要壓縮到的尺寸;

該畫布既為圖片縮放後的尺寸,此處有個點是需要保證圖片的比例不變, 因此需要通過計算得出畫布的寬與高:

let imgRatio = img.naturalWidth / img.naturalHeight;
// 创建一个画布容器;
let cvs = document.createElement('canvas');
// 获取容器中的画板;
let ctx = cvs.getContext('2d');
cvs.width = 1000;
cvs.height = cvs.width / imgRatio;
登入後複製

2、將圖片畫入後再導出成base64;

這裡使用2個最常用的方法:

ctx.drawImage(image, dx, dy, dw, dh): 這個方法其實最多可以接收9個參數, 實現壓縮,只需要使用其中的5個參數即可, 其餘參數在其它部分使用到時再做詳解;

image : 需要繪製的圖片來源,需要接收已經載入完成的HTMLImageElementHTMLCanvasElementHTMLVideoElement; dx / dy : 相對於畫布左上角的繪製起始點座標; dw / dh : 繪製的寬度和高度,寬高比例並不鎖定,可使圖片變形;

##cvs. toDataURL(type, quality): 此方法用於將畫布上的內容匯出成base64 格式的圖片,可配置2個參數;

type: 圖片格式, 一般可以使用

image/pngimage/jpeg, 當圖片不包含透明時,建議使用 jpeg,可使匯出的圖片大小減小很多;quality : 圖片質量,可使用0~1之間的任意值;經過測試,該值設定成0.9時較為合適,可以有效減小圖片檔案大小且基本上不影響圖片清晰度,導出後的base64 既為壓縮後的圖片;

Tips: 此處有個坑, 想導出
jpg格式的圖片必須用image/jpeg,不能使用image/jpg
// 将原图等比例绘制到缩放后的画布上;
ctx.drawImage(image, 0, 0, cvs.width, cvs.height);
// 将绘制后的图导出成 base64 的格式;
let b64 = cvs.toDataURL('image/jpeg', 0.9);
登入後複製
3.多種格式的圖片轉換成

base64;

#我們常用的圖片上傳功能,我們使用的是原生的

標籤,此時取得到的是File格式的圖片,圖片的格式各異且尺寸很大,我們應該壓縮處理後再使用。

使用

FileReader:

let file = e.files[0]; 
if(window.FileReader) { 
 let fr = new FileReader(); 
 fr.onloadend = e => {
 let b64 = e.target.result;
 
 // b64即为base64格式的用户上传图;
 }; 
 fr.readAsDataURL(file);
}
登入後複製

base64的圖片使用剛才的canvas方式進行壓縮的處理;

Tips: 這裡有個小坑是,圖片的

EXIF訊息中的方向值會影響圖片的展示,在IOS會出現圖片的寬高與圖片的方向不符的問題,因此需要進行特殊處理,矯正圖片的方向。方案:

1、可以使用

exif.js 來取得圖片資訊中的Orientation屬性,利用canvas的旋轉繪製來矯正;

2、這裡有個

canvasResize.js 插件,可以解決從Filebase64 的所有問題。

二、圖片的裁切

在实际项目中,由于图片的宽高比例各式各样,而展示和使用一般需要一个较为固定的比例,此时便需要将图片裁剪成我们需要的宽高比例,使用到的方式其实和图片的缩放基本一致,主要是通过调整 drawImagedx, dy参数来实现。原理其实是,将drawImage的绘制起始点(dx, dy)向上偏移,此时由于canvas已被我们设置成期望裁剪后的尺寸,而超出画布的部分不会绘制,从而达到裁剪的目的;通过灵活的设置值,基本可以完成各种图片裁剪需求,简单示例图(黑色框代表创建的画布的尺寸):

此处以需要将一张600*800的长方形图竖直居中裁剪为600*600的正方形图为例, 简单封装成一个功能函数:

// 使用方式:
let b64 = cropImage(img, {
 width : 600,
 height : 600,
});
// 居中裁剪
function cropImage(img, ops){
 // 图片原始尺寸;
 let imgOriginWidth = img.naturalWidth,
 imgOriginHeight = img.naturalHeight;
 
 // 图片长宽比,保证图片不变形;
 let imgRatio = imgOriginWidth / imgOriginHeight;
 
 // 图片裁剪后的宽高, 默认值为原图宽高;
 let imgCropedWidth = ops.width || imgOriginWidth,
 imgCropedHeight = ops.height || imgOriginHeight;
 
 // 计算得出起始坐标点的偏移量, 由于是居中裁剪,因此等于 前后差值 / 2;
 let dx = (imgCropedWidth - imgOriginWidth) / 2,
 dy = (imgCropedHeight - imgOriginHeight) / 2;
 // 创建画布,并将画布设置为裁剪后的宽高;
 let cvs = document.createElement('canvas');
 let ctx = cvs.getContext('2d');
 cvs.width = imgCropedWidth;
 cvs.height = imgCropedHeight;
 
 // 绘制并导出图片;
 ctx.drawImage(img, dx, dy, imgCropedWidth, imgCropedWidth / imgRatio);
 return cvs.toDataURL('image/jpeg', 0.9);
}
登入後複製

三、图片的旋转

图片的旋转的原理同样也是将图片绘制到画布上进行旋转后再导出。其实使用到的是canvasrotate方法;

let cvs = document.createElement('canvas');
let ctx = cvs.getContext('2d');
// 将参照点移动到画板的中心点;
ctx.translate(ctx.width/2, ctx.height/2);
// 旋转画板;
ctx.rotate = 90;
// 绘制图片;
ctx.drawImage(img);
// 导出得到旋转后的图片;
cvs.toDataURL();
登入後複製

这里有个比较特别的部分,就是这里旋转的是画布的画板部分,并不是整个画布容器,而画布容器外面不会被绘制,因此这里就会出现一个图像四个角被裁剪掉的问题:

解决的方式就是:

将画布容器放大,变成:

上面这个例子中,由于图片是正方形,因此将容器的宽高放大1.5倍便可保证图片不会被裁剪,而现实中的图片由于宽高比例不定,因此这个放大系数是一个动态的值:

Tips: 由于我们将画板基点移动到画布中心了,因此在绘制的时候,要相对于基点调整 dxdy;
// 创建画布,获取画板;
...
// 放大系数为
let iw = img.width, ih = img.height;
let ir = iw > ih ? iw / ih : ih / iw;
cvs.width = iw * ir * 1.5;
cvs.height = ih * ir * 1.5;
// 将参照点移动到画板的中心点;
ctx.translate(cvs.width/2, cvs.height/2);
// 旋转画板;
ctx.rotate = 90;
// 绘制图片;
ctx.drawImage(img, -cvs.width/2, -cvs.height/2);
// 导出图片;
...
登入後複製

总结

本文主要介绍了一些前端图片处理的前置知识:

图片处理技术分类;

基础类型图片处理技术;算法类型图片处理技术; 图片的跨域;图片的加载;

还有讲解了属于基础类型图片处理中最简单的两类:

图片的缩放;图片的裁剪;图片的旋转;

相信大家已经对图片的处理有了个大致的了解了。下篇文章,我们将继续深入研究基础类型中的图片合成,也是各种干货满满,美不胜收。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

ionic2中怎么使用自动生成器

操作Vue渲染与插件加载的顺序

以上是JS的圖片處理與合成詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Win11管理員權限取得詳解 Win11管理員權限取得詳解 Mar 08, 2024 pm 03:06 PM

Windows作業系統是全球最受歡迎的作業系統之一,其新版本Win11備受矚目。在Win11系統中,管理員權限的取得是一個重要的操作,管理員權限可以讓使用者對系統進行更多的操作和設定。本文將詳細介紹在Win11系統中如何取得管理員權限,以及如何有效地管理權限。在Win11系統中,管理員權限分為本機管理員和網域管理員兩種。本機管理員是指具有對本機電腦的完全管理權限

Oracle SQL中的除法運算詳解 Oracle SQL中的除法運算詳解 Mar 10, 2024 am 09:51 AM

OracleSQL中的除法運算詳解在OracleSQL中,除法運算是一種常見且重要的數學運算運算,用來計算兩個數相除的結果。除法在資料庫查詢中經常用到,因此了解OracleSQL中的除法運算及其用法是資料庫開發人員必備的技能之一。本文將詳細討論OracleSQL中除法運算的相關知識,並提供具體的程式碼範例供讀者參考。一、OracleSQL中的除法運算

怎樣把幾張照片合成一張照片 如何將幾張圖片拼接為一張 怎樣把幾張照片合成一張照片 如何將幾張圖片拼接為一張 Feb 22, 2024 pm 04:00 PM

在拼圖中選擇圖片和模板後儲存即可。教學適用型號:iPhone13系統:iOS15.3版本:美圖秀9.5.70&&天天P圖6.5.4解析1先進入美圖秀秀的首頁,找到並點選拼圖。 2跳轉進入相簿頁面,選擇需要合成的圖片後,點選開始拼圖。 3選擇拼圖模板後,點選頁面右上角的鉤形圖示即可。補充:天天P圖如何拼接圖片1先進入天天P圖首頁中,找到並點選故事拼圖。 2待頁面跳轉,勾選合適的圖片後,點選右下方的開始拼圖。 3選擇喜歡的拼圖範本後,點選頁面右上角的儲存圖示即可。總結/注意事項一次拼圖只能選擇1至9張

PHP模運算子的作用及用法詳解 PHP模運算子的作用及用法詳解 Mar 19, 2024 pm 04:33 PM

PHP中的模運算子(%)是用來取得兩個數值相除的餘數的。在本文中,我們將詳細討論模運算子的作用及用法,並提供具體的程式碼範例來幫助讀者更好地理解。 1.模運算子的作用在數學中,當我們將一個整數除以另一個整數時,就會得到一個商和一個餘數。例如,當我們將10除以3時,商數為3,餘數為1。模運算子就是用來取得這個餘數的。 2.模運算子的用法在PHP中,使用%符號來表示模

linux系統呼叫system()函數詳解 linux系統呼叫system()函數詳解 Feb 22, 2024 pm 08:21 PM

Linux系統呼叫system()函數詳解系統呼叫是Linux作業系統中非常重要的一部分,它提供了一種與系統核心互動的方式。其中,system()函數是常用的系統呼叫函數之一。本文將詳細介紹system()函數的使用方法,並提供對應的程式碼範例。系統呼叫的基本概念系統呼叫是使用者程式與作業系統核心互動的一種方式。使用者程式透過呼叫系統呼叫函數來請求作業系統

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

Linux的curl指令詳解 Linux的curl指令詳解 Feb 21, 2024 pm 10:33 PM

Linux的curl命令詳解摘要:curl是一種強大的命令列工具,用於與伺服器進行資料通訊。本文將介紹curl指令的基本用法,並提供實際的程式碼範例,幫助讀者更好地理解和應用該指令。一、curl是什麼? curl是命令列工具,用於發送和接收各種網路請求。它支援多種協議,如HTTP、FTP、TELNET等,並提供了豐富的功能,如檔案上傳、檔案下載、資料傳輸、代

我的世界綠色染料怎麼合成 我的世界綠色染料怎麼合成 Jan 27, 2024 am 10:27 AM

在我的世界中,道具的合成是一項重要的任務。為了獲得綠色染料,玩家需要準備一些特定的材料來合成。下面是合成綠色染料的方法。我的世界綠色染料合成方法1、製作工作台:採集木材徒手製作工作台,放置地面待用。 2.解鎖熔爐:透過工作台製作熔爐,點擊熔爐打開製作介面。 3.合成仙人掌綠:將採集來的仙人掌方塊放入熔爐,添加燃料得到仙人掌綠。 4.分解骨粉:將骨頭放入工作台製作介面,分解為骨粉。 5.製作綠色染料:將1份骨粉和1份仙人掌綠放入工作台,製作綠色染料。

See all articles