一個圖片濾鏡效果
html頁面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width = device-width,initial-scale=1.0"> </head> <body> <img src="img/5.jpg" class="photo"> </br> </br> <button class="reset">復位</button> </br> </br> <button class="grayscale">灰度效果</button> <button class="sepia">復古效果</button> <button class="redmask">紅色蒙版效果</button> <button class="brightness">亮度效果</button> <button class="invert">反轉效果</button> <button class="blackWhite">黑白效果</button> <button class="emboss">浮雕效果</button> </br> </br> <button class="redFilter">紅色濾鏡</button> <button class="greenFilter">綠色濾鏡</button> <button class="blueFilter">藍色濾鏡</button> <button class="yellowFilter">×××濾鏡</button> <button class="perpleFilter">紫色濾鏡</button> <button class="cyanFilter">青色濾鏡</button> <script src="js/photoFilter.js"></script> <script src="js/app.js"></script> </body> </html>
app.js代碼:
/**
* Created by syo on 2017/3/14.
* @author syo QQ:23371891
*/
let photoData = new PhotoFilter(document.querySelector('.photo'));
Array.prototype.slice.call(document.querySelectorAll('button')).map(function (dom, index) {
dom.onclick = function (evt) {
switch (evt.target.className) {
case 'grayscale':
photoData.grayscale();
break;
case 'sepia':
photoData.sepia();
break;
case 'redmask':
photoData.redmask();
break;
case 'brightness':
photoData.brightness(20);
break;
case 'invert':
photoData.invert();
break;
case 'blackWhite':
photoData.blackWhite(100);
break;
case 'emboss':
photoData.emboss();
break;
case 'redFilter':
photoData.redFilter();
break;
case 'greenFilter':
photoData.greenFilter();
break;
case 'blueFilter':
photoData.blueFilter();
break;
case 'yellowFilter':
photoData.yellowFilter();
break;
case 'perpleFilter':
photoData.perpleFilter();
break;
case 'cyanFilter':
photoData.cyanFilter();
break;
case 'reset':
photoData.reset();
break;
}
}
})photoFilter.js 類:
/**
* Created by syo on 2017/3/14.
* @author syo QQ:23371891
* 圖片濾鏡效果
* class PhotoFilter
* @param img 傳入img元素
*/
class PhotoFilter {
constructor(img) {
this.src = img.src;
this.img = img;
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
this.canvas.width = this.img.width;
this.canvas.height = this.img.height;
this.drawImage();
}
/**
* 初始化
* 圖片轉canvas
*/
drawImage() {
this.ctx.drawImage(this.img, 0, 0);
this.imgData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
}
/**
* 灰度
* 紅、綠、藍三個像素值的算術平均值
*/
grayscale() {
let d = this.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] = d[i + 1] = d[i + 2] = (r + g + b) / 3;
}
this.canvasToImage();
}
/**
* 復古
* 將紅、綠、藍三個像素,分別取這三個值的某種加權平均值,使得圖像有一種古舊的效果。
*/
sepia() {
let d = this.imgData.data;
//假定d[i]是像素數組中一個象素的紅色值,則d[i+1]為綠色值,d[i+2]為藍色值,d[i+3]就是alpha通道值
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
}
this.canvasToImage();
}
/**
* 紅色蒙版
* 圖像呈現一種偏紅的效果
* 算法是將紅色通道設為紅、綠、藍三個值的平均值,而將綠色通道和藍色通道都設為0
*/
redmask() {
let d = this.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 + g + b) / 3;
d[i + 1] = d[i + 2] = 0;
}
this.canvasToImage();
}
/**
* 亮度
* 圖像變得更亮或更暗
* 算法將紅色通道、綠色通道、藍色通道,同時加上一個正值或負值
* @param val 亮度值
*/
brightness(val) {
let d = this.imgData.data;
for (let i = 0; i < d.length; i += 4) {
d[i] += val;
d[i + 1] += val;
d[i + 2] += val;
}
this.canvasToImage();
}
/**
* 反相
* 圖片呈現一種色彩顛倒的效果
* 算法為紅、綠、藍通道都取各自的相反值(255-原值)
*/
invert() {
let d = this.imgData.data;
for (let i = 0; i < d.length; i += 4) {
d[i] = 255 - d[i];
d[i + 1] = 255 - d[i + 1];
d[i + 2] = 255 - d[i + 2];
}
this.canvasToImage();
}
/**
* 黑白圖片
* 求RGB平均值Avg = (R + G + B) / 3,如果Avg >= 100,則新的顏色值為R=G=B=255;
* @param Threshold 閾值
*/
blackWhite(threshold) {
let d = this.imgData.data;
for (let i = 0; i < d.length; i += 4) {
let avg = (d[i] + d[i + 1] + d[i + 2]) / 3;
d[i] = d[i + 1] = d[i + 2] = avg > threshold ? 255 : 0;
}
this.canvasToImage();
}
/**
* 浮雕效果
* 當前RGB減去相鄰的GRB得到的值再加上128
* 取平均值 再次灰度,優化浮雕的效果
*/
emboss() {
let d = this.imgData.data;
for (let i = 4; i < d.length; i += 4) {
d[i] = d[i] - d[i + 4] + 128;
d[i + 1] = d[i + 1] - d[i + 5] + 128;
d[i + 2] = d[i + 2] - d[i + 6] + 128;
let avg = (d[i] + d[i + 1] + d[i + 2]) / 3;
d[i] = avg;
d[i + 1] = avg;
d[i + 2] = avg;
}
this.canvasToImage();
}
/**
* 紅色濾鏡
* 當前紅色通道值變為原來的2倍
*/
redFilter() {
let d = this.imgData.data;
for (let i = 4; i < d.length; i += 4) {
let r = d[i] * 2;
d[i] = r > 255 ? 255 : r;
}
this.canvasToImage();
}
/**
* 綠色濾鏡
* 當前綠色通道值變為原來的2倍
*/
greenFilter() {
let d = this.imgData.data;
for (let i = 4; i < d.length; i += 4) {
let g = d[i + 1] * 2;
d[i + 1] = g > 255 ? 255 : g;
}
this.canvasToImage();
}
/**
* 藍色濾鏡
* 當前藍色通道值變為原來的2倍
*/
blueFilter() {
let d = this.imgData.data;
for (let i = 4; i < d.length; i += 4) {
let b = d[i + 2] * 2;
d[i + 2] = b > 255 ? 255 : b;
}
this.canvasToImage();
}
/**
* ×××濾鏡
* 當前紅色通道和綠色通道值+50
*/
yellowFilter() {
let d = this.imgData.data;
for (let i = 4; i < d.length; i += 4) {
let r = d[i] + 50;
let g = d[i + 1] + 50;
d[i] = r > 255 ? 255 : r;
d[i + 1] = g > 255 ? 255 : g;
}
this.canvasToImage();
}
/**
* 紫色濾鏡
* 當前紅色通道和藍色通道值+50
*/
perpleFilter() {
let d = this.imgData.data;
for (let i = 4; i < d.length; i += 4) {
let r = d[i] + 50;
let b = d[i + 2] + 50;
d[i] = r > 255 ? 255 : r;
d[i + 2] = b > 255 ? 255 : b;
}
this.canvasToImage();
}
/**
* 青色濾鏡
* 當前藍色通道和綠色通道值+50
*/
cyanFilter() {
let d = this.imgData.data;
for (let i = 4; i < d.length; i += 4) {
let g = d[i + 1] + 50;
let b = d[i + 2] + 50;
d[i + 1] = g > 255 ? 255 : g;
d[i + 2] = b > 255 ? 255 : b;
}
this.canvasToImage();
}
/**
* canvas轉換成圖片元素
*/
canvasToImage() {
this.ctx.putImageData(this.imgData, 0, 0);
this.img.src = this.canvas.toDataURL();
}
/**
* 復原
*/
reset() {
this.img.src = this.src;
this.drawImage();
}
}免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。