前端压缩图片-获取base64图片大小并根据情况选择压缩或者不压缩

项目场景:

前端展示图片的时候,不压缩展示,但是上传后端接口需要压缩,要求是200kb
如果图片大小在200kb以内就不压缩,如果大于200kb就压缩,压缩的时候我希望压缩比例最大为图片/200kb,最小压缩比例为0.8(不能)

问题描述

提示:这里描述项目中遇到的问题:

  1. 如何计算base图片文件大小
  2. 如何压缩
              // 计算图片大小
              const calculateSize = (base64Str: string) => {
                const base64Data = base64Str.split(",")[1] || "";
                const padding = (base64Data.match(/=/g) || []).length;
                return (base64Data.length * 3) / 4 - padding;
              };
              // 压缩图片方法
              const compressImage = (
                base64: string,
                quality: number,
                callback: any
              ) => {
                const img = new Image();
                img.onload = () => {
                  const canvas = document.createElement("canvas");
                  canvas.width = img.width;
                  canvas.height = img.height;
                  const ctx: any = canvas.getContext("2d");
                  ctx.fillStyle = "#fff";
                  ctx.fillRect(0, 0, canvas.width, canvas.height);
                  ctx.drawImage(img, 0, 0);
                  canvas.toBlob(
                    (blob: any) => {
                      const reader = new FileReader();
                      reader.onload = () => callback(reader.result);
                      reader.readAsDataURL(blob);
                    },
                    "image/jpeg",
                    quality
                  );
                };
                img.src = base64;
              };
              // 判断是否需要压缩,并确定压缩比例
              const currentSize = calculateSize(base64String);
              console.log("原始大小:", currentSize);
              if (currentSize > 200 * 1024) {
                let quality = (200 * 1024) / currentSize;
                quality = Math.max(0.8, quality);
                compressImage(
                  base64String,
                  quality,
                  (compressedBase64: string) => {
                    compressPhoto.value = compressedBase64;
                  }
                );
              } else {
                compressPhoto.value = base64String;
              }

计算图片大小-详解

              const calculateSize = (base64Str: string) => {
                const base64Data = base64Str.split(",")[1] || "";
                const padding = (base64Data.match(/=/g) || []).length;
                return (base64Data.length * 3) / 4 - padding;
              };

这段代码定义了一个名为 calculateSize 的函数,用于计算 Base64 编码字符串所表示的数据大小(以字节为单位)。以下是详细的解释:

  • 函数签名

    • const calculateSize = (base64Str: string) => { ... }: 定义了一个箭头函数 calculateSize,它接受一个参数 base64Str,该参数是一个 Base64 编码的字符串。
  • 提取 Base64 数据部分

    • const base64Data = base64Str.split(",")[1] || "":
      • 这行代码将传入的 Base64 字符串按照逗号 , 分割成数组。
      • 通常 Base64 编码的字符串前面会有一个 MIME 类型前缀,例如 data:image/png;base64,。通过 .split(",")[1] 可以获取到实际的 Base64 编码数据部分。
      • 如果没有逗号分隔的内容,则返回空字符串 ""
  • 计算填充字符的数量

    • const padding = (base64Data.match(/=/g) || []).length:
      • 使用正则表达式 /=/g 查找所有等于号 =,这些等于号是 Base64 编码中的填充字符。
      • 如果没有找到任何等于号,则返回空数组 [],然后计算其长度。
      • 填充字符用于确保 Base64 编码后的字符串长度是 4 的倍数。
  • 计算原始数据的大小

    • return (base64Data.length * 3) / 4 - padding:
      • Base64 编码将每 3 个字节的二进制数据转换为 4 个字符,因此 (base64Data.length * 3) / 4 计算出原始数据的字节数。
      • 减去 padding 是因为填充字符并不表示实际的数据,所以需要从总字节数中减去。

总结来说,这个函数的作用是根据 Base64 编码字符串计算出它所表示的原始数据的大小(以字节为单位),并返回这个大小值。

canvas.toBlob-详解

      canvas.toBlob(
                    (blob: any) => {
                      const reader = new FileReader();
                      reader.onload = () => callback(reader.result);
                      reader.readAsDataURL(blob);
                    },
                    "image/jpeg",
                    quality
                  );

这段代码使用了 HTML5 的 <canvas> 元素的 toBlob 方法,将 canvas 上绘制的内容转换为一个 Blob 对象,并通过 FileReader 将其读取为 Base64 编码的数据 URL。以下是详细的解释:

1. canvas.toBlob

  • 方法签名canvas.toBlob(callback, type, quality)
  • 参数
    • callback: 当 Blob 对象创建完成后调用的回调函数。
    • type: 指定生成的 Blob 对象的 MIME 类型(例如 "image/jpeg")。
    • quality: 图像的质量(仅对 JPEG 和 WebP 格式有效),范围是 0 到 1。

2. 回调函数

(blob: any) => {
  const reader = new FileReader();
  reader.onload = () => callback(reader.result);
  reader.readAsDataURL(blob);
}
2.1 创建 FileReader 实例
  • const reader = new FileReader();
    • 创建一个新的 FileReader 实例,用于读取文件或 Blob 对象。
2.2 设置 onload 事件处理程序
  • reader.onload = () => callback(reader.result);
    • FileReader 完成读取操作时触发 onload 事件。
    • reader.result 包含读取的结果,即 Base64 编码的字符串。
    • 调用外部传入的 callback 函数,并将 reader.result 作为参数传递给它。
2.3 读取 Blob 为 Data URL
  • reader.readAsDataURL(blob);
    • 使用 readAsDataURL 方法将 Blob 对象读取为 Base64 编码的数据 URL。
    • 这个方法会触发 onload 事件,当读取完成时执行相应的回调。

总结

这段代码的作用是将 canvas 上的内容转换为指定类型的图像(如 JPEG),并将其编码为 Base64 数据 URL。具体步骤如下:

  1. 使用 canvas.toBlob 方法将 canvas 内容转换为 Blob 对象。
  2. 使用 FileReader 读取 Blob 对象并将其转换为 Base64 编码的字符串。
  3. 当读取完成时,调用外部传入的 callback 函数,并将 Base64 编码的字符串作为参数传递给它。

这种方式常用于将 canvas 上绘制的图像保存为文件、上传到服务器或在页面中直接显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值