Javascript 通过纯JS缩小图像尺寸会导致图像大小膨胀(以字节为单位)

Javascript 通过纯JS缩小图像尺寸会导致图像大小膨胀(以字节为单位),javascript,Javascript,我是一名服务器端开发人员,从纯JS开始学习客户端操作的诀窍 目前,我正在使用纯JS调整通过浏览器上传的图像的尺寸 我遇到的情况是,将1018 x 1529.jpg文件缩小为400 x 601.jpeg会产生一个更大的文件(以字节为单位)。它从70013字节变为74823字节 我的期望是应该缩小规模,而不是通货膨胀。到底发生了什么,有什么办法来弥补这种情况吗 注意:有一点让我特别困惑,那就是每个图像的压缩都是在事先不知道目标先前压缩的情况下开始的。因此,任何低于100的质量级别都会进一步降低图像质

我是一名服务器端开发人员,从纯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 });
}
var max\u img\u 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)];
函数prep_映像(img_src、文本、img_名称、目标_操作、回调){
var img=document.createElement('img');
var fr=new FileReader();
fr.onload=函数(){
var dataURL=fr.result;
img.onload=函数(){
img_width=此宽度;
img_高度=此高度;
img_to_send=调整大小并压缩(即img_宽度、img_高度、“图像/jpeg”);
回调(文本、img\u名称、目标操作、img\u发送);
}
img.src=数据URL;
};
fr.readAsDataURL(img_src);
}
函数resize\u和\u compress(源\u img、img\u width、img\u height、mime\u type){
新宽度;
开关(真){
案例img_宽度
如果有保证,以下是我使用的测试图像:

图像的原始位置


请注意,对于我尝试的其他几个图像,代码的行为与预期一致。它并不总是把结果搞砸,但现在我不能确定它是否总是有效。对于这个问题的范围,让我们坚持使用纯JS解决方案。

这是一个建议,而不是一个真正的解决方案(或解决方案)

如果遇到此问题,请确保在完成调整大小操作后比较两个图像的文件大小。如果新文件较大,则只需返回到源映像即可

为什么画布不是缩小图像文件大小的最佳选项。 我不想谈太多细节,也不想深入解释,但我会尽力向你解释你遇到的基本情况

以下是一些您需要理解(至少部分理解)的概念

  • 什么是有损图像格式(如JPEG)
  • 在画布上绘制图像时会发生什么
  • 将画布图像导出为图像格式时会发生什么情况

. 图像格式可分为三类:

  • 原始图像格式
  • 无损图像格式(tiff、png、gif、bmp、webp…)
  • 有损图像格式(jpeg,…)
无损图像格式通常只需压缩表格中的数据,将像素颜色映射到使用该颜色的像素位置

另一方面,有损图像格式将丢弃信息并从原始图像生成数据(伪影)的近似值,以便使用较少的数据创建感知相似的图像渲染

近似(伪影)之所以有效,是因为解压算法知道它必须在给定区域上传播颜色信息,因此它不必保留每个像素的信息

但是,一旦算法处理了原始图像并生成了新图像,就无法找到丢失的数据


在画布上绘制图像。 在画布上绘制图像时,浏览器将图像信息转换为原始图像格式

它不会存储有关传递给它的图像格式的任何信息,并且在有损图像的情况下,工件中包含的每个像素都会像其他像素一样成为一等公民


导出画布图像 canvas 2D API有三种方法导出其原始数据:

  • 。它将返回原始像素RGBA值
  • 。它将同步应用与作为参数传递的MIME相对应的压缩算法
  • 。类似于
    toDataURL
    ,但异步
我们感兴趣的案例是
toDataURL
中的一个