我正在尝试在移动设备上调整图像大小。(使用离子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插件相机获取文件本身,它是指向用户设备上文件的直接链接。所以这不是一个base64图像(但如有必要,我确实可以轻松获得一个(。
你的调整大小函数真的叫得不好。它的作用是更改 jpeg 有损算法的质量。它并没有真正调整您的图像大小,而且我想您的8MB图像非常大,如果它来自设备相机,压缩可能已经相当不错了。
因此,当您在画布上绘制它时,您实际上是在生成一个新的原始图像(没有任何压缩(,其像素数与原始文件中相同。
这意味着您的画布本身将比内存中的原始 8MB 大得多。当调用DataURL时,它将不得不提取这些数据,处理它等,消耗更多的内存。
甚至不确定最后你会得到一个更轻的文件......
如果您可以真正调整图像大小(即更改尺寸(,那么您的设备将更容易处理它:
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">
编辑 (伊瓦罗18(
我只是想添加这个答案的修改版本。我不喜欢将质量参数降低到 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);
}
如果压缩的唯一目的是减小文件大小,那么您可以在拍照时在插件的配置中指定图像质量。
您可以尝试几种不同的值,看看哪一个最适合您。
https://github.com/apache/cordova-plugin-camera#cameracameraoptions--object
已经有一个库可以做到这一点,无需重新发明轮子
https://www.npmjs.com/package/ngx-image-compress
你可以在这里尝试一下 https://stackblitz.com/edit/ngx-compress-sample