1. Vue和Canvas介绍
Vue.js是一个轻巧、高效的JavaScript框架,广受开发者欢迎,并且被用于构建一系列单页面应用程序。
Canvas是HTML5中定义的一个画布元素,可以用来绘制2D图形和动态图像。
2. 实现图片的颜色调整功能
2.1 图片预览
首先需要使用Vue.js实现图片的预览功能,可以通过Vue.js自带的<input type="file">
和<img>
标签来达到目的。
将图片显示在canvas上需要两个步骤:使用drawImage()
方法将图片画在canvas上,将图片转换为canvas可处理的颜色值。
new Vue({
el: "#app",
data: {
imageSrc: "",
canvas: null,
ctx: null,
imageData: null,
},
mounted() {
this.initCanvas();
},
methods: {
initCanvas() {
this.canvas = document.getElementById("canvas");
this.ctx = this.canvas.getContext("2d");
},
previewImage(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = () => {
const image = new Image();
image.onload = () => {
this.canvas.width = image.width;
this.canvas.height = image.height;
this.drawImage(image);
};
image.src = reader.result;
this.imageSrc = reader.result;
};
reader.readAsDataURL(file);
},
drawImage(image) {
this.ctx.drawImage(image, 0, 0);
this.imageData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
},
},
});
这里使用了Vue.js的data
属性管理图片链接和canvas对象,使用drawImage()
绘制图片到canvas并使用getImageData()
获取图像数据。
2.2 调整图片颜色
接下来,实现调整图片颜色的功能。调整图片颜色的方法有很多,这里采用简单的调整亮度、对比度、饱和度的方法。
2.2.1 调整亮度
调整亮度的方法很简单,将所有像素值加上一个指定数值即可。具体实现代码如下:
changeBrightness(value) {
for (let i = 0; i < this.imageData.data.length; i += 4) {
this.imageData.data[i] += value;
this.imageData.data[i + 1] += value;
this.imageData.data[i + 2] += value;
}
this.ctx.putImageData(this.imageData, 0, 0);
}
这里使用了value
指定亮度,将每个像素的RGB值都加上value
即可。
2.2.2 调整对比度
要调整对比度,可以用下面这个公式:
C = f( C ? 0.5) + 0.5
其中f(x) = (1 + factor) * Math.pow(x - 0.5, 3) + 0.5
。
下面是具体实现代码:
changeContrast(value) {
const factor = (259 * (value + 255)) / (255 * (259 - value));
for (let i = 0; i < this.imageData.data.length; i += 4) {
this.imageData.data[i] = factor * (this.imageData.data[i] - 128) + 128;
this.imageData.data[i + 1] = factor * (this.imageData.data[i + 1] - 128) + 128;
this.imageData.data[i + 2] = factor * (this.imageData.data[i + 2] - 128) + 128;
}
this.ctx.putImageData(this.imageData, 0, 0);
}
这里使用了value
指定对比度,使用公式计算RGB值的新值。
2.2.3 调整饱和度
饱和度每个像素的RGB值都是另一个值的加权平均值。使用下面的公式计算权重:
gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
其中r、g、b
分别是像素的红、绿、蓝通道值。
然后使用下面的公式计算新的RGB值:
r = gray + saturation * (r - gray)
g = gray + saturation * (g - gray)
b = gray + saturation * (b - gray)
其中saturation
是在0到1之间的值。
changeSaturation(value) {
const grayScaleLuminance = [0.2989, 0.5870, 0.1140];
const maxRGB = 255;
for (let i = 0; i < this.imageData.data.length; i += 4) {
const r = this.imageData.data[i];
const g = this.imageData.data[i + 1];
const b = this.imageData.data[i + 2];
const gray = r * grayScaleLuminance[0] + g * grayScaleLuminance[1] + b * grayScaleLuminance[2];
this.imageData.data[i] = Math.round(gray + (r - gray) * value);
this.imageData.data[i + 1] = Math.round(gray + (g - gray) * value);
this.imageData.data[i + 2] = Math.round(gray + (b - gray) * value);
}
this.ctx.putImageData(this.imageData, 0, 0);
}
3. 实现图片滤镜效果
本节将实现几个常见的图片滤镜效果。
3.1 模糊滤镜
模糊滤镜可以通过计算每个像素的周围像素的平均值来实现。具体代码如下:
blurImage() {
const weights = [1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9];
const side = Math.round(Math.sqrt(weights.length));
const halfSide = Math.floor(side / 2);
const src = this.imageData.data;
const dest = new Uint8ClampedArray(src.length);
const width = this.canvas.width;
const height = this.canvas.height;
let alphaFac = 0;
for (let i = 0; i < weights.length; i++) {
const f = weights[i];
alphaFac += f;
}
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const sy = y;
const sx = x;
const dstOff = (y * width + x) * 4;
let r = 0;
let g = 0;
let b = 0;
let a = 0;
for (let cy = 0; cy < side; cy++) {
for (let cx = 0; cx < side; cx++) {
const scy = sy + cy - halfSide;
const scx = sx + cx - halfSide;
if (scy >= 0 && scy < height && scx >= 0 && scx < width) {
const srcOff = (scy * width + scx) * 4;
const wt = weights[cy * side + cx];
r += src[srcOff] * wt;
g += src[srcOff + 1] * wt;
b += src[srcOff + 2] * wt;
a += src[srcOff + 3] * wt;
}
}
}
dest[dstOff] = r / alphaFac;
dest[dstOff + 1] = g / alphaFac;
dest[dstOff + 2] = b / alphaFac;
dest[dstOff + 3] = a;
}
}
this.imageData.data.set(dest);
this.ctx.putImageData(this.imageData, 0, 0);
}
3.2 反色滤镜
反色滤镜可以将每个像素的颜色取反实现。代码如下:
invertImage() {
for (let i = 0; i < this.imageData.data.length; i += 4) {
this.imageData.data[i] = 255 - this.imageData.data[i];
this.imageData.data[i + 1] = 255 - this.imageData.data[i + 1];
this.imageData.data[i + 2] = 255 - this.imageData.data[i + 2];
}
this.ctx.putImageData(this.imageData, 0, 0);
}
3.3 灰度滤镜
灰度滤镜可以通过将每个像素的R、G、B值取平均值实现。具体代码如下:
grayscaleImage() {
for (let i = 0; i < this.imageData.data.length; i += 4) {
const avg = (this.imageData.data[i] + this.imageData.data[i + 1] + this.imageData.data[i + 2]) / 3;
this.imageData.data[i] = avg;
this.imageData.data[i + 1] = avg;
this.imageData.data[i + 2] = avg;
}
this.ctx.putImageData(this.imageData, 0, 0);
}
3.4 调整色温
如果想要通过滤镜调整图片的色温,可以使用下面的代码:
adjustTemperature(value) {
const newRedMatrix = [
1 + 0.10 * value, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 - 0.10 * value,
];
for (let i = 0; i < this.imageData.data.length; i += 4) {
const [r, g, b] = [this.imageData.data[i], this.imageData.data[i + 1], this.imageData.data[i + 2]];
this.imageData.data[i] = Math.round(r * newRedMatrix[0] + g * newRedMatrix[1] + b * newRedMatrix[2]);
this.imageData.data[i + 1] = Math.round(r * newRedMatrix[3] + g * newRedMatrix[4] + b * newRedMatrix[5]);
this.imageData.data[i + 2] = Math.round(r * newRedMatrix[6] + g * newRedMatrix[7] + b * newRedMatrix[8]);
}
this.ctx.putImageData(this.imageData, 0, 0);
}
这里使用的是一个线性变换newRedMatrix
,可以将红色通道的值增加或减少一定比例。如果想要增加色温,则增加红色通道的值,同时减少蓝色通道的值,反之则亦然。
4. 结语
本文介绍了如何使用Vue.js和Canvas实现图片的颜色调整和滤镜效果。使用Canvas可以轻松实现常见的图像处理操作,不仅能够提供更好的用户体验、更加直观的操作,而且还能够显著提高网站的性能。