在web应用中,图片通常是必不可少的一部分,我们经常需要处理图片。但是,图片往往比较大,导致加载时间较长。因此,我们需要对图片进行压缩,以减小文件大小,同时保证图片的质量。本文将介绍如何使用canvas和openCV.js来压缩图片。
一、使用Canvas压缩图片
一种压缩图片的方法是使用HTML5的canvas元素。canvas元素允许您在网页上绘制图形和图片。要使用canvas压缩图片,您可以将图片绘制到canvas元素上,然后将canvas导出为压缩后的图片。
1.压缩原理
使用canvas压缩图片的底层原理是将原始图片的像素数据读取到内存中,然后使用canvas的2D上下文对象将像素数据绘制到canvas元素上。在绘制时,可以通过调整canvas的大小来压缩图片的尺寸,从而减小文件大小。此外,可以通过调整toBlob方法的第三个参数来控制压缩质量,进一步减小文件大小。最终,使用toBlob方法将canvas元素上绘制的结果转换为Blob对象,即压缩后的图片。
2.代码实现
实现步骤如下:
- 使用FileReader对象读取文件内容。
- 当文件内容读取完成后,将其作为src传递给Image对象,并将其加载到内存中。
- 当图像加载完成后,创建一个canvas元素,并使用2D上下文对象将图像绘制到canvas元素上。
- 调整canvas的大小以压缩图片,并使用toBlob方法将canvas元素上的图像转换为Blob对象。
函数compressWithCanvas接受四个参数:文件对象、最大宽度、最大高度和压缩质量。该函数返回一个promise对象,该对象在压缩完成时解析为Blob对象。
以下是使用canvas压缩图片的完整代码实现:
const compressWithCanvas = async (file, maxWidth, maxHeight, quality) => {
try {
const dataUrl = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
const img = await new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = (error) => reject(error);
img.src = dataUrl;
});
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
let width = img.width;
let height = img.height;
if (width > height) {
if (width > maxWidth) {
height *= maxWidth / width;
width = maxWidth;
}
} else {
if (height > maxHeight) {
width *= maxHeight / height;
height = maxHeight;
}
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
const blob = await new Promise((resolve) => {
canvas.toBlob((blob) => resolve(blob), file.type, quality);
});
return blob;
} catch (error) {
throw error;
}
};
将文件、最大宽度、最大高度和质量作为参数传递。函数将返回一个Promise对象,该对象在压缩完成时解析为Blob对象。以下是使用此函数的示例代码:
//调用compressWithCanvas方法
const file = document.getElementById('input').files[0];
const maxWidth = 800;
const maxHeight = 600;
const quality = 0.7;
compressWithCanvas(file, maxWidth, maxHeight, quality)
.then((blob) => {
// Do something with the compressed image blob
})
.catch((error) => {
// Handle any errors that occurred during compression
});
二、使用openCV.js压缩图片
另一种压缩图片的方法是使用openCV.js。OpenCV.js是一个JavaScript库,可以在网络应用中使用OpenCV,一个流行的计算机视觉库。OpenCV.js提供了一个名为imencode的函数,可用于压缩图片。
1. 压缩原理
使用Uint8Array和arrayBuffer将文件内容读取到内存中,然后使用cv.imreadAsync将图像转换为矩阵。接着,使用cv.imencode函数压缩图像,并将压缩后的数据转换为Blob对象,最后返回该对象。
cv.imreadAsync函数用于将图像数据读取到内存中,并转换为OpenCV中的矩阵格式。该函数接受一个Uint8Array类型的参数,该参数包含图像数据。函数返回一个Promise对象,该对象在读取完成后解析为OpenCV中的Mat对象。
cv.imencode函数用于压缩图像并将其转换为Blob对象。该函数接受四个参数:文件扩展名、输入图像、输出缓冲区和压缩参数。输出缓冲区是一个Mat对象,用于存储压缩后的图像数据。压缩参数是一个数组,用于指定压缩选项。例如,可以使用[cv.IMWRITE_JPEG_QUALITY, quality]来指定JPEG格式的压缩质量。该函数返回一个布尔值,表示是否成功压缩图像。
2. 代码实现
使用openCV.js压缩图片的实现步骤如下:
- 加载openCV.js
- 使用
Uint8Array和arrayBuffer将文件内容读取到内存中。 - 使用
cv.imreadAsync将图像转换为矩阵。 - 使用
cv.imencode函数压缩图像。可以通过更改函数的参数来调整压缩级别。参数越高,图片的压缩程度越小,文件大小越大。 - 将压缩后的数据转换为Blob对象。
以下是使用openCV.js压缩图片的完整代码实现:
在代码中加载 opencv.js :
<script async src="<https://docs.opencv.org/master/opencv.js>" type="text/javascript">
</script>
在这里,JavaScript文件的URL是 https://docs.opencv.org/master/opencv.js。下载和加载该文件可能需要一些时间。然后,您可以调用 cv.imreadAsync 和 cv.imencode 等函数来完成图像的压缩处理。
const compressWithOpenCV = async (file, quality) => {
try {
const imgData = new Uint8Array(await file.arrayBuffer());
const img = await cv.imreadAsync(imgData);
const result = new cv.Mat();
cv.imencode('.jpg', img, result, [cv.IMWRITE_JPEG_QUALITY, quality]);
const blob = new Blob([result.data], { type: 'image/jpeg' });
img.delete();
result.delete();
return blob;
} catch (error) {
throw error;
}
};
其中,file是要压缩的文件,quality是压缩质量,通常在0到100之间。函数将返回一个Promise对象,该对象在压缩完成时解析为Blob对象。
调用compressWithOpenCV方法:
try {
const file = document.getElementById('input').files[0];
const quality = 80;
const blob = await compressWithOpenCV(file, quality);
// 处理压缩后的图片blob对象
} catch (error) {
// 处理压缩过程中的错误
}
三、两种压缩方法的优缺点
在选择压缩图片的方法时,需要考虑应用程序的具体要求和限制条件。如果只需要简单地压缩JPEG和PNG格式的图片,使用canvas是一个不错的选择。如果需要处理各种格式的图片,并且需要更细致地控制压缩质量,使用openCV.js是一个更好的选择。
-
使用Canvas压缩图片
使用canvas压缩图片的优点是它是HTML5的标准元素,无需任何库或框架即可使用。此外,它的使用非常简单,只需要几行代码即可完成压缩。
它的缺点是它只能压缩JPEG和PNG格式的图像,虽然Canvas可以使用
toBlob方法将图像转换为Blob对象,但是它的压缩质量受到浏览器支持的限制,无法进行更细致的控制。 -
使用openCV.js压缩图片
使用openCV.js压缩图片的优点是它可以处理各种格式的图像,包括JPEG、PNG和BMP等常见格式,还支持其他一些图像格式TIFF (.tif, .tiff)和WebP (.webp)等。此外,它提供了更多的压缩选项,可以更细致地控制压缩质量。
它的缺点是它需要加载一个较大的JavaScript库,因此它可能不适合于需要快速加载的应用程序。不支持直接压缩GIF格式的图片,如果需要压缩GIF格式的图片,需要考虑使用其他库或工具来处理。
四、写在文末
随着人工智能和机器学习技术的不断发展,图片压缩技术也可以更加智能化。例如,可以使用机器学习算法来自动识别和压缩不同类型的图像,以提高压缩效率和质量。这些新技术和算法将使图片压缩技术更加智能化和自动化,为应用提供更好的用户体验。