web-dev-qa-db-ja.com

Base64データURIイメージの圧縮

問題

PDFを作成するためにサーバーに送信される複数のグラフを作成しています。このデータは大きくなる可能性があります。

質問

画像データを圧縮してサーバーに送信する最良の方法は何ですか

背景

私が作成しているチャートはかなり複雑です。頭痛を省くために、このすべてがbase64データuriが生成されるキャンバスに変換されます。現在、データuriは、処理を処理するためにサーバーに送信されます。投稿された情報は、小さなチャートでは約400〜600 kb、最大のチャートでは12 mbとかなり大きくなります。

チャートは、操作/並べ替えが可能な組織チャートです。

これらの文字列をサーバーに送り返す前に圧縮するより良い方法はありますか?

研究

私がチェックアウトしたいくつかのこと:

https://github.com/brunobar79/J-I-C/blob/master/src/JIC.js (オプションのサイズだけを変更するようには見えません)

http://Pastebin.com/MhJZBsqW (おもしろそう)

しかし、私が見つけることができない外部ライブラリを参照しています:C_H_ImageLib_MinifyJpeg

https://code.google.com/p/jslzjb/source/browse/trunk/Iuppiter.js?r=2 (これは機能するように見えますが、サーバー側の解凍に依存しています)

22
David Nguyen

たぶん文字列圧縮があなたのための解決策です。これにより、データがバイト配列に変換されます。

たとえば、複数の実装とアルゴリズムがあります

  • LZMA-JSLempel-Ziv-Markovチェーン(LZMA)圧縮アルゴリズムのスタンドアロンJavaScript実装

    my_lzma = new LZMA("./lzma_worker.js");
    my_lzma.compress("This is my compression test.", 1, function on_compress_complete(result) {
        console.log("Compressed: " + result);
        my_lzma.decompress(result, function on_decompress_complete(result) {
            console.log("Decompressed: " + result);
        }, function on_decompress_progress_update(percent) {
            console.log("Decompressing: " + (percent * 100) + "%");
        });
    }, function on_compress_progress_update(percent) {
        console.log("Compressing: " + (percent * 100) + "%");
    });
    
  • lz-stringJavaScript圧縮、高速!

    var str = "This is my compression test.";
    console.log("Size of sample is: " + str.length);
    var compressed = LZString.compress(str);
    console.log("Size of compressed sample is: " + compressed.length);
    str = LZString.decompress(compressed);
    console.log("Sample is: " + str);
    
37
Koen.

大きな画像からサムネイルを生成する必要がありました。この問題の私のバージョンをHTML5 Canvasテクニックで解決することにしました。 GWTを使用しているため、コードは次のとおりです。

//Scale to size
public static String scaleImage(Image image, int width, int height) {

    Canvas canvasTmp = Canvas.createIfSupported();
    Context2d context = canvasTmp.getContext2d();

    canvasTmp.setCoordinateSpaceWidth(width);
    canvasTmp.setCoordinateSpaceHeight(height);

    ImageElement imageElement = ImageElement.as(image.getElement());

    context.drawImage(imageElement, 0, 0, width, height);

    //Most browsers support an extra option for: toDataURL(mime type, quality) where quality = 0-1 double.
    //This is not available through this Java library but might work with elemental version?
    String tempStr = canvasTmp.toDataUrl("image/jpeg");

    return tempStr;
}

JSを使用している場合、おそらくアイデアを得ることができます。

  • キャンバスを目的の出力画像のサイズにします
  • 入力画像を新しいサイズでキャンバスに描画します
  • canvas.toDataURL( "mime-type"、quality)を呼び出します

私が思うに任意のMIMEタイプを使用できますが、私にとってはjpegが最小で、私のデスクトップイメージプログラムの結果に匹敵しました。

私のGWTは品質パラメーターを許可しませんでした(そして、どのブラウザーでどれだけ広くサポートされているかは100%わかりません)。 mime-typeを空白のままにすると、デフォルトではpngになり、私の場合はjpegよりも3〜4倍大きくなります。

8
Jesse Adamson

かなり大きなファイルでこれが機能するようになりました。

それをするために、lz-string上記のように

ただし、1つの問題があります。これは、 ajaxを介したUTF-16データの送信は非推奨 であるため、機能しません。修正は、UTF-16とUTF-8の間での変換です。

これが私が使用している変換コードです。ところで、標準のエンディアンが何なのかわかりません。

var UTF = {};

UTF.U16to8 = function(convertMe) {
var out = "";
  for(var i = 0; i < convertMe.length; i++) {
      var charCode = convertMe.charCodeAt(i);
      out += String.fromCharCode(~~(charCode/256));
      out += String.fromCharCode(charCode%256);
    }
  return out;
}

UTF.U8to16 = function(convertMe) {
  var out = ""
  for(var i = 0; i < convertMe.length; i += 2) {
    var charCode = convertMe.charCodeAt(i)*256;
    charCode += convertMe.charCodeAt(i+1);
    out += String.fromCharCode(charCode)
  }
  return out;
}

Node.jsを使用している場合、このコードは両側で機能します。そうでない場合は、サーバー側にこれらのコンバーターの独自のバージョンを作成する必要があります。

ふう!これはなんて日だった。

3
Seph Reed

これはあまり満足のいく答えではありませんが、おそらくあなたが望む結果を与えるライブラリはありません。

サイズ変更はオプションではないと言いますが、それでは何ですか?ロスレス圧縮のみ? Base64文字列はすでに圧縮されたイメージを表しているため、どのライブラリもロスレス圧縮を提供するとは思わない。

0
T.S.