2012-12-19 13 views
18

javacript Uint8Arrayに保存されているPNG画像をレンダリングしようとしています。Javascript:データURIなしのキャンバス要素にUint8Arrayとして保存されたPNGをレンダリングする

var imgByteStr = String.fromCharCode.apply(null, this.imgBytes); 

var pageImg = new Image(); 
pageImg.onload = function(e) { 

    // Draw onto the canvas 
    canvasContext.drawImage(pageImg, 0, 0); 

}; 

// Attempt to generate the Data URI from the binary 
// 3rd-party library adds toBase64() as a string function 
pageImg.src="data:image/png;base64,"+encodeURIComponent(imgByteStr.toBase64()); 

は、しかし、私はいくつかの理由のonload関数は決して(私はクロームで設定したブレークポイントを持っていたし、それは単に打つことはありません)を実行しなかったことが判明:私はもともと試したコードは以下の通りでした。データURIの代わりにURLにsrcを設定すると、正しく動作することがわかりました。しかし、いくつかの制約のために、画像のURLを直接参照することはできません。すなわち、UInt8Arrayからロードする必要があります。

また、もっと複雑にするために、これらのイメージのサイズはメガバイトです。私が読んだところでは、非常に大きな画像にデータURIを使用しようとする際の互換性の問題があります。このため、私はそれらを利用することを非常に躊躇しています。

質問は、です。データURIを使用せずに、または画像URLを直接参照することなく、このバイト配列をキャンバスコンテキストにPNGとしてレンダリングするにはどうすればよいですか?


私はまた、直接putImageData機能を使用して画像データを操作するために、次のようなものを使用してみました。私は100%それはそのタブ私は、閉じたので、持っているブログから持ち上げた

var imgdata = canvasContext.createImageData(this.baseHeight, this.baseWidth); 
var imgdatalen = imgdata.data.length; 
for(var i=0; i<imgdatalen; i++) { 
    imgdata.data[i] = _this.imgBytes[i]; 
} 
canvasContext.putImageData(imgdata, 0, 0); 

この関数は謝罪ので、適切な信用を与えないためのインスピレーションに、どのように機能するかを理解していないことに注意してください。ゆっくりとこの事で離れて打撃ながら


はまた、私はクロームSECURITY_ERR: DOM Exception 18でエラーに遭遇しました。 ImageがdrawImageを使用してキャンバスに読み込まれるとすぐに、それはいくつかの追加の回避策なしで取得することはできません。トピックのChromium Blog postが特に役に立ちました

+0

あなたは 'putImageData()'を調べましたか? – David

+0

ちょうど好奇心のため:画像データはどのように配列に入ったのですか? – closure

+1

@David:少し調べましたが、PNGでエンコードされた画像データではなく、生の画像データであることを理解しています。 – zashu

答えて

15

PNGデータがメモリにある場合(私が思うと思います)、そこからイメージを作成できます。あなたはPNGデータを持っていない場合は、MIMEタイプを変更することができます

var image = document.createElement('img'); 
    image.src = 'data:image/png;base64,' + base64Data; 

注:あなたが同じことを行うことができますJavaScriptでは

<img src="data:image/png;base64,KSjs9JdldhAlisflAkshf==" /> 

:HTMLでは、それは次のようになります。

context.drawImage(image, 0, 0)などを使用してキャンバスにimageを描画することができます。

パズルの残りの部分は、Uint8Arrayの内容をBase 64データにエンコードすることです。

var array = new Uint8Array(), 
    base64Data = btoa(String.fromCharCode.apply(null, array)); 

機能btoaは標準ではありませんので、一部のブラウザでは、それをサポートしていない可能性があります。しかし、それはmost doのようです。そうでなければsome code I useが役に立つかもしれません。

私はこれをテストしていません!

+0

btoaは、ネイティブ関数を使用してエンコードする方法として使用しているサードパーティ製のライブラリの素晴らしい代替手段です。データURI(私がお勧めの方法です)の私の最大の恐怖は、具体的には、これが設計されているモバイルブラウザ上のサイズであり、[この質問](http://stackoverflow.com/questions/ 695151/data-protocol-url-size-limitation)を参照してください。 – zashu

+2

データURL経由で画像を表示しようとする前に、Chromeで制限を超えました。 2MBを超えると、Chromeはタブのプロセスにエラーを発生させます。他のブラウザには上限があります。このChromiumのバグレポートで見つかった回避策を使用しました:http://code.google.com/p/chromium/issues/detail?id=69227 –

+0

最終的に、データURIは他のように見えなかったのでソリューションはニーズに合っています。私は、画像そのものが十分に小さいことを確認しなければなりませんでした。 – zashu

16

すでにUInt8Arrayがある場合は、BlobcreateObjectURLを使用することを検討してください。 createObjectURLは、外部からロードされているファイルであるかのように、内部的に作成されたBlobのバイナリデータにブラウザがアクセスできる特別なURLを割り当てます。

Where it is supported,createObjectURLは、巨大なデータURIの優れた代替品です。 Opera、IE < 10、最新バージョン以外のすべてのモバイルブラウザでデータURIの使用に戻す必要があります。

var myArray; //= your data in a UInt8Array 
var blob = new Blob([myArray], {'type': 'image/png'}); 
var url = URL.createObjectURL(blob); //possibly `webkitURL` or another vendor prefix for old browsers. 
+0

'未定義のcreateObjectURL()エラー – adi

関連する問題