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

压缩和水印

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

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

图像压缩

大多数现代浏览器都支持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...

效果

相关推荐
Watermelo61717 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
一个处女座的程序猿O(∩_∩)O2 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
燃先生._.8 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖9 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
black^sugar10 小时前
纯前端实现更新检测
开发语言·前端·javascript
2401_8576009512 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_8576009512 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL12 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
小白学大数据12 小时前
如何使用Selenium处理JavaScript动态加载的内容?
大数据·javascript·爬虫·selenium·测试工具