計算機圖像處理是一門很成熟的技術,任何一門可操做系統接口的語言都能很輕易的實現各類處理操做。可是前端限於瀏覽器環境和接口限制,處理起來會有諸多不便,這裏所說的前端圖像處理,是真的指不借助任何後端服務純前端實現的圖像處理。本文會介紹canvas位圖處理,SVG矢量圖和CSS3圖像處理,重點是canvas,而且最後會附上一個TrimPNG小應用。javascript
HTML5 canvas爲咱們提供了一塊畫布,讓前端也有了操做位圖的功能:圖片旋轉、縮放、濾鏡、壓縮等均可以經過JS來實現。html
經過設置drawImage參數能夠實現圖片繪製、縮放、拉伸和裁剪等操做(注意canvas沒法繪製體積過大圖片,不然會卡甚至崩掉,大圖能夠分塊讀取繪製
):前端
詳細用法參考 drawImage(),DEMO源碼戳這裏 JS Bin.java
只須要drawImage一個方法,就能夠實現基本圖形處理功能,再結合鼠標或滾輪事件,就能夠實現更復雜的局部放大預覽,縮放等功能了。git
如今的朋友圈發個圖都要用濾鏡美一下,復古清純膠片LOMO各類風格應有盡有。canvas提供了getImageData方法來獲取圖像上每個像素點的RGBA信息,這樣咱們就能對圖片進行像素級處理了。經過特定算法來重寫imageData中的像素信息,而後用setImageData方法把新的數據從新繪製在canvas上,這樣就能夠實現圖像濾鏡打碼加特效等一系列功能。程序員
好比咱們如今要實現一個復古濾鏡:github
// 復古濾鏡處理算法:獲取每一個像素的RGB信息,並按特定權重返回其加權平均值 let sepiaFilter = function(imgData) { let d = imgData.data for (let i = 0; i < d.length; i += 4) { let r = d[i] let g = d[i + 1] let b = d[i + 2] d[i] = (r * 0.393) + (g * 0.769) + (b * 0.189) // red d[i + 1] = (r * 0.349) + (g * 0.686) + (b * 0.168) // green d[i + 2] = (r * 0.272) + (g * 0.534) + (b * 0.131) // blue } return imgData } //圖像地址必須和當前頁面同域,不然會報cross-origin錯誤 img.src = '/img/logo@2x.png' img.onload = () => { ctx.drawImage(img, 0, 0) // 繪製原圖 let imgData = ctx.getImageData(0, 0, img.width, img.height) // 獲取圖片信息 ctx.putImageData(sepiaFilter(imgData), 100, 0) // 繪製處理後圖片 }
詳細用法參考 getImageData() 和 putImageData(),DEMO源碼戳這裏 JSFiddle.web
濾鏡處理關鍵在於濾鏡算法,要想寫出更高級的特效須要有計算機圖形學基礎,對卷積矩陣、拉普拉斯變換、傅里葉變換等數學知識也要了解,這個坑很大我就不挖了。算法
加完特效後若是咱們想把圖像保存下來,就能夠用toDataURL方法來對圖片進行格式轉換、壓縮存儲了。canvas
// 支持三種文件類型:image/png(默認) | image/jpeg | image/webp(僅Chrome) canvas.toDataURL() // 默認存儲爲png // 僅jpeg/webp支持質量參數(0~1,默認0.92) canvas.toDataURL("image/jpeg", 0.1) // 存儲爲質量爲0.1的jpeg
因爲存儲形式是base64編碼,原來圖片的每三個字節都會被擴展成4字節,因此總體上編碼後數據會比原來多約1/3。如下是經過toDataURL存儲後的圖片和原圖大小相關對比數據(數據僅供參考,不具通用性
):
可見存儲後圖片體積並非原來的4/3,實際上處理後的圖片都會比原圖大好幾倍,而且不一樣的圖片增大的體積也是不肯定的。若是是要上傳圖片到服務器,能夠把base64轉化成Blob二進制數據壓縮上傳;若是要直接在前端顯示或供用戶下載,jpg還好能夠設置質量參數,要是png就無法壓縮了。
只是用toDataURL還不夠,用戶須要經過手動點擊圖片-右鍵圖片存儲爲
來保存圖片,若是要實現點擊下載按鈕自動下載圖片還須要修改圖片類型爲octet-stream,而後利用HTML5的download屬性強制讓瀏覽器下載。
詳細用法參考toDataURL(). 自動下載圖片DEMO源碼快戳我 JSFiddle.
有了以上基礎,再結合成熟的圖形處理算法,咱們能夠完成平常工做中大部分圖像處理需求,如下列出了一些相關輪子可作備胎。備胎這種東西多多益善,萬一之後用到了呢?
注意:本人很專注。
將web頁面經過canvas來實現截屏,其原理就是遍歷DOM結構和樣式,而後在canvas中繪製出來,經過toDataURL輸出圖片。但因爲canvas圖片的同源策略限制,若是圖片和網站不一樣源的話會截取不出來的。另外在微信中測試時,即便用同源的圖片截取出來的圖片也有問題,因此要想將其用於生產環境,仍是得看場景,有不少坑要踩。
代碼轉圖片工具。有時候你在不一樣的平臺寫文章貼代碼,因爲不一樣平臺代碼格式化規範不一,因此常常會出現代碼排版問題,經過這個工具將代碼轉成圖片就能夠避免排版問題了。
一個專門用來作圖片裁剪的應用。
這是一個專業的計算機視覺處理JS庫,包含了大量圖形處理算法,可用來作人臉識別,色彩追蹤等酷炫功能。
用JS動態生成二維碼,這個庫仍是很實用的,原理就是qrcode算法+canvas繪圖,不支持canvas的用table兼容。
騰訊出的基於HTML5的專業級圖像處理開源引擎,功能很強大,簡直就是Web版的PS。
以上列舉部分,更多備胎在此: https://github.com/0326/canvas
講完位圖再說矢量圖。矢量圖在繪製圖標、商業LOGO、動畫元素上應用很是廣範。Web最開始支持的矢量圖形並非如今的SVG,而是微軟主推的VML,因此在低版本IE下面只支持VML而不支持SVG,直到後來SVG成爲W3C標準並被普及,微軟纔在IE9中支持SVG。
SVG遵循XML規範,能夠很好的集成在HTML裏面,同時支持JS腳本控制,還有基於SMIL標準的動態內容支持,作起動畫來也是很是方便。目前基於SVG的JS圖形庫輪子也是很是多,如svg.js, Snap.svg, Velocity.js, D3.js等等,目前暫無SVG應用需求,等用的時候再翻牌子吧。
若是你的圖像特效只是用來給用戶展現,並不須要存儲的話,能夠直接用CSS處理,基本的調整圖片大小、拉伸、旋轉、裁切等操做直接幾個CSS屬性width/height/skew/rotate/clip-path等就能搞定了。若是想加特效,使用CSS濾鏡Duang的一下就出來了,不須要任何圖形學基礎和數學知識:
詳細說明見 CSS filter - MDN, DEMO 源碼見JS Bin.
最後介紹個小工具TrimPNG。你們都知道TinyPNG能夠壓縮PNG, TrimPNG顧名思義就是去除圖片空白和白邊的,實現了自動摳圖和切圖的功能(logo我是直接抄的TinyPNG,都是熊貓,應該沒關係?)
用到的技術點上面都說到了,裁切實現原理就是橫向縱向分別掃描兩次像素點陣,找出上下左右最外面的非透明點,而後定位出有效圖像區域。去除白邊算法目前還比較傻逼,只要是接近白色的點都被我幹掉了,後面再完善好了 去白邊算法優化了一下,採用標記清除策略(聽着耳熟吧,其實就是從GC受的啓發...),先掃描一遍標記出可疑白點,而後再掃描一遍,凡是與透明區域相鄰的可疑白點就清除,固然這個算法也比較死,若是有更專業更智能的請務必告訴我。
體驗地址:http://quanfeng.tech/trimpng/
本文只拋磚,做爲工做時技能儲備,若有任何補充歡迎留言交流~,另外,大家這幫人吶,都收藏了就順便點個推薦尼!⊙ o ⊙