質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Emscripten

    12questions

    Emscripten は JavaScript に変換するコンパイラです。 C/C++ から生成される LLVM ビットコードをJavaScript に変換します。

  • WebAssembly

    11questions

webassemblyでの画像をCからjavascriptにもちこむ方法について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 217

kokawa2003

score 134

webassemblyでCでプログラミングしています。
Cとjavascriptの変換で苦しんでおります
https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html
を読んで以下の関数を作りました。

void showImage(cv::Mat img){
#ifdef EMSCRIPTEN
    cout<<"EMSCRIPTEN"<<endl;

    EM_ASM(
    function ImageToBase64(img, mime_type) {
        // New Canvas
        var canvas = document.createElement('canvas');
        canvas.width  = img.width;
        canvas.height = img.height;
        // Draw Image
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0);
        // To Base64
        return canvas.toDataURL(mime_type);
    }

    var b64 = ImageToBase64(img, "image/jpeg");
    window.open(b64);
    );
#else
    cout<<"LINUX"<<endl;
#endif

}


これ実行すると
ImageToBase64のところで " img is not defined"
と言われて実行エラーを出してしまいます。

書いているときから思っていたがcv::matをそのままjavascriptにもちこむのはやはりNGらしいです。

それではどうやってもちこんだらいいのでしょうか?
なにかJavascriptのblobかなにかに変換する方法を知りませんか?

その後とりあえず持ちこむことは成功して

#ifdef EMSCRIPTEN
#include <emscripten.h>

EM_JS(int, showImage, (cv::Mat img), {

          function ImageToBase64(img, mime_type) {
              // New Canvas
              var canvas = document.createElement('canvas');
              canvas.width  = img.width;
              canvas.height = img.height;
              // Draw Image
              var ctx = canvas.getContext('2d');
              ctx.drawImage(img, 0, 0);
              // To Base64
              return canvas.toDataURL(mime_type);
          }

          var b64 = ImageToBase64(img, "image/jpeg");
          window.open(b64);
          return 0;
});

#endif


void ofApp::saveImage(cv::Mat img){
#ifdef EMSCRIPTEN
    cout<<"EMSCRIPTEN"<<endl;
    showImage(img);
#else
    cout<<"LINUX"<<endl;
#endif

}


みたいな感じのですが今度はjavascriptでエラーを出してしまいます。
こんな感じです。
Uncaught TypeError: Failed to execute ‘drawImage’ on ‘CanvasRenderingContext2D’: The provided value is not of type ‘(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)’
at ImageToBase64 (:6931/OFNewPlayer.js:1)
at _showImage (:6931/OFNewPlayer.js:1)

これからするとやはり型が違うらしい。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

+1

分かりました。コツはmatをPNGデータにしてjavascriptのblobに持ち込むことです。
C->Javascriptの通信はBINDで行います
リンクフフラグに--bind が要ります

std::vector<uchar> g_buffer;
int buffer_size(){
    return g_buffer.size();
}

uchar buffer_data(int pos){
    return g_buffer[pos];
}

#ifdef EMSCRIPTEN
#include <emscripten.h>
#include <emscripten/bind.h>






EMSCRIPTEN_BINDINGS(my_module) {

    emscripten::function("buffer_data", &buffer_data);
    emscripten::function("buffer_size", &buffer_size);
}

EM_JS(int, showImage, (), {

          function ImageToBase64(img, mime_type) {
              // New Canvas
              var canvas = document.createElement('canvas');
              canvas.width  = img.width;
              canvas.height = img.height;
              // Draw Image
              var ctx = canvas.getContext('2d');
              ctx.drawImage(img, 0, 0);
              // To Base64
              return canvas.toDataURL(mime_type);
          }
          function debugBase64(base64URL){
              var newTab = window.open();
              newTab.document.body.innerHTML = '<img src="'+ base64URL +'" >';
          }


          console.log('Start');

          var size=Module.buffer_size();
          var uint8 = new Uint8Array(size);
          for(var i=0;i<size;i++){
              uint8[i]=Module.buffer_data(i);
          }
          var blob = new Blob([ uint8 ], { type: "image/png" });
          console.log('blob:'+blob);
          window.createImageBitmap(blob)
          .then(function(image) {
              var width = image.width;
              var height = image.height;
              console.log('ok'+image);
              var b64 = ImageToBase64(image, "image/jpeg");
              debugBase64(b64);
          })
          .catch(function(error) {
              console.log(error);
          });



          console.log('End');


      });

#endif



void ofApp::saveImage(cv::Mat img){
    cout<<"ookawa koui"<<endl;

    cv::imencode(".png", img, g_buffer);


#ifdef EMSCRIPTEN
    cout<<"EMSCRIPTEN"<<endl;
    showImage();
#else
    cout<<"LINUX"<<endl;
#endif

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • Emscripten

    12questions

    Emscripten は JavaScript に変換するコンパイラです。 C/C++ から生成される LLVM ビットコードをJavaScript に変換します。

  • WebAssembly

    11questions