bonus-material-app/src/services/utils/imageUtils.js

198 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 图片处理工具类
class ImageUtils {
/**
* 将图片转换为Base64字符串相当于Android的bitmapToString
* @param {string} imagePath 图片路径
* @param {number} quality 压缩质量 0-100
* @returns {Promise<string>} Base64字符串
*/
static async imageToBase64(imagePath, quality = 50) {
try {
// 如果已经是base64格式直接返回数据部分
if (imagePath.startsWith("data:image/")) {
return imagePath.split(",")[1]
}
// 如果是纯base64字符串直接返回
if (!imagePath.includes("/") && !imagePath.includes("\\")) {
return imagePath
}
// 压缩图片
const compressResult = await new Promise((resolve, reject) => {
window.uni.compressImage({
src: imagePath,
quality: quality,
success: resolve,
fail: reject,
})
})
// 读取压缩后的文件并转换为base64
const fileManager = window.uni.getFileSystemManager()
const base64Data = await new Promise((resolve, reject) => {
fileManager.readFile({
filePath: compressResult.tempFilePath,
encoding: "base64",
success: (res) => resolve(res.data),
fail: reject,
})
})
return base64Data
} catch (error) {
console.error("Image to base64 conversion failed:", error)
throw error
}
}
/**
* 获取缩放后的图片相当于Android的getSmallBitmap
* @param {string} imagePath 图片路径
* @param {number} maxWidth 最大宽度
* @param {number} maxHeight 最大高度
* @returns {Promise<string>} 处理后的图片路径
*/
static async getSmallImage(imagePath, maxWidth = 1024, maxHeight = 1024) {
try {
return await this.resizeImageWithCanvas(imagePath, maxWidth, maxHeight)
} catch (error) {
console.error("Get small image failed:", error)
// 如果canvas方法失败尝试使用压缩API
return await this.fallbackCompress(imagePath, maxWidth, maxHeight)
}
}
/**
* 使用Canvas调整图片尺寸
* @param {string} imagePath 图片路径
* @param {number} maxWidth 最大宽度
* @param {number} maxHeight 最大高度
* @returns {Promise<string>} 处理后的图片路径
*/
static async resizeImageWithCanvas(imagePath, maxWidth, maxHeight) {
return new Promise((resolve, reject) => {
// 获取图片信息
window.uni.getImageInfo({
src: imagePath,
success: (imageInfo) => {
const { width, height } = imageInfo
// 计算缩放比例
const scale = this.calculateScale(width, height, maxWidth, maxHeight)
const newWidth = Math.floor(width * scale)
const newHeight = Math.floor(height * scale)
// 如果不需要缩放,直接返回原图
if (scale >= 1) {
resolve(imagePath)
return
}
// 创建canvas上下文
const canvasId = "imageProcessCanvas_" + Date.now()
const ctx = window.uni.createCanvasContext(canvasId)
// 绘制缩放后的图片
ctx.drawImage(imagePath, 0, 0, newWidth, newHeight)
ctx.draw(false, () => {
// 导出canvas为临时文件
window.uni.canvasToTempFilePath({
canvasId: canvasId,
fileType: "jpg",
quality: 0.8,
success: (res) => {
resolve(res.tempFilePath)
},
fail: reject,
})
})
},
fail: reject,
})
})
}
/**
* 备用压缩方法
* @param {string} imagePath 图片路径
* @param {number} maxWidth 最大宽度
* @param {number} maxHeight 最大高度
* @returns {Promise<string>} 处理后的图片路径
*/
static async fallbackCompress(imagePath, maxWidth, maxHeight) {
return new Promise((resolve, reject) => {
window.uni.compressImage({
src: imagePath,
quality: 80,
compressedWidth: maxWidth,
compressedHeight: maxHeight,
success: (res) => resolve(res.tempFilePath),
fail: reject,
})
})
}
/**
* 计算缩放比例相当于Android的calculateInSampleSize
* @param {number} originalWidth 原始宽度
* @param {number} originalHeight 原始高度
* @param {number} maxWidth 最大宽度
* @param {number} maxHeight 最大高度
* @returns {number} 缩放比例
*/
static calculateScale(originalWidth, originalHeight, maxWidth, maxHeight) {
if (originalWidth <= maxWidth && originalHeight <= maxHeight) {
return 1 // 不需要缩放
}
const widthScale = maxWidth / originalWidth
const heightScale = maxHeight / originalHeight
// 选择较小的缩放比例,确保图片完全适应限制尺寸
return Math.min(widthScale, heightScale)
}
/**
* 批量处理图片
* @param {string} imagePath 图片路径
* @param {object} options 处理选项
* @returns {Promise<string>} 处理后的Base64字符串
*/
static async processImage(imagePath, options = {}) {
const { maxWidth = 1024, maxHeight = 1024, quality = 50, outputFormat = "base64" } = options
try {
// 1. 先缩放图片
const resizedImagePath = await this.getSmallImage(imagePath, maxWidth, maxHeight)
// 2. 根据输出格式返回结果
if (outputFormat === "base64") {
return await this.imageToBase64(resizedImagePath, quality)
} else {
return resizedImagePath
}
} catch (error) {
console.error("Process image failed:", error)
throw error
}
}
/**
* 获取图片尺寸信息
* @param {string} imagePath 图片路径
* @returns {Promise<object>} 图片信息
*/
static async getImageInfo(imagePath) {
return new Promise((resolve, reject) => {
window.uni.getImageInfo({
src: imagePath,
success: resolve,
fail: reject,
})
})
}
}
export default ImageUtils