canvas压缩图片的原理

本文介绍了前端压缩图片的原理(其实服务端也可以处理图片,因为图片的本质只是数据而已,图片的展示才是前端范畴),比如大名鼎鼎的OpenCV和java中的Java Advanced Imaging (JAI)以及nodejs中的sharp模块。毕竟数据的处理是服务端最擅长的,前端擅长的是渲染展示。而服务端一般没有ui渲染这方面的负担。

1、 OpenCV:OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理、分析和计算机视觉功能。它支持多种编程语言,包括 C++、Python、Java 等。

2、 Java Advanced Imaging (JAI):JAI 是 Java 平台上的一个图像处理库,提供了高性能的图像处理和分析功能,包括图像缩放、旋转、过滤、分割等。

3、 sharp:sharp 是一个高性能的 Node.js 图像处理库,它支持对图片进行缩放、裁剪、旋转、调整尺寸、变换格式等操作。由于 sharp 使用 libvips(一个轻量级的图像处理库)作为后端,因此在处理大尺寸图片时具有较高的性能。

本文主要介绍前端是如何通过canvas来处理图片的!!(图像的处理本质是通过一些算法处理特定的数据)

前端压缩图片与服务端压缩图片的区别

  1. 处理环境:
    前端压缩图片:前端图片压缩是在用户的浏览器环境中进行的,通常使用 JavaScript 和 HTML5 Canvas 等技术实现。这意味着压缩过程是在用户设备上进行的,可以减少服务器的负载和带宽消耗,但也受到客户端设备性能和浏览器支持的限制。
    服务端压缩图片:服务端图片压缩是在服务器端进行的,通常在后端代码中使用特定的图像处理库或工具实现。这样可以利用服务器的计算资源和存储空间,适用于处理大规模图片或需要复杂处理的场景。

  2. 处理方式:
    前端压缩图片:前端图片压缩通常是通过调整图片尺寸和/或图像质量来实现的。在客户端环境中,可以使用 Canvas API 或第三方图像处理库来进行压缩操作。
    服务端压缩图片:服务端图片压缩可以使用各种图像处理库或工具来实现,例如 ImageMagick、GraphicsMagick、Sharp 等。这些库提供了丰富的图像处理功能,可以进行更复杂的处理操作,如裁剪、旋转、滤镜等。

  3. 适用场景:
    前端压缩图片:前端图片压缩适用于需要在用户设备上进行实时处理或交互式操作的场景,如上传图片、裁剪图片、生成缩略图等。它可以减少服务器负载,提高用户体验,并且可以根据用户设备的性能和需求进行定制化处理。
    服务端压缩图片:服务端图片压缩适用于需要在服务器端进行批量处理或复杂处理的场景,如图像处理流程、图片存储和管理系统等。它可以利用服务器的计算资源和存储空间,实现更复杂的图像处理功能,并适用于大规模图片处理和高并发访问。

综上所述,前端压缩图片和服务端压缩图片在处理环境、处理方式和适用场景等方面存在一些区别,开发者可以根据具体需求选择合适的方式进行图片压缩,一般情况比如上传头像到服务器可以在前端进行压缩,减少网络带宽压力。

canvas压缩图片的原理

Canvas 压缩图片的原理主要涉及以下步骤:

  1. 加载图片到 Canvas:首先,将要压缩的图片加载到 HTML5 的 Canvas 元素中。这可以通过创建一个新的 Image 对象,然后设置其 src 属性为图片的 URL,并在图片加载完成后将其绘制到 Canvas 上。

  2. 调整尺寸:一旦图片加载到 Canvas 上,可以通过设置 Canvas 的宽度和高度来调整图片的尺寸。通常情况下,压缩图片时会将其尺寸缩小到所需的大小。这可以通过设置 Canvas 元素的 width 和 height 属性来实现。

  3. 绘制图片:接下来,使用 Canvas 的绘图 API(如 drawImage() 方法)将原始图片绘制到调整尺寸后的 Canvas 上。这将把图片按照指定的尺寸绘制在 Canvas 上。

  4. 导出压缩后的图片:最后,可以使用 Canvas 的 toDataURL() 方法将压缩后的图片导出为数据 URL。数据 URL 包含了整个图片的 Base64 编码字符串,可以直接用于在网页中显示图片,或者将其发送到服务器端进行保存。

通过以上步骤,可以在客户端使用 Canvas 对图片进行压缩处理,以减小图片文件的大小,从而加快图片加载速度和节省带宽资源。

toDataURL怎么用

toDataURL() 方法用于将 Canvas 中的内容导出为一个 data URL。这个 data URL 可以直接用作图片的源,也可以用于将图片数据发送到服务器等用途。以下是使用 toDataURL() 方法的简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 获取 Canvas 元素
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// 绘制图片到 Canvas
var img = new Image();
img.onload = function() {
// 将图片绘制到 Canvas 上
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

// 导出 Canvas 中的内容为 data URL
var dataURL = canvas.toDataURL('image/jpeg'); // 默认为 PNG 格式,可以指定其他格式
console.log(dataURL);

// 在页面中显示导出的图片
var exportedImage = document.getElementById('exportedImage');
exportedImage.src = dataURL;
};
img.src = 'path/to/your/image.jpg'; // 图片路径

在上面的示例中:

  1. 首先获取了一个 Canvas 元素,并获取了它的 2D 绘图上下文。

  2. 创建了一个新的 Image 对象,并设置了它的 onload 事件处理函数。这个函数在图片加载完成后执行。

  3. 在图片加载完成后,将图片绘制到 Canvas 上,然后使用 toDataURL() 方法将 Canvas 中的内容导出为 data URL。在这里,我们指定了图片的格式为 JPEG,你也可以选择其他格式,比如 PNG。

  4. 最后,将导出的图片显示在页面上,或者将数据 URL 发送到服务器端进行保存等操作。

这样就完成了将 Canvas 中的内容导出为 data URL 的过程。

canvas.toDataURL有几个参数

canvas.toDataURL() 方法有两个可选参数:

type:指定导出图片的类型,默认为 “image/png”。可以传入 “image/jpeg”、”image/webp” 等值。如果指定的格式不被支持,则会使用默认格式 “image/png”。
encoderOptions:在指定图片格式为 “image/jpeg” 或 “image/webp” 时,可以通过该参数来指定图像质量。其取值范围在 0 到 1 之间,表示导出的图片质量,1 表示最高质量,0 表示最低质量。这个参数只在部分浏览器中受支持,如果不支持,会被忽略。
例如:

1
var dataURL = canvas.toDataURL('image/jpeg', 0.8);

这里将图片格式指定为 JPEG,并设置了图像质量为 0.8

图片质量表示什么

图片质量表示图像的清晰度和细节保留程度。在压缩图片时,通常会调整图像的质量来平衡图像文件大小和视觉质量之间的关系。

对于基于损失的压缩格式(如 JPEG),降低图像质量会导致图像中一些细节的丢失,但可以减小文件大小。这是因为 JPEG 使用了有损压缩算法,它通过减少图像中的一些细微变化来实现压缩,从而牺牲了一定程度的图像质量。

一般而言,图像质量的数值范围在 0 到 1 之间,1 表示最高质量,0 表示最低质量。较高的质量值意味着更多的细节被保留,但也导致文件大小更大;而较低的质量值则会导致更多的细节丢失,但文件大小会更小。选择合适的图像质量取决于具体的应用场景,需要权衡图像的清晰度和文件大小之间的需求。

图片压缩是通过设置宽度和高度还是通过canvas.toDataURL的第二个参数

图片压缩通常是通过两种方式来实现的:调整图片尺寸(宽度和高度)和调整图像质量。这两种方式都可以用于减小图片文件大小,但它们的原理和效果略有不同。

1、调整图片尺寸:通过设置图片的宽度和高度来调整图像的尺寸。减小图片的尺寸可以直接减小图片文件的大小,因为更少的像素意味着更少的数据需要存储。在客户端,可以将图片加载到 Canvas 中,然后设置 Canvas 的宽度和高度,最后将调整尺寸后的图片导出为 data URL。这种方法可以在一定程度上减小图片文件大小,但可能会影响图像的清晰度和细节。

2、调整图像质量:通过调整图像的质量来减小图片文件大小。在使用 JPEG 格式保存图片时,可以通过设置图像质量参数来控制压缩级别。较低的图像质量会导致更多的细节丢失,但文件大小更小。在使用 canvas.toDataURL() 方法导出图片时,可以通过第二个参数 encoderOptions 来指定 JPEG 图像的质量,从而实现压缩。这种方法不会改变图片的尺寸,但会影响图像的清晰度和细节。

综上所述,调整图片尺寸和调整图像质量都是常用的图片压缩方法,可以根据具体的需求选择合适的方式进行压缩。

encoderOptions 的原理

encoderOptions 参数的原理可以更具体地解释如下:

1、JPEG 压缩:当使用 canvas.toDataURL(‘image/jpeg’) 方法导出 JPEG 格式的图片时,可以通过设置 encoderOptions 参数来调整 JPEG 图片的压缩质量。这个参数的值在 0 到 1 之间,0 表示最低质量(最大压缩),1 表示最高质量(无损压缩)。较高的质量值会导致生成的 JPEG 图片质量更高,但文件大小也更大,而较低的质量值则会导致更大的压缩比和更小的文件大小,但也会损失图像细节和清晰度。

2、WebP 压缩:类似地,当使用 canvas.toDataURL(‘image/webp’) 方法导出 WebP 格式的图片时,也可以通过设置 encoderOptions 参数来调整图像的压缩质量。WebP 是一种先进的图像格式,通常可以实现比 JPEG 更好的压缩率和图像质量。通过调整 encoderOptions 参数,可以控制生成的 WebP 图片的质量,使其符合特定的需求,例如平衡图像质量和文件大小之间的关系。

总之,encoderOptions 参数提供了一个灵活的方式来控制在使用 Canvas 导出 JPEG 或 WebP 图片时的压缩质量,使开发者能够根据具体的应用场景和需求来选择合适的压缩级别。

浏览器底层是如何压缩的

浏览器在底层对图片进行压缩时,通常会使用特定的压缩算法来减小图像文件的大小,而尽量保持图像的视觉质量。不同的浏览器可能会使用不同的算法,但主要的压缩技术包括有损压缩和无损压缩。

1、有损压缩:常见的有损压缩格式包括 JPEG。在有损压缩中,一些图像信息会被丢弃以减小文件大小,这样可以降低图像的清晰度和细节,但通常不会对人眼可见的图像质量产生明显影响。有损压缩算法通常会根据图像中的像素值和颜色分布等特征来确定丢弃哪些信息,并使用变换、量化和熵编码等技术来实现压缩。

2、无损压缩:常见的无损压缩格式包括 PNG 和 WebP(无损模式)。在无损压缩中,图像的每个像素都会被精确地保留,不会丢失任何信息。无损压缩算法通常会利用图像中的重复模式和冗余信息来实现压缩,例如使用预测编码和差分编码来表示图像中的像素差异。

在实际压缩过程中,浏览器会根据用户设定的参数(例如图片质量、压缩级别)以及图片的特性(如分辨率、色彩深度、内容复杂度)来选择合适的压缩算法和参数。通常情况下,浏览器会尽可能地减小文件大小,同时保持图像在浏览器中的显示质量。

总的来说,浏览器在底层对图片进行压缩时会应用各种压缩技术和算法,以实现尽可能小的文件大小和较好的图像质量。

两种压缩方式的区别

两种压缩方式(调整图片尺寸和调整图像质量)在实现上有一些关键区别:

1、调整图片尺寸:

原理:这种方式通过减小图片的宽度和高度来减少像素数量,从而降低了图像文件的大小。这会直接影响图像的分辨率和尺寸,但不会改变图像的内容或细节。
影响:由于减少了像素数量,因此文件大小会相应减小,加载速度也会加快。但缩小尺寸可能会导致图像在显示时出现失真或模糊,特别是在较大的缩放比例下。
2、调整图像质量:

原理:这种方式通过调整图像的压缩质量来减小文件大小。在 JPEG 格式中,可以通过减少压缩质量来降低图像的文件大小,而在 WebP 格式中,可以通过调整压缩参数来实现类似的效果。
影响:降低压缩质量会导致图像文件大小减小,但也会引起图像的细节丢失和视觉质量下降。通常情况下,较低的压缩质量会导致更明显的失真和压缩伪影,特别是在图像中包含细节丰富的区域时。
综合来看,调整图片尺寸主要影响图像的尺寸和加载速度,而调整图像质量则主要影响图像的视觉质量和文件大小。在实际应用中,需要根据具体的需求和场景来选择合适的压缩方式,以平衡图像的质量和文件大小。

简单案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片压缩示例</title>
</head>
<body>
<h1>图片压缩示例</h1>
<input type="file" id="imageInput" accept="image/*">
<br>
<button onclick="compressImage()">压缩图片</button>
<br>
<h2>原始图片</h2>
<img id="originalImage" src="" alt="Original Image" style="max-width: 100%;">
<h2>压缩后的图片</h2>
<img id="compressedImage" src="" alt="Compressed Image" style="max-width: 100%; display: none;">
<script>
function compressImage() {
var input = document.getElementById('imageInput');
var originalImage = document.getElementById('originalImage');
var compressedImage = document.getElementById('compressedImage');

var file = input.files[0];
if (!file) {
alert('请先选择一张图片!');
return;
}

var reader = new FileReader();
reader.onload = function(e) {
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var maxWidth = 800; // 最大宽度
var maxHeight = 600; // 最大高度
var quality = 0.7; // 图片质量

var width = img.width;
var height = img.height;
if (width > maxWidth || height > maxHeight) {
if (width / maxWidth > height / maxHeight) {
height *= maxWidth / width;
width = maxWidth;
} else {
width *= maxHeight / height;
height = maxHeight;
}
}

canvas.width = width;
canvas.height = height;

ctx.drawImage(img, 0, 0, width, height);
var dataURL = canvas.toDataURL('image/jpeg', quality);
console.log("压缩后图片的 data URL 长度:", dataURL.length);
// 将 data URL 转换为 Blob 对象
var blob = dataURItoBlob(dataURL);
console.log("压缩后图片的 Blob 对象大小:", blob.size);
originalImage.src = e.target.result;
compressedImage.src = dataURL;
compressedImage.style.display = 'inline';
};
img.src = e.target.result;

};
reader.readAsDataURL(file);
console.log('压缩前:',file.size)
}
// 将 data URL 转换为 Blob 对象的函数
function dataURItoBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: mimeString });
}
</script>
</body>
</html>
压缩前后对比
压缩前后对比

canvas压缩图片的原理
https://zbdev.online/2024/04/06/canvas压缩图片的原理/
作者
zzb
发布于
2024年4月6日
许可协议