我试图在移动设备上调整图片大小。 (使用离子2框架,基于角度2)。
我的最大文件大小为5MB,有些设备捕获的图像大于此值。所以我目前正在尝试使用canvas.toDataURL()
调整图片大小,但这非常慢。 (应用程序没有响应15-20秒)。
我目前的调整大小功能如下:
private resize(outputFormat, sourceImgObj, quality) {
let mimeType = "image/jpeg";
let cvs = document.createElement('canvas');
cvs.width = sourceImgObj.naturalWidth;
cvs.height = sourceImgObj.naturalHeight;
let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0);
let newImageData = cvs.toDataURL(mimeType, quality/100);
return newImageData;
}
当时的(我相信)基于j-i-c,如果不相同的话。
此功能确实有效。在浏览器中它很不错但仍然很慢(Chrome)。但是当在设备上运行此功能时,例如选择8 MB的图像,应用程序将基本崩溃。
有没有办法更快地压缩/调整图像大小?
其他信息
我使用cordova-plugin-camera获取文件本身,{{3}}是用户设备上文件的直接链接。所以这不是base64图像(但我可以在必要时轻松获得)。
答案 0 :(得分:2)
您的调整大小功能确实命名错误。它的作用是改变jpeg有损算法的质量。它并没有真正调整你的图像大小,我想你的8MB图像非常大,如果它来自设备相机,压缩可能已经相当不错了。
因此,当您在画布上绘制它时,实际上是在生成一个新的原始图像(没有任何压缩),其像素数量与原始文件相同。
这意味着您的画布本身将比内存中的原始8MB大。当调用toDataURL时,它必须提取这些数据,处理它等,吃掉更多的内存。
它甚至不确定最后你会得到一个更轻的档案......
如果您可以真正调整图像大小(即更改尺寸),那么您的设备将更容易处理它:
function resize(sourceImgObj) {
const mimeType = "image/jpeg"; // would probably be better to keep the one of the file...
let quality = .92; // default;
const cvs = document.createElement('canvas');
const MAX_SIZE = 500; // in px for both height and width
const w = sourceImgObj.naturalWidth;
const h = sourceImgObj.naturalHeight;
let ratio = MAX_SIZE / Math.max(w, h);
if(ratio > 1){ // if it's smaller than our defined MAX_SIZE
ratio = 1;
quality = .5; // lower the jpeg quality
}
cvs.width = ratio * w;
cvs.height = ratio * h;
let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0, cvs.width, cvs.height);
// note : if it's not a problem to convert it to async then toBlob would be a better choice
let newImageData = cvs.toDataURL(mimeType, quality);
return newImageData;
}
inp.onchange = e => {
const MAX_SIZE = 100000; // 100KB
let img = new Image();
img.src = URL.createObjectURL(inp.files[0]);
img.onload = e => {
// if it's not too big, return the image's current src
let dataURL = (inp.files[0].size > MAX_SIZE) ?
resize(img) : img.src;
let out = new Image();
out.src = dataURL;
document.body.appendChild(out);
};
}
<input type="file" id="inp">
编辑(ivaro18)
我只想添加我的修改版本的答案。我不喜欢将质量参数降低到50%,所以我坚持使用比率并根据我的需要进行修改。这将在600毫秒内将8.1MB图像调整为900kB。
resize(sourceImgObj, callback) {
const mimeType = "image/jpeg";
let quality = .92; // default;
const cvs = document.createElement('canvas');
const MAX_SIZE = 1024; // in px for both height and width
const w = sourceImgObj.naturalWidth;
const h = sourceImgObj.naturalHeight;
let ratio = MAX_SIZE / Math.max(w, h);
if(ratio > 1) {
let percentage = (w >= h) ? ((w - MAX_SIZE) / w * 100) : ((h - MAX_SIZE) / h * 100);
cvs.width = (percentage + 100)/100 * w;
cvs.height = (percentage + 100)/100 * h;
} else {
cvs.width = w * ratio;
cvs.height = h * ratio;
}
let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0, cvs.width, cvs.height);
let newImageData = cvs.toDataURL(mimeType, quality);
callback(newImageData);
}
答案 1 :(得分:0)
如果压缩的唯一目的是减小文件大小,那么您可以在拍摄照片时在插件的配置中指定图像质量。
您可以尝试多种不同的值,看看哪种最适合您。
https://github.com/apache/cordova-plugin-camera#cameracameraoptions--object
答案 2 :(得分:0)
已经有一个用于执行此操作的库,无需重新发明轮子