gpt4 book ai didi

javascript - 调整 Canvas 质量以达到预定的图像文件大小

转载 作者:行者123 更新时间:2023-11-28 19:01:37 26 4
gpt4 key购买 nike

我想使用 Canvas 调整图像大小(例如,如果超出限制则减小文件大小)。我发现在 Canvas 上绘制的最终图像大小保持宽度和高度不变,会根据 Canvas 上绘制的内容产生不同的文件大小。

只要获得所需的文件大小,我愿意进一步降低分辨率。

如何确保无论分辨率如何,我获得的文件(图像)大小都在限制范围内?

引用this fiddle

var el = document.getElementById('f');

el.addEventListener('change', onChange);

function onChange(e) {
var file = this.files[0];

console.log("CHANGING");

var fr = new FileReader();
fr.onload = function(e) {
drawOnCanvas(e.target.result);
}
fr.readAsDataURL(file);
}


function drawOnCanvas(imgSrc) {
var canv = document.createElement('canvas'),
img = new Image();

console.log("DRAWING");

canv.width = canv.height = 500;
ctx = canv.getContext('2d');

img.onload = function() {
console.log("IMAGE LOADED");
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canv.width, canv.height);

try {
document.body.removeChild(document.querySelector('canvas'));
} catch (e) {}

document.body.appendChild(canv);

blob = canvasToFile(canv.toDataURL());

alert("FILE SIZE " + blob.size);
}

img.src = imgSrc;
}

function canvasToFile(dataUrl) {
var encData = dataUrl.split(',')[1],
binString = atob(encData),
binData = new Uint8Array(binString.length),
i, blob;

for (i = 0; i < binString.length; i++) {
binData[i] = binString.charCodeAt(i);
}

blob = new Blob([binData], {
type: 'image/jpeg'
});

return blob;
}
<p>Try uploading different image file and see the difference in size for same output resolution:</p>
<input type="file" id="f">

最佳答案

您遇到的是 canvas.toDataURL(type, encoderOptions) 的默认 type 参数是 image/png,而且它实际上是图像数据的 Base64 编码。

  • 对于前者,大多数浏览器都支持 image/jpeg 作为图像类型。由于 jpg 压缩,这可能会减少数据大小,但这首先会启用该方法的 encoderOptions 参数,该参数可以转换为质量参数,并且需要 0 到 1 的 float 。
    请注意,您不能确定转换为 jpg 后数据会更亮:如果图像主要由透明像素组成,则 png 会更亮。 此外,请记住 jpeg 压缩会降低图像质量,请参阅最后一个片段以了解 0 的结果:)

  • 对于后者(您可以找到原因的解释 here ),解决方案是将 dataURL 转换回 blob。

这是一个演示它的片段:

var input = document.querySelector('input');
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');

function draw(){
var img = new Image();
img.src = URL.createObjectURL(this.files[0]);
img.onload = function(){
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0,0);
var noData = canvas.toDataURL();
png_data.innerHTML = 'dataURL length: '+noData.length;
var noBlob = dataURItoBlob(noData);
png_blob.innerHTML = 'blob size: '+ noBlob.size;
var jpgData10 = canvas.toDataURL('image/jpeg', 1),
jpgData5 = canvas.toDataURL('image/jpeg', 0.5),
jpgData0 = canvas.toDataURL('image/jpeg', 0);
jpg_data.innerHTML = 'quality = 1 : '+ jpgData10.length+'<br>';
jpg_data.innerHTML += 'quality = 0.5 : '+ jpgData5.length+'<br>';
jpg_data.innerHTML += 'quality = 0 :'+ jpgData0.length+'<br>';
var jpgBlob10 = dataURItoBlob(jpgData10);
jpg_blob.innerHTML = 'blob quality = 1 : '+jpgBlob10.size+'<br>';
var jpgBlob5 = dataURItoBlob(jpgData5);
jpg_blob.innerHTML += 'blob quality = .5 : '+jpgBlob5.size+'<br>';
var jpgBlob0 = dataURItoBlob(jpgData0);
jpg_blob.innerHTML += 'blob quality = 0 : '+jpgBlob0.size;
}
this.previousElementSibling.innerHTML = 'orginal size : '+this.files[0].size;
}
input.onchange = draw;


// Taken from https://stackoverflow.com/a/5100158/3702797
function dataURItoBlob(dataURI) {
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
<div></div>
<input type="file"/>
<br>PNG :
<div id="png_data"></div>
<div id="png_blob"></div>
<br>Jpeg :
<div id="jpg_data"></div>
<div id="jpg_blob"></div>

canvas.toDataURL('image/jpeg', 0) 演示?

var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
document.querySelector('input').onchange = function(){
var img = new Image();
img.src = URL.createObjectURL(this.files[0]);
img.onload = function(){
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0,0);
document.images[0].src = canvas.toDataURL('image/jpeg', 0);
}
}
<input type="file"/>
<img/>

此外,如果您需要使文件比特定大小更轻,我在 another question 上写了一些内容,将数据大小限制为 3Mb(只需根据需要更改 maxSize 并删除 localStorage 部分)。

关于javascript - 调整 Canvas 质量以达到预定的图像文件大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32433211/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com