前端处理图片的N中方式

前言

在前端开发的世界里,图片处理和优化是至关重要的一环。本文章浅析了图片处理的多个方面,包括灰度处理、抠图去除背景、证件照一键换背景、图像编辑器以及canvas海报等。此外,还探讨了图片压缩的各种手段,并通过sharp、webpack和oss等示例演示了实际应用。对于图片格式和兼容性的了解,以及小图处理与SVG的应用,也在本文章中得到详细的讨论。无论你是新手还是经验丰富的前端开发者,这里都有你需要的技术指南,助你在图像处理的道路上更进一步。

1、图片处理

1、灰度处理

图片灰度处理的意义:

  • 简化图像、提高性能:将彩色图像转换为灰度图像可以简化图像的信息表示。灰度图像只有一个通道,每个像素的值表示亮度,因此比彩色图像更加简洁。这可以减少图像处理的复杂度,并降低存储和传输的成本。
  • 色彩失真不敏感+提取关键特征: 在某些图像处理任务中,彩色信息可能不是必要的,而只需关注图像的亮度信息。例如,人脸识别算法通常使用灰度图像进行特征提取,因为亮度信息对于人脸的结构和纹理更具有表达能。灰度图像不受彩色信息的影响,因此对色彩变化更不敏感。在某些图像处理任务中,如边缘检测、图像增强等,灰度图像可以更好地保留图像的结构和细节,而不受颜色变化的干扰, 如:医学影像领域。
  • 对于视力障碍者来说,灰度处理有利于他们更好的看世界

在线demo

JS 复制代码
// 文件输入框变化时的事件监听器
document.getElementById("imageInput").addEventListener("change", handleImage);

function handleImage(e) {
  // 获取选择的文件
  const fileInput = e.target;
  const file = fileInput.files[0];

  if (file) {
    // 创建FileReader以读取所选图像
    const reader = new FileReader();

    // 读取器完成读取时的事件处理程序
    reader.onload = function (e) {
      // 获取对原始图像和灰度画布的引用
      const originalImage = document.getElementById("originalImage");
      originalImage.src = e.target.result;

      const grayscaleCanvas = document.getElementById("grayscaleCanvas");
      const ctx = grayscaleCanvas.getContext("2d");

      // 原始图像加载完成时的事件处理程序
      originalImage.onload = function () {
        // 将灰度画布的尺寸设置为原始图像的尺寸
        grayscaleCanvas.width = originalImage.width;
        grayscaleCanvas.height = originalImage.height;

        // 在灰度画布上绘制原始图像
        ctx.drawImage(
          originalImage,
          0,
          0,
          originalImage.width,
          originalImage.height
        );

        // 获取灰度图像的图像数据
        const imageData = ctx.getImageData(
          0,
          0,
          originalImage.width,
          originalImage.height
        );
        const data = imageData.data;

        // 将每个像素的颜色值取平均,实现灰度效果
        for (let i = 0; i < data.length; i += 4) {
          const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
          data[i] = data[i + 1] = data[i + 2] = avg;
        }

        // // 最大值法
        // for (let i = 0; i < data.length; i += 4) {
        //   const maxVal = Math.max(data[i], data[i + 1], data[i + 2]);
        //   data[i] = data[i + 1] = data[i + 2] = Math.min(255, maxVal);
        // }

        // // 加权平均值法:
        // const Wr = 0.3; // Weight for red
        // const Wg = 0.59; // Weight for green
        // const Wb = 0.11; // Weight for blue

        // for (let i = 0; i < data.length; i += 4) {
        //   const weightedAvg =
        //     (data[i] * Wr + data[i + 1] * Wg + data[i + 2] * Wb) /
        //     (Wr + Wg + Wb);
        //   data[i] =
        //     data[i + 1] =
        //     data[i + 2] =
        //       Math.min(255, Math.max(0, weightedAvg));
        // }


        // 将处理后的图像数据放回灰度画布
        ctx.putImageData(imageData, 0, 0);

        // 显示原始图像和灰度画布
        originalImage.style.display = "block";
        grayscaleCanvas.style.display = "block";
      };
    };

    // 读取文件数据URL
    reader.readAsDataURL(file);
  }
}

注:关于图片灰度转换的6种算法,这里使用了平均值算法

2、扩展(抠图去除背景)

在线demo

这里借助了三方api: removebg,Cloud-Hosted Background Image Remover

js 复制代码
 // 发送POST请求到remove.bg的API
fetch("https://api.remove.bg/v1.0/removebg", {
  method: "POST",
  headers: {
    "X-Api-Key": "XXXXXX", // 替换成你自己的Remove.bg API密钥
  },
  body: formData,
})

3、扩展(证件照一键换背景)

在线demo

到这里就水到渠成,整体思路是:详细代码见上面👆demo

4、扩展(图像编辑器)

在线demo

借助:tui-image-editor

5、扩展(canvas海报)

2、图片压缩

根据 HTTP ARCHIVE 的统计,网站静态资源传输数据中位数为 2.5MB 左右,而其中图片传输数据的中位数在 1MB 左右。

1、压缩手段

2、demo演示

1、sharp:

sharp压缩服务端

sharp压缩客户端

压缩效果:

⚠️注意:sahrp存在的问题

2、wepack:

四个压缩工具

3、oss

oss阿里云图片处理

js 复制代码
// 伪代码展示
// 定义一个支持图片处理的 React Component
function CDNImage(path, width, height) {
 // 如果是 DataURL,则直接返回图片
 if (path.startsWith("data")) {
   return <img src={path} />;
 }
 // 这里的xxxx为域名
 const avifSrc = `https://xxxx/${path}?x-oss-process=image/format,avif/quality,Q_75/resize,w_${width},h_${height}`;
 const webPSrc = `https://xxxx/${path}?x-oss-process=image/format,webp/quality,Q_75/resize,w_${width},h_${height}`;
 const src = `https://xxxx/${path}`;
 return (
   <picture>
     <source srcSet={avifSrc} type="image/avif" />
     <source srcSet={webpSrc} type="image/webp" />
     <img src={src} width={width} height={height} loading="lazy" />
   </picture>
 );
}

// 使用它
import hello from "./hello.png";
<CDNImage path={hello} width={100} height={100} />;

3、图片格式+兼容性

从存储和表示图像的方式来划分,主要为两类:

  • 矢量图: 使用数学公式来描述图像。图像由一系列的点、线、曲线等数学对象组成,因此无论放大还是缩小,图像都能保持较高的质量。
  • 位图:由像素阵列组成的图像。每个像素都有自己的颜色信息,因此在缩放时可能会失去一些图像质量。

矢量图典型: SVG(Scalable Vector Graphics)

位图(bitmap):常见的图片格式 GIF、JPEG、PNG、WEBP 和 AVIF 都属于位图

位图格式的图片相同质量的情况下,他们的体积大小不同,一般来说: jpeg,png,webp,avif 依次减小

根据 webp and avif comparison 文章,针对相同质量的 jpeg,webp 减少了 30% 的体积(中位数),而 avif 减少了 50% 的体积。

综上,avif 拥有更小的体积,但为什么没大量使用呢?在于它的浏览器的兼容性,目前只有86%的支持率:

处理兼容性 : 在前端项目中,我们一般通过 img 标签来表示图片,但基于兼容性影响,可以考试使用picture,它可以根据浏览器对图片格式的支持情况,来降级处理。如此一来,它即使不支持 avif 图片格式,也可以优雅地降级到 webp 甚至 jpeg

html 复制代码
<picture>
  <source srcset="shanyue-hello.avif" type="image/avif">
  <source srcset="shanyue-hello.webp" type="image/webp">
  <img src="shanyue-hello.jpeg">
</picture>

4、小图处理与svg

在前端性能优化中,常有一项是将小图片转化为 DataURL,转化为 DataURL 虽然无法使得图片体积减小,但是可以使得图片地址内联,减少了 HTTP 请求次数

DataUrl组成规范

从上可知:

  • DataURL 并不仅可代表图片,他同样也可代表其它所有文件类型,比如音视频,Markdown,HTML 等,只要你给出了对应的 MIME Type。
  • DataURL 并不仅可由 base64 表示,它也可以使用纯文本表示,比如 HTML。只有二进制的资源,如 jpeg/avif 等二进制资源必须使用 base64 表示。
html 复制代码
data:text/html,lots of text...<p><a name%3D"bottom">bottom</a>?arg=val</p>

// 转换前:
lots of text...
<p><a name="bottom">bottom</a>?arg=val</p>

webpack处理小图:

在 webpack 5 中,可使用 asset 模块对小图片进行处理。

json 复制代码
{
 module: {
    rules: [
      {
        test: /.(jpg|png|avif)/,
        type: 'asset',
        parser: {
          // 对小于 4kb 的图片进行 DataURL 处理
          dataUrlCondition: {
            maxSize: 4 * 1024
          }
        }
      }
    ]
  },
};

注意,以上 asset 仅对二进制图片进行了处理,而无对 svg 这种文本图片进行处理。因为 SVG 为文本格式,使用 base64 编码反而使其体积增大了 30%,而文本格式并不必使用 base64 编码。

处理SVG:

在官方示例中,对 svg 生成 DataURL 时进行了额外的处理。使用了 mini-svg-data-uri,而 源码 也极其简单,仅有几十行,核心功能是 URLEncode 以及字符串,引号等的处理

javascript 复制代码
// mini-svg-data-uri demo
const path = require('path');
const svgToMiniDataURI = require('mini-svg-data-uri');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /.svg/,
        type: 'asset/inline',
        generator: {
          dataUrl: content => {
            content = content.toString();
            return svgToMiniDataURI(content);
          }
        }
      }
    ]
  },
};

end❤️

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax