gift/unpackage/dist/dev/mp-weixin/common/utils.js
2025-07-31 20:06:59 +08:00

174 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.

"use strict";
const common_vendor = require("./vendor.js");
const getFileSize = async (filePath) => {
try {
const res = await new Promise((resolve, reject) => {
common_vendor.wx$1.getFileSystemManager().getFileInfo({
filePath,
success: resolve,
fail: reject
});
});
return res.size || Infinity;
} catch (err) {
common_vendor.index.__f__("error", "at common/utils.js:34", "获取文件大小失败:", err);
return Infinity;
}
};
const doCompressImage = (src, quality) => {
return new Promise((resolve) => {
common_vendor.index.compressImage({
src,
quality,
success: (res) => resolve(res.tempFilePath),
fail: () => resolve(src)
// 失败返回原路径
});
});
};
const preciseCompress = async (tempFilePath, targetSize = 500 * 1024, initialQuality = 85) => {
let quality = initialQuality;
let compressedPath = tempFilePath;
let currentSize = Infinity;
let iterations = 0;
const maxIterations = 10;
const history = [];
const originalSize = await getFileSize(tempFilePath);
if (originalSize <= targetSize) {
return { path: tempFilePath, quality: 100, iterations: 0, finalSize: originalSize };
}
const predictQualityRange = (originalSize2, targetSize2) => {
const ratio = targetSize2 / originalSize2;
if (ratio > 0.8)
return { low: 70, high: 95 };
if (ratio > 0.5)
return { low: 45, high: 75 };
if (ratio > 0.3)
return { low: 25, high: 50 };
if (ratio > 0.1)
return { low: 10, high: 30 };
return { low: 5, high: 15 };
};
const { low: predictedLow, high: predictedHigh } = predictQualityRange(originalSize, targetSize);
let low = predictedLow;
let high = Math.min(predictedHigh, initialQuality);
common_vendor.index.__f__("log", "at common/utils.js:132", `预测质量范围: ${low}-${high} (原图${(originalSize / 1024).toFixed(2)}KB → 目标${(targetSize / 1024).toFixed(2)}KB)`);
const adjustBounds = (currentQuality, currentSize2, targetSize2) => {
const sizeRatio = currentSize2 / targetSize2;
const qualityDelta = Math.max(2, Math.floor(currentQuality * 0.1));
if (sizeRatio > 2.5) {
return { lowDelta: -qualityDelta * 2, highDelta: -qualityDelta };
} else if (sizeRatio > 1.5) {
return { lowDelta: -qualityDelta, highDelta: -Math.floor(qualityDelta / 2) };
} else if (sizeRatio > 1.1) {
return { lowDelta: -3, highDelta: -1 };
} else {
return { lowDelta: -1, highDelta: 0 };
}
};
let bestResult = null;
while (iterations < maxIterations && low <= high) {
iterations++;
quality = Math.floor((low + high) / 2);
if (history.some((item) => item.quality === quality)) {
break;
}
compressedPath = await doCompressImage(tempFilePath, quality);
currentSize = await getFileSize(compressedPath);
history.push({ quality, size: currentSize });
common_vendor.index.__f__("log", "at common/utils.js:165", `${iterations}次尝试: quality=${quality}${(currentSize / 1024).toFixed(2)}KB (目标${(targetSize / 1024).toFixed(2)}KB)`);
if (!bestResult || Math.abs(currentSize - targetSize) < Math.abs(bestResult.size - targetSize)) {
bestResult = { quality, size: currentSize, path: compressedPath };
}
if (Math.abs(currentSize - targetSize) < targetSize * 0.03) {
common_vendor.index.__f__("log", "at common/utils.js:174", "✅ 达到精准匹配,提前结束");
break;
}
if (currentSize > targetSize) {
const { lowDelta, highDelta } = adjustBounds(quality, currentSize, targetSize);
high = Math.max(5, quality + highDelta);
} else {
low = quality + 1;
}
if (high - low <= 1)
break;
}
if (bestResult && bestResult.size > targetSize * 1.1) {
common_vendor.index.__f__("log", "at common/utils.js:191", "🔥 尝试极限压缩...");
const extremePath = await doCompressImage(tempFilePath, 5);
const extremeSize = await getFileSize(extremePath);
common_vendor.index.__f__("log", "at common/utils.js:194", `极限压缩结果: quality=5 → ${(extremeSize / 1024).toFixed(2)}KB`);
if (extremeSize < bestResult.size) {
bestResult = { quality: 5, size: extremeSize, path: extremePath };
}
}
const finalResult = bestResult || { quality: 10, size: currentSize, path: compressedPath };
common_vendor.index.__f__("log", "at common/utils.js:203", `🎯 最终结果quality=${finalResult.quality}${(finalResult.size / 1024).toFixed(2)}KB迭代${iterations}次,压缩率${((1 - finalResult.size / originalSize) * 100).toFixed(1)}%`);
return {
path: finalResult.path,
quality: finalResult.quality,
iterations,
finalSize: finalResult.size
};
};
const imageToBase64 = (filePath) => {
return new Promise((resolve, reject) => {
common_vendor.index.getImageInfo({
src: filePath,
success: (info) => {
const type = info.type || "jpeg";
common_vendor.index.getFileSystemManager().readFile({
filePath,
encoding: "base64",
success: (res) => resolve(`data:image/${type};base64,${res.data}`),
fail: reject
});
},
fail: () => {
common_vendor.index.getFileSystemManager().readFile({
filePath,
encoding: "base64",
success: (res) => resolve(`data:image/jpeg;base64,${res.data}`),
fail: reject
});
}
});
});
};
const processImage = async (maxSize = 500 * 1024) => {
const chooseRes = await new Promise((resolve) => {
common_vendor.index.chooseImage({
count: 1,
sizeType: ["original", "compressed"],
success: resolve,
fail: () => resolve(null)
});
});
if (!chooseRes)
throw new Error("选择图片失败");
const tempFilePath = chooseRes.tempFilePaths[0];
let finalPath = tempFilePath;
let isCompressed = false;
const fileSize = await getFileSize(tempFilePath);
common_vendor.index.__f__("log", "at common/utils.js:272", `原图大小: ${(fileSize / 1024).toFixed(2)}KB`);
if (fileSize > maxSize) {
common_vendor.index.__f__("log", "at common/utils.js:276", "🔄 开始智能压缩...");
const compressResult = await preciseCompress(tempFilePath, maxSize);
finalPath = compressResult.path;
isCompressed = true;
common_vendor.index.__f__("log", "at common/utils.js:282", `✅ 压缩完成: ${(fileSize / 1024).toFixed(2)}KB → ${(compressResult.finalSize / 1024).toFixed(2)}KB (节省${((1 - compressResult.finalSize / fileSize) * 100).toFixed(1)}%)`);
}
const base64 = await imageToBase64(finalPath);
common_vendor.index.__f__("log", "at common/utils.js:288", `📄 Base64长度: ${base64.length} 字符`);
return {
base64,
// Base64字符串
path: finalPath,
// 最终文件路径(可能是原图或压缩图)
compressed: isCompressed
// 是否经过压缩
};
};
exports.processImage = processImage;
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/utils.js.map