图像水印和压缩的前端实现

压缩和水印

在现代网络应用中,图像处理是一项重要的任务,尤其是在需要展示用户上传的图片时。但是,经常会面临两个主要问题:图像大小和图像安全。一方面,大尺寸的图片会增加加载时间,降低用户体验,另一方面,保护图片免受盗用或篡改是至关重要的。

在本文中,我们将讨论如何通过前端技术来解决这些问题,具体而言,我们将关注图像的压缩和水印添加。

图像压缩

大多数现代浏览器都支持HTML5的<canvas>元素,它可以在客户端进行图像处理。我们可以利用这个特性来压缩用户上传的图片。

代码分析:

javascript 复制代码
/**
 * 将图像文件压缩以减小其大小。
 * @param {File} file - 要压缩的图像文件。
 * @param {number} maxSizeMB - 压缩后图像的最大大小,以兆字节为单位。
 * @returns {Promise<File>} 一个解析为压缩后图像文件的 Promise。
 */
compressImage(file, maxSizeMB) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();

    reader.onload = function () {
      let img = new Image();

      img.onload = function () {
        let canvas = document.createElement("canvas");
        let ctx = canvas.getContext("2d");
        let maxSizeBytes = maxSizeMB * 1024 * 1024;
        let scaleFactor = 0.5;

        if (file.size > maxSizeBytes) {
          scaleFactor = Math.min(
            scaleFactor,
            Math.sqrt(maxSizeBytes / file.size)
          ); // 计算缩放比例,保持宽高比
        }

        canvas.width = img.width * scaleFactor;
        canvas.height = img.height * scaleFactor;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

        canvas.toBlob(
          (blob) => {
            const compressedFile = new File([blob], file.name, {
              type: file.type,
              lastModified: Date.now(),
            });
            resolve(compressedFile);
          },
          file.type,
          0.8 // 设置压缩质量参数为 0.8
        );
      };

      img.onerror = reject;

      img.src = reader.result;
    };

    reader.onerror = reject;

    reader.readAsDataURL(file);
  });
},

这段代码实现了一个compressImage函数,它接受一个图像文件和最大允许大小作为参数,并返回一个Promise对象,解析为压缩后的图像文件。主要步骤包括:

  • 使用FileReader对象读取文件内容。
  • 将文件内容加载到<img>元素中。
  • 创建一个新的<canvas>元素,并将图像绘制到画布上。
  • 根据图像大小和指定的最大大小,计算压缩比例。
  • 将绘制后的图像数据转换为Blob对象,并返回压缩后的文件。

图像水印

为了标识图片的来源和保护版权,我们通常会添加水印。在本文中,我们使用HTML5的<canvas>元素来实现水印效果。

代码分析:

javascript 复制代码
/**
 * 添加水印到图片
 * @param {File} file 图片文件
 * @param {string} gasName 油站名称
 * @param {string} location 地址
 * @returns {Promise<Blob>} 返回添加水印后的 Blob 对象
 */
addWatermarkToImage(file, gasName, location) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.src = URL.createObjectURL(file);

    img.onload = () => {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d");

   
      const watermarkWidthPercentage = 0.9;

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

      ctx.drawImage(img, 0, 0);

     
      ctx.fillStyle = "rgba(0, 0, 0, 0.2)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

     
      const watermarkWidth = canvas.width * watermarkWidthPercentage;
      const watermarkX = (canvas.width - watermarkWidth) / 2; 

      const currentDate = new Date();
      const timeString = currentDate.toLocaleTimeString([], {
        hour: "2-digit",
        minute: "2-digit",
      });

      
      const dateString = currentDate.toLocaleDateString();
      const dayOfWeek = new Intl.DateTimeFormat("en-US", {
        weekday: "long",
      }).format(currentDate);
      CanvasUtils.drawText(
        ctx,
        `${dateString} ${dayOfWeek} ${timeString}`,
        CanvasUtils.calculateFontSize(watermarkWidth),
        CanvasUtils.calculateFontSize(watermarkWidth) * 2,
        watermarkX + watermarkWidth / 2
      );

     
      CanvasUtils.drawText(
        ctx,
        gasName,
        CanvasUtils.calculateFontSize(watermarkWidth),
        CanvasUtils.calculateFontSize(watermarkWidth) * 3.5,
        watermarkX + watermarkWidth / 2
      );

   
      CanvasUtils.drawText(
        ctx,
        location,
        CanvasUtils.calculateFontSize(watermarkWidth),
        CanvasUtils.calculateFontSize(watermarkWidth) * 5,
        watermarkX + watermarkWidth / 2
      );

      canvas.toBlob((blob) => {
        resolve(blob);
      }, file.type);
    };

    img.onerror = (error) => {
      reject(error);
    };
  });
},

这段代码实现了一个addWatermarkToImage函数,它接受一个图片文件和水印信息作为参数,并返回一个Promise对象,解析为添加水印后的Blob对象。主要步骤包括:

  • 加载图片并绘制到画布上。
  • 绘制一个半透明的矩形作为背景。
  • 在背景上添加日期、时间、油站名称和地址等信息。
  • 将绘制后的图像数据转换为Blob对象,并返回添加水印后的文件。

结论

通过前端技术,我们可以轻松地实现图像压缩和水印添加功能,从而改善用户体验和保护图像安全。本文提供了核心的代码分析和实现,希望能够帮助读者更好地理解图像处理的实现原理和技术细节。 完整代码:github.com/itc-1118/im...

效果

相关推荐
阿伟来咯~7 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端12 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱15 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai24 分钟前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨25 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry3 小时前
JS常用数组方法 reduce filter find forEach
javascript
ZL不懂前端3 小时前
Content Security Policy (CSP)
前端·javascript·面试