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

ril*_*lar 56 javascript base64 resize canvas html5-canvas

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

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

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

小智 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();
}
Run Code Online (Sandbox Code Playgroud)

如果要生成与PNG不同的格式(默认),只需指定如下类型:

return canvas.toDataURL('image/jpeg', quality);  // quality = [0.0, 1.0]
Run Code Online (Sandbox Code Playgroud)

值得注意的是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...
}
Run Code Online (Sandbox Code Playgroud)

如果源是纯base-64字符串,只需向其添加一个标头,使其成为数据uri:

function base64ToDataUri(base64) {
    return 'data:image/png;base64,' + base64;
}
Run Code Online (Sandbox Code Playgroud)

只需用image/pngbase64字符串表示的类型替换该部分(即使其成为可选参数).

  • 对我不起作用.它创建了一个base64字符串,但它只是透明的. (2认同)

Pie*_*ère 18

肯的​​答案是正确的答案,但他的代码不起作用.我对它做了一些调整,它现在完美无缺.要调整数据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);
Run Code Online (Sandbox Code Playgroud)


小智 8

PierrickMartellière是最好的答案,我只是想指出你应该实现一个异步功能.一旦你能够做到这样的事情:

var newDataUri = await resizedataURL(datas,600,600);
Run Code Online (Sandbox Code Playgroud)

这将在进入下一步之前等待函数的结果.这是编写代码的一种更简洁的方法.
以下是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);
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请查看MDN文档:https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise

  • @AdamBarnes 我希望你当时对所有其他答案投反对票;) 如果你阅读了问题的前 2 或 3 条评论,你实际上可以读到目标是不在 DOM 上插入任何元素并在后面(后端)执行。干杯小伙子! (4认同)
  • 这个问题特别说“没有画布”。这不是一个答案。投反对票。 (2认同)

Ale*_*lin 6

是的你可以.这些解决方案不仅可以调整大小,还可以将图像转换为base64.

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

Jpg-js和Pica根本不会使用dom元素.这些库只适用于图像数据,没有dom元素(画布和图像).

关于画布,尺寸限制请看这篇文章