在不使用画布的情况下在JavaScript中调整Base-64图像的大小

时间:2014-01-06 19:52:31

标签: javascript canvas resize html5-canvas base64

我需要一种在不使用HTML元素的情况下在JavaScript中调整图片大小的方法。

我的移动HTML应用程序拍摄照片,然后将它们转换为base64字符串。此后,我需要在将它们发送到API之前调整它们的大小,以节省存储空间。

我正在寻找一种不同的,更合适的方法来调整它们然后使用canvas元素。有办法吗?

6 个答案:

答案 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。

  1. 您可以通过jpg-js将js文件转换为图像位图。并且您只能通过此lib调整大小,但是在从非常大的图像调整到非常小的情况下,质量将非常糟糕。最佳方式高分辨率图像是通过jpg-js将文件转换为位图,然后通过Pica lib调整此位图的大小。
  2. 您可以通过jpg-js从文件中获取图像数据(或在画布上绘制图像),然后通过调整lib pica的大小来调整canvasImageData的大小。 (适用于高分辨率图像,没有画布大小限制)
  3. 您可以使用屏幕外画布,而无需将画布附加到正文,并调整图像大小。这种解决方案会更快,但对于高分辨率图像来说将是更糟糕的解决方案,例如6000x6000像素。在这种情况下,结果画布可能质量不好或只是空,或浏览器可能会出现内存限制异常。 (适用于普通和小图像)
  4. 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 事件。