web-dev-qa-db-ja.com

キャンバスを使用せずにJavaScriptでBase-64画像のサイズを変更する

HTML要素を使用せずにJavaScriptで画像のサイズを変更する方法が必要です。

私のモバイルHTMLアプリは写真を撮り、それをbase64文字列に変換します。その後、ストレージスペースを節約するために、APIに送信する前にサイズを変更する必要があります。

私は、キャンバス要素を使用してサイズを変更するための別のより適切な方法を探しています。方法はありますか?

55
rilar

メイン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データを持つdata-uriであると思われますか?)、最初に画像を「ロード」する必要があります。

_var img = new Image;

img.onload = resizeImage;
img.src = originalDataUriHere;

function resizeImage() {
    var newDataUri = imageToDataUri(this, targetWidth, targetHeight);
    // continue from here...
}
_

ソースが純粋なbase-64文字列である場合、単純にヘッダーを追加してdata-uriにします。

_function base64ToDataUri(base64) {
    return 'data:image/png;base64,' + base64;
}
_

_image/png_部分をbase64文字列が表す型に置き換えるだけです(つまり、オプションの引数にします)。

68
user1693593

ケンの答えは正しい答えですが、彼のコードは機能しません。私はそれにいくつかの調整を加え、今では完全に動作します。データ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);
16

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 Docsを確認できます。 https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise

6
user8094363

はい、できます。これらのソリューションは、画像をbase64に変換するだけでなく、サイズ変更にも適しています。

  1. jpg-js でjsファイルを画像ビットマップに変換できます。また、このlibでのみサイズ変更できますが、非常に大きな画像から非常に小さなサイズに変更する場合、品質は非常に悪くなります。高解像度画像の方法は、jpg-jsでファイルをビットマップに変換してから、Pica libでこのビットマップのサイズを変更することです。
  2. Jpg-jsでファイルから画像データを取得(またはキャンバスに画像を描画)し、lib pica のサイズを変更してcanvasImageDataのサイズを変更できます。 (キャンバスサイズの制限なしで高解像度画像に適しています)
  3. キャンバスをボディにアタッチせずにオフスクリーンキャンバスを使用し、画像のサイズを変更できます。このソリューションは高速になりますが、たとえば6000x6000ピクセルなどの高解像度画像の場合は、より悪いソリューションになります。その場合、結果のキャンバスの品質が悪いか、空になるか、ブラウザがメモリ制限の例外で落ちる可能性があります。 (通常の画像と小さな画像に適しています)

Jpg-jsとPicaは、dom要素をまったく使用しません。これらのライブラリは、dom要素(キャンバスと画像)を使用せず、画像データのみで機能します。

キャンバスについては、サイズ制限はこちらをご覧ください post

6
Alex Nikulin

ここに示すように、生のBase64イメージ操作を使用できます。

見た目が難しく(PNGのみ)、多くの人がキャンバスの使用を選択する理由

http://blog.calyptus.eu/seb/2009/05/png-parser-in-javascript/

1
user3105359