更新记录
1.0.0(2025-07-07)
初版
平台兼容性
云函数类插件通用教程
使用云函数类插件的前提是:使用HBuilderX 2.9+
使用说明
概述
基于 Sharp 的高性能图片处理库,提供了完整的图片压缩、缩略图生成、水印添加等功能。支持批量处理、并发控制、内存监控、进度追踪等高级特性。
特性
- 多格式支持:JPEG、PNG、WebP
- 智能压缩:根据图片尺寸自动调整参数
- 批量处理:支持并发批量处理
- 内存监控:防止内存溢出
- 进度追踪:实时监控处理进度
- 缓存机制:提升重复处理性能
- 预设配置:内置多种压缩预设
- 错误处理:完善的错误处理机制
安装 (在 /uni_modules/x-image-processor/uniCloud/cloudfunctions/common/x-image-processor 目录下)
npm install sharp
基本使用
1. 初始化处理器
const { ImageProcessor } = require('x-image-processor');
// 使用默认配置
const processor = new ImageProcessor();
// 使用自定义配置
const processor = new ImageProcessor({
concurrency: 8, // 并发数
maxMemoryUsage: 512 * 1024 * 1024, // 最大内存使用 512MB
enableCache: true, // 启用缓存
cacheSize: 200, // 缓存大小
defaultQuality: 85, // 默认质量
preserveExif: false, // 保留EXIF信息
progressCallback: (progress) => {
console.log(`处理进度: ${progress.percentage}%`);
}
});
2. 单图片压缩
// 压缩到内存
const compressedBuffer = await processor.compress('input.jpg', {
quality: 80,
format: 'jpeg',
resize: {
width: 1200,
height: 800,
fit: 'inside',
withoutEnlargement: true
}
});
// 压缩并保存到文件
const result = await processor.compressToFile('input.jpg', 'output.jpg', {
quality: 80,
format: 'jpeg'
});
console.log(`压缩率: ${result.compressionRatio}`);
console.log(`节省空间: ${result.savedBytes} bytes`);
3. 批量处理
// 批量压缩到内存
const inputs = [
'image1.jpg',
'image2.png',
{ input: 'image3.jpg', options: { quality: 90 } }
];
const results = await processor.batchCompressToBuffer(inputs, {
quality: 80,
format: 'jpeg'
});
results.forEach(result => {
if (result.success) {
console.log(`${result.input} 压缩成功, 压缩率: ${result.compressionRatio}`);
} else {
console.error(`${result.input} 压缩失败: ${result.error}`);
}
});
// 批量压缩到文件
const fileInputs = [
{ input: 'image1.jpg', output: 'compressed/image1.jpg' },
{ input: 'image2.png', output: 'compressed/image2.jpg', options: { quality: 90 } }
];
const fileResults = await processor.batchCompressToFile(fileInputs, {
quality: 80,
format: 'jpeg'
});
4. 使用预设
// 使用内置预设
const thumbnail = await processor.compressWithPreset('input.jpg', 'thumbnail');
const webOptimized = await processor.compressWithPreset('input.jpg', 'web');
const printQuality = await processor.compressWithPreset('input.jpg', 'print');
const mobileOptimized = await processor.compressWithPreset('input.jpg', 'mobile');
// 添加自定义预设
processor.addPreset('custom', {
quality: 75,
format: 'webp',
resize: { width: 800, height: 600, fit: 'cover' }
});
const customResult = await processor.compressWithPreset('input.jpg', 'custom');
5. 智能压缩
// 根据图片尺寸自动调整参数
const smartCompressed = await processor.smartCompress('input.jpg', {
format: 'jpeg'
});
高级功能
1. 缩略图生成
const thumbnail = await processor.generateThumbnail('input.jpg', {
width: 200,
height: 200,
fit: 'cover', // 'cover', 'contain', 'fill', 'inside', 'outside'
position: 'center', // 'center', 'top', 'bottom', 'left', 'right'
format: 'jpeg',
quality: 80
});
2. 添加水印
const watermarked = await processor.addWatermark('input.jpg', 'watermark.png', {
gravity: 'southeast', // 'north', 'northeast', 'east', 'southeast', 'south', 'southwest', 'west', 'northwest', 'center'
opacity: 0.5, // 透明度 0-1
blend: 'over' // 混合模式
});
// 自定义位置
const customWatermark = await processor.addWatermark('input.jpg', 'watermark.png', {
left: 50,
top: 50,
opacity: 0.7
});
3. 获取图片信息
const info = await processor.getImageInfo('input.jpg');
console.log(info);
/*
{
width: 1920,
height: 1080,
format: 'jpeg',
size: 245760,
density: 72,
channels: 3,
hasAlpha: false,
space: 'srgb'
}
*/
4. 内存监控
const memoryInfo = processor.getMemoryInfo();
console.log(`内存使用: ${memoryInfo.percentage}%`);
console.log(`已用内存: ${(memoryInfo.used / 1024 / 1024).toFixed(2)}MB`);
配置选项
压缩选项
const options = {
quality: 80, // 质量 1-100
format: 'jpeg', // 'jpeg', 'png', 'webp'
progressive: true, // 渐进式JPEG
resize: {
width: 1200,
height: 800,
fit: 'inside', // 'cover', 'contain', 'fill', 'inside', 'outside'
withoutEnlargement: true // 不放大图片
},
preserveExif: false // 保留EXIF数据
};
内置预设
预设名称 | 用途 | 配置 |
---|---|---|
thumbnail | 缩略图 | 200x200, 质量80, JPEG |
web | 网页优化 | 1200x800, 质量85, WebP |
打印质量 | 3000x2000, 质量95, JPEG | |
mobile | 移动端优化 | 750x500, 质量70, JPEG |
处理器配置
const config = {
concurrency: 4, // 并发数量
maxMemoryUsage: 256 * 1024 * 1024, // 最大内存使用
tempDir: './temp', // 临时目录
enableCache: true, // 启用缓存
cacheSize: 100, // 缓存大小
defaultQuality: 80, // 默认质量
preserveExif: false, // 保留EXIF
progressCallback: null // 进度回调
};
错误处理
const { ImageProcessingError, ERROR_CODES } = require('x-image-processor');
try {
const result = await processor.compress('input.jpg');
} catch (error) {
if (error instanceof ImageProcessingError) {
console.error(`处理错误: ${error.message}`);
console.error(`错误代码: ${error.code}`);
console.error(`发生时间: ${error.timestamp}`);
switch (error.code) {
case ERROR_CODES.FILE_NOT_FOUND:
console.error('文件不存在');
break;
case ERROR_CODES.INVALID_FORMAT:
console.error('不支持的格式');
break;
case ERROR_CODES.MEMORY_LIMIT_EXCEEDED:
console.error('内存使用超限');
break;
// 其他错误处理...
}
}
}
最佳实践
1. 并发控制
// 根据系统性能调整并发数
const processor = new ImageProcessor({
concurrency: require('os').cpus().length
});
2. 内存管理
// 定期检查内存使用
setInterval(() => {
const memInfo = processor.getMemoryInfo();
if (parseFloat(memInfo.percentage) > 80) {
console.warn('内存使用过高:', memInfo.percentage + '%');
processor.clearCache(); // 清理缓存
}
}, 30000);
3. 批量处理优化
// 大批量处理时分批进行
const chunkSize = 50;
const allFiles = [...]; // 所有文件
for (let i = 0; i < allFiles.length; i += chunkSize) {
const chunk = allFiles.slice(i, i + chunkSize);
const results = await processor.batchCompressToFile(chunk);
// 处理结果
results.forEach(result => {
if (!result.success) {
console.error(`处理失败: ${result.input} - ${result.error}`);
}
});
// 短暂等待,避免内存压力
await new Promise(resolve => setTimeout(resolve, 100));
}
4. 资源清理
// 应用退出时清理资源
process.on('exit', async () => {
await processor.cleanup();
});
process.on('SIGINT', async () => {
await processor.cleanup();
process.exit(0);
});
性能优化建议
- 合理设置并发数:通常设置为 CPU 核心数的 1-2 倍
- 启用缓存:对于重复处理的图片,缓存可以显著提升性能
- 监控内存使用:定期检查并清理内存,防止内存泄漏
- 选择合适的格式:WebP 通常比 JPEG 有更好的压缩率
- 批量处理:尽量使用批量处理 API,减少单次调用开销
注意事项
- 文件大小限制:单个文件最大 50MB
- 图片尺寸限制:最大 8192x8192 像素
- 内存使用:处理大图片时会消耗较多内存
- 格式支持:目前支持 JPEG、PNG、WebP 格式
- 水印透明度:水印功能需要 PNG 格式的透明图片效果更佳
示例代码
完整的图片处理流程
const { ImageProcessor } = require('x-image-processor');
const path = require('path');
async function processImages() {
const processor = new ImageProcessor({
concurrency: 4,
enableCache: true,
progressCallback: (progress) => {
console.log(`处理进度: ${progress.completed}/${progress.total} (${progress.percentage}%)`);
}
});
try {
// 1. 单图片处理
const singleResult = await processor.compressToFile(
'input/large-image.jpg',
'output/compressed-image.jpg',
{ quality: 80, format: 'jpeg' }
);
console.log('单图片压缩完成:', singleResult.compressionRatio);
// 2. 批量处理
const batchInputs = [
{ input: 'input/image1.jpg', output: 'output/image1.jpg' },
{ input: 'input/image2.png', output: 'output/image2.jpg' },
{ input: 'input/image3.jpg', output: 'output/image3.webp', options: { format: 'webp' } }
];
const batchResults = await processor.batchCompressToFile(batchInputs, {
quality: 85,
format: 'jpeg'
});
// 3. 生成缩略图
const thumbnailBuffer = await processor.generateThumbnail('input/large-image.jpg', {
width: 300,
height: 300,
fit: 'cover'
});
// 4. 添加水印
const watermarkedBuffer = await processor.addWatermark(
'input/photo.jpg',
'assets/watermark.png',
{ gravity: 'southeast', opacity: 0.4 }
);
// 5. 智能压缩
const smartCompressed = await processor.smartCompress('input/huge-image.jpg');
console.log('所有处理完成');
console.log('内存使用:', processor.getMemoryInfo());
} catch (error) {
console.error('处理失败:', error.message);
} finally {
await processor.cleanup();
}
}
processImages();