TL;DR;
有没有办法在上传之前直接在浏览器端压缩图像(主要是jpeg,png和gif)?我很确定JavaScript可以做到这一点,但我找不到实现它的方法 .
这是我想要实现的完整场景:
-
用户访问我的网站,并通过
input type="file"
元素选择图像, -
此图片是通过JavaScript检索的,我们会做一些验证,例如正确的文件格式,最大文件大小等,
-
如果一切正常,页面上会显示图像的预览,
-
用户可以进行一些基本操作,例如将图像旋转90°/ -90°,按照预定义的比例裁剪等,或者用户可以上传另一张图像并返回步骤1,
-
当用户满意时,编辑后的图像会被压缩并在本地"saved"(不保存到文件中,但在浏览器内存/页面中), -
-
用户填写表格,其中包含姓名,年龄等数据,
-
用户点击"Finish"按钮,然后将包含数据压缩图像的表单发送到服务器(不带AJAX),
直到最后一步的完整过程应该在客户端完成,并且应该与最新的Chrome和Firefox,Safari 5和 IE 8+ 兼容 . 如果可能,只应使用JavaScript(但我很确定这是不可能的) .
我已经考虑过了 . 可以通过File API在本地读取文件,可以使用Canvas元素进行图像预览和编辑,但是 I can't find a way to do the image compression part .
根据html5please.com和caniuse.com,支持这些浏览器非常困难(感谢IE),但可以使用FlashCanvas和FileReader之类的polyfill来完成 .
实际上,目标是减小文件大小,因此我将图像压缩视为一种解决方案 . 但是,我知道上传的图像将在我的网站上显示,每次都在同一个地方,我知道这个显示区域的尺寸(例如200x400) . 因此,我可以调整图像大小以适应这些尺寸,从而减小文件大小 . 我不知道这种技术的压缩比是多少 .
你怎么看 ?你有什么建议告诉我吗?你知道在JavaScript中压缩图像浏览器的方法吗?谢谢你的回复 .
6 回答
编辑:根据Mr Me对此答案的评论,看起来压缩现在可用于JPG / WebP格式(请参阅https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL) .
据我所知,你无法使用画布压缩图像,相反,你可以调整它的大小 . 使用canvas.toDataURL不会让您选择要使用的压缩率 . 您可以查看完全符合您要求的canimage:https://github.com/nfroidure/CanImage/blob/master/chrome/canimage/content/canimage.js
实际上,通常只需调整图像大小以减小其大小即可,但如果您想要更进一步,则必须使用新引入的方法file.readAsArrayBuffer来获取包含图像数据的缓冲区 .
然后,只需使用DataView根据图像格式规范(http://en.wikipedia.org/wiki/JPEG或http://en.wikipedia.org/wiki/Portable_Network_Graphics)读取其内容 .
处理图像数据压缩会很困难,但尝试更糟糕 . 另一方面,您可以尝试删除PNG标头或JPEG exif数据以使图像更小,这样做应该更容易 .
您必须在另一个缓冲区上创建另一个DataWiew,并用过滤后的图像内容填充它 . 然后,您只需使用window.btoa将图像内容编码为DataURI .
让我知道如果你实现类似的东西,将通过代码将是有趣的 .
@PsychoWoods的回答很好 . 我想提供自己的解决方案 . 此Javascript函数获取图像数据URL和宽度,将其缩放到新宽度,并返回新的数据URL .
此代码可以在您拥有数据URL的任何地方使用,并且需要缩小图像的数据URL .
简而言之:
使用带有.readAsArrayBuffer的HTML5 FileReader API读取文件
使用文件数据创建e Blob并使用window.URL.createObjectURL(blob)获取其URL
创建新的Image元素并将其src设置为文件blob url
将图像发送到画布 . 画布大小设置为所需的输出大小
通过canvas.toDataURL("image/jpeg",0.7)从画布返回缩小的数据(设置您自己的输出格式和质量)
将新的隐藏输入附加到原始表单,并将dataURI图像基本上作为普通文本传输
在后端,读取dataURI,从Base64解码,然后保存
资料来源:code .
上面由@ daniel-allen-langdon发布的
downscaleImage()
函数存在一个问题,因为图像加载是 asynchronous ,image.width
和image.height
属性不能立即使用 .请参阅下面更新的TypeScript示例,该示例将此考虑在内,使用
async
函数,并根据最长维度调整图像大小,而不仅仅是宽度我看到其他答案中缺少两件事:
canvas.toBlob
(如果可用)比canvas.toDataURL
更高效,也是异步 .该文件 - >图像 - >画布 - >文件转换丢失EXIF数据;特别是,关于图像旋转的数据通常由现代手机/平板电脑设定 .
以下脚本处理这两点:
用法示例:
对于JPG图像压缩,您可以使用称为JIC(Javascript图像压缩)的最佳压缩技术 . 这肯定会帮助您 - > https://github.com/brunobar79/J-I-C