我需要一种在不使用HTML元素的情况下在JavaScript中调整图片大小的方法。
我的移动HTML应用程序拍摄照片,然后将它们转换为base64字符串。此后,我需要在将它们发送到API之前调整它们的大小,以节省存储空间。
我正在寻找一种不同的,更合适的方法来调整它们然后使用canvas元素。有办法吗?
答案 0 :(得分:68)
避免主HTML受影响的一种方法是创建一个不在DOM树之外的屏幕外画布。
这将提供位图缓冲区和本机编译代码来编码图像数据。这很简单:
function imageToDataUri(img, width, height) {
// create an off-screen canvas
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// set its dimension to target size
canvas.width = width;
canvas.height = height;
// draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, width, height);
// encode image to data-uri with base64 version of compressed image
return canvas.toDataURL();
}
如果要生成与PNG不同的格式(默认),只需指定如下类型:
return canvas.toDataURL('image/jpeg', quality); // quality = [0.0, 1.0]
值得注意的是CORS限制适用于toDataURL()
。
如果你的应用只提供base64编码的图像(我假设它们是带有base64数据的数据?)那么你需要首先“加载”图像:
var img = new Image;
img.onload = resizeImage;
img.src = originalDataUriHere;
function resizeImage() {
var newDataUri = imageToDataUri(this, targetWidth, targetHeight);
// continue from here...
}
如果源是纯base-64字符串,只需添加一个标题即可使其成为数据-uri:
function base64ToDataUri(base64) {
return 'data:image/png;base64,' + base64;
}
只需用base64字符串表示的类型替换image/png
部分(即使其成为可选参数)。
答案 1 :(得分:16)
肯的答案是正确的答案,但他的代码不起作用。我对它做了一些调整,它现在完美无缺。要调整数据URI的大小:
// Takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
function resizedataURL(datas, wantedWidth, wantedHeight)
{
// We create an image to receive the Data URI
var img = document.createElement('img');
// When the event "onload" is triggered we can resize the image.
img.onload = function()
{
// We create a canvas and get its context.
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = wantedWidth;
canvas.height = wantedHeight;
// We resize the image with the canvas method drawImage();
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
/////////////////////////////////////////
// Use and treat your Data URI here !! //
/////////////////////////////////////////
};
// We put the Data URI in the image's src attribute
img.src = datas;
}
// Use it like that : resizedataURL('yourDataURIHere', 50, 50);
答案 2 :(得分:6)
是的,你可以。这些解决方案不仅可以调整大小,还可以将图像转换为base64。
Jpg-js和Pica根本不会使用dom元素。这些库只适用于图像数据,没有dom元素(画布和图像)。
关于画布,尺寸限制请参阅此post
答案 3 :(得分:5)
PierrickMartellière远不是最好的答案,我只是想指出您应该使用异步功能来实现。一旦完成,您将可以执行以下操作:
var newDataUri = await resizedataURL(datas,600,600);
在继续下一步之前,它将等待函数的结果。这是一种更干净的代码编写方式。这是Pierrick的功能,只需进行少量编辑:
// Takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
function resizedataURL(datas, wantedWidth, wantedHeight){
return new Promise(async function(resolve,reject){
// We create an image to receive the Data URI
var img = document.createElement('img');
// When the event "onload" is triggered we can resize the image.
img.onload = function()
{
// We create a canvas and get its context.
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = wantedWidth;
canvas.height = wantedHeight;
// We resize the image with the canvas method drawImage();
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
// This is the return of the Promise
resolve(dataURI);
};
// We put the Data URI in the image's src attribute
img.src = datas;
})
}// Use it like : var newDataURI = await resizedataURL('yourDataURIHere', 50, 50);
有关更多详细信息,您可以查看MDN文档:https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise
答案 4 :(得分:1)
您可以使用原始Base64图像处理,如下所示。
看起来很难(仅适用于png)以及为什么许多人选择使用画布
http://blog.calyptus.eu/seb/2009/05/png-parser-in-javascript/
答案 5 :(得分:0)
我认为此方法是解决此问题的最佳方法。
function base64Resize(sourceBase64, scale , callBack) {
const _scale = scale;
var img = document.createElement('img');
img.setAttribute("src", sourceBase64);
img.onload = () => {
var canvas = document.createElement('canvas');
canvas.width = img.width * _scale;
canvas.height = img.height * _scale;
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var maxW = img.width * _scale;
var maxH = img.height * _scale;
var iw = img.width;
var ih = img.height;
var scl = Math.min((maxW / iw), (maxH / ih));
var iwScaled = iw * scl;
var ihScaled = ih * scl;
canvas.width = iwScaled;
canvas.height = ihScaled;
ctx.drawImage(img, 0, 0, iwScaled, ihScaled);
const newBase64 = canvas.toDataURL("image/jpeg", scl);
callBack(newBase64);
}
}
重要的一点是您应该使用 img.onload
事件。