【发布时间】:2018-07-15 21:25:49
【问题描述】:
我是一名服务器端开发人员,学习客户端操作的技巧,从纯 JS 开始。
目前我正在使用纯 JS 来调整通过浏览器上传的图像的尺寸。
我遇到了一种情况,将 1018 x 1529 .jpg 文件缩小到 400 x 601 .jpeg 会产生更大尺寸(以字节为单位)的文件。它从70013 字节到74823 字节。
我的期望是应该缩小规模,而不是通货膨胀。这是怎么回事,有什么办法可以解决这种情况吗?
注意:让我特别困惑的一点是,每个图像的压缩都是在没有事先了解目标之前的压缩的情况下开始的。因此,任何低于 100 的质量水平都会进一步降低图像质量。这应该相应地始终减小文件大小。但奇怪的是没有发生?
如果需要,我的相关JS代码是:
var max_img_width = 400;
var wranges = [max_img_width, Math.round(0.8*max_img_width), Math.round(0.6*max_img_width),Math.round(0.4*max_img_width),Math.round(0.2*max_img_width)];
function prep_image(img_src, text, img_name, target_action, callback) {
var img = document.createElement('img');
var fr = new FileReader();
fr.onload = function(){
var dataURL = fr.result;
img.onload = function() {
img_width = this.width;
img_height = this.height;
img_to_send = resize_and_compress(this, img_width, img_height, "image/jpeg");
callback(text, img_name, target_action, img_to_send);
}
img.src = dataURL;
};
fr.readAsDataURL(img_src);
}
function resize_and_compress(source_img, img_width, img_height, mime_type){
var new_width;
switch (true) {
case img_width < wranges[4]:
new_width = wranges[4];
break;
case img_width < wranges[3]:
new_width = wranges[4];
break;
case img_width < wranges[2]:
new_width = wranges[3];
break;
case img_width < wranges[1]:
new_width = wranges[2];
break;
case img_width < wranges[0]:
new_width = wranges[1];
break;
default:
new_width = wranges[0];
break;
}
var wpercent = (new_width/img_width);
var new_height = Math.round(img_height*wpercent);
var canvas = document.createElement('canvas');//supported
canvas.width = new_width;
canvas.height = new_height;
var ctx = canvas.getContext("2d");
ctx.drawImage(source_img, 0, 0, new_width, new_height);
return dataURItoBlob(canvas.toDataURL(mime_type),mime_type);
}
// converting image data uri to a blob object
function dataURItoBlob(dataURI,mime_type) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);//supported
for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); }
return new Blob([ab], { type: mime_type });
}
如果有必要,这是我使用的测试图片:
Here's图片的原始位置。
请注意,对于我尝试过的其他几个图像,代码的行为确实符合预期。它并不总是把结果搞砸,但现在我不能确定它是否总是有效。在这个问题的范围内,让我们坚持使用纯 JS 解决方案。
【问题讨论】:
-
链接的问答将为您提供解决方法。如果我有时间,我会尝试为这个骗局添加一个更全面的答案,但基本上,当你在画布上绘制 jpeg 时,你也会绘制 JPEG 工件
-
@Kaiido:在那个骗子中尝试的唯一答案是要求该人使用
encoderOptions参数来设置质量。就我而言,我还是将其保留为默认设置。 -
这就是你的问题。您的问题仍然相同,了解 JPEG 有损压缩的工作原理 + 了解为什么在画布上绘制有损 JPEG 会产生更多信息 + 了解为什么更大的质量选项会产生更大的 JPEG 文件大小。所以我认为一个人可以在一篇文章中回答这两个问题 => 欺骗。
-
@Kaiido:然后归结为 - 是否可以检测输入图像的
encoderOptions设置(在处理之前)?这是实现苹果对苹果比较(和调整大小)的一种方法。 -
不是真的...即使有一种方法可以检测所使用的质量级别,当绘制到画布上时,您将从原始像素数据重新开始,除了所有已被被 JPEG 算法丢弃的将被人工制品取代。无法从创建 jpeg 版本的原始图像开始。因此,您将不得不从这些工件中创建更多工件。但如果你能等几个小时,我会尝试为目标提供更全面的答案。
标签: javascript