前言
在现代网络应用中,图像处理是一项重要的任务,尤其是在需要展示用户上传的图片时。但是,经常会面临两个主要问题:图像大小和图像安全。一方面,大尺寸的图片会增加加载时间,降低用户体验,另一方面,保护图片免受盗用或篡改是至关重要的。在本文中,我们将讨论如何通过前端技术来解决这些问题,具体而言,我们将关注图像的压缩和水印添加。
/** * 堆代码 duidaima.com * 将图像文件压缩以减小其大小。 * @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对象,解析为压缩后的图像文件。主要步骤包括:
/** * 添加水印到图片 * @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对象。主要步骤包括: