none
C/C++ void型でのRowデータ画像の編集に関して RRS feed

  • 質問

  • お世話になります。

    C/C++どちらかでの、Raw画像の編集についてご教授頂きたく、質問させて頂きました。

    メーカー製のSDKより、画像のRowデータを受け取り、その画像データを切り取り、分割して行きたいと考えています。

    現在、メーカーSDKのBufferから、Void型のBufferへ画像データを受け取れる事を確認しました。

    fwriteにて、Bufferデータを出力すると、ちゃんとRawデータと同様の事を確認しました。

    Void型のBufferで受け取ったデータを分割して行きたいと思いますが、どうやったらいいのか分かりません。

    漠然としていて申し訳ありませんが、良い方法など、ご教授して頂ければ幸いです。

    よろしくお願い致します。


    2015年10月24日 6:48

回答

  • 配列に入れていく必要があるかどうかはあなたがやりたいこと次第なので、私には答えられません。
    単に中身のデータを何ブロックかに分けてファイルに書き出すだけであれば、配列は不要だと思いますけれども。

    ところで、「画像処理」って書いていますが、何するんですか?
    データを一定バイト単位で分けるだけなら、「画像処理」というより、単にメモリを扱うだけです。

    char 型や unsigned char 型といった 1 バイト単位で処理できる型のポインタにキャストするのがまず第一歩でしょう。
    そこから配列のようにポインタを使うもよし、一定バイトごとに区切ってポインタを操作するもよし。

    このあたりの話を聞いてもピンとこないのであれば、「C 言語のポインタ」について学んでいただき、さらにその応用としてポインタを進めるとか、メモリ読み書き・ファイル読み書きの関数や API について調べてください。
    それらを学んでもまだイメージがつかないのであれば、ファイルを分割するようなサンプルを読んでもらった方がいいでしょうね。

    2015年10月24日 9:55
    モデレータ
  • 2bitのグレースケールというのものはありません。
    それは一般的には「モノクロ」のフォーマットに使用されます。

    グレースケールと言う場合、黒(一般に0側)~白を数値で表しています。
    が、何ビットのグレースケールであるかの定義を見つけなければなりません。
    区切りの良い数値、8、16、32bitのグレースケールが良く使われますが、
    16、32の場合にはエンディアン(=バイトオーダー)が関わってきます。
    グレースケールであるとわかっていても、まず、

     1. 画像1[pixl]あたり、何Byteで表現されているか。
     2. 1[pixl]の内部の構造。及びスケールに使われるbit数は何ビットか。
     3. 1ラインの表現にパディングが含まれる場合がありえるか。
     4. pixlの並び順の定義。

    等がわかっていないと、作業を進めることは困難でしょう。
    あてずっぽうで進めても解決から遠ざかるばかりであると断言できます。

    2015年10月26日 9:52
  • tmp は何型になっているのですか?
    unsigned 指定しかしていないようですので、きちんと unsigned char になっておらず、意図したバイト列にできていないのでは?

    1 pixel あたり 2bytes であれば、unsigned char としては width * height * 2 の領域が必要です。
    width * height の領域にして unsigned short で扱った方がやりやすいかもしれませんが。

    2015年10月26日 12:52
    モデレータ

すべての返信

  • void* は型を指定していないポインタと考えてください。

    char 型として 1 バイトずつ扱いたいなら、static_cast<char*> などでキャストすれば良いでしょう。

    2015年10月24日 7:12
    モデレータ
  • 返信ありがとうございます。

    char型としてキャストして、配列に入れていけばいいという事でしょうか。

    すみません。画像処理は初めてのもので、、、調べ方が悪いのか、やり方が出て来ません。

    2015年10月24日 8:04
  • 配列に入れていく必要があるかどうかはあなたがやりたいこと次第なので、私には答えられません。
    単に中身のデータを何ブロックかに分けてファイルに書き出すだけであれば、配列は不要だと思いますけれども。

    ところで、「画像処理」って書いていますが、何するんですか?
    データを一定バイト単位で分けるだけなら、「画像処理」というより、単にメモリを扱うだけです。

    char 型や unsigned char 型といった 1 バイト単位で処理できる型のポインタにキャストするのがまず第一歩でしょう。
    そこから配列のようにポインタを使うもよし、一定バイトごとに区切ってポインタを操作するもよし。

    このあたりの話を聞いてもピンとこないのであれば、「C 言語のポインタ」について学んでいただき、さらにその応用としてポインタを進めるとか、メモリ読み書き・ファイル読み書きの関数や API について調べてください。
    それらを学んでもまだイメージがつかないのであれば、ファイルを分割するようなサンプルを読んでもらった方がいいでしょうね。

    2015年10月24日 9:55
    モデレータ
  • まず、RAWとは「未加工の」という様な意味です。従って、
    その画像データの内部構造は
    「それを出力したハード又はソフトの定義による」
    ということになります。
    つまりそのデータの内部構造(フォーマットと呼ぶ場合もあります)
    を知ることが最初にやるべきことです。
    質問文中の「メーカー製SDK」に、それの説明が無ければ、
    ほぼお手上げであると言えます。

    さて、そもそもRAWデータはそれを出力したメーカーの純正アプリ等で
    加工することが前提となります(他社の製品もありますが)。

    そもそもRAWデータをどの様にしたいのでしょうか、
    それを質問したほうが近道かもしれません。

    2015年10月26日 1:15
  • 仰って頂いた、「何ブロックかに分けて書きだす」処理をしたいと考えていました。

    自分のイメージも、ポインタを使ったブロック分けを行いたいと考えていました。

    久しぶりにポインタを使ったコードを書く為、色々思い出しながらになりそうです。

    先ずは、unsingned char への変換を行い、それからポインタでのメモリ操作でのデータのブロック分けを行いたいと思います。

    2015年10月26日 1:30
  • 仲澤@失業者 様

    ご返信、ありがとうございます。

    RAWデータの内部構造ですが、バイナリエディタで確認しています。(メーカーSDKから、Bufferのポインタをもらってます)

    SDKには、加工に関する関数が容易されていないようで、、、頑張ってC言語で書く事にしました。(というか出力してあげるから後は何とかして的なSDKでした。)

    フォーマットがヘッダーに記載されていない事を、バイナリエディタにて、先頭32bitをコピーしただけのデータを、

    バイナリエディタにて作成して確認しました。結果、先頭から画像データが入っていそうです。(画像のコントラスト等が入っている為)

    Azulean様にアドバイス頂いたことを元に、SDKのバッファからビット単位のデータを取得し、書き込みを行う予定です。

    しかし、、、思うように行きません。私のコードが間違っているのではと思っています。確認して頂ければ幸いです。

    ==============================

    //4000 x 2000 の画像データから、先頭の170 x 120のデータを取り出したい

    void* m_tempBuffer = malloc( 4000 x 200 x 2);

    memcpy( m_tempBuffer, getBufferSDK. sizeof(getBufferSDK)); //getBufferSDKはSDKデータ

    unsigned char* buff = static_cast<unsigned char*>(m_tempBuffer);

    unsigned tmp[170][120] = {""};

    for(int x = 0; x < 170; x++)

    {

    for(int y = 0; y < 120; y++)

    {

    tmp[x][y] = *buff;

    buff++;

    }

    }

    FILE fp = 保存先:

    if(fp != NULL)

    {

    fwrite(tmp, (170 x 120 x 2), 1, fp);

    //fwrite(buff , ( 4000 x 200 x 2), 1, fp); //出力OK.同じデータになる.

    fclose(fp);

    }

    free(m_tempBuffer );

    ==============================

    よろしくお願い致します。

    2015年10月26日 7:19
  • 画像のフォーマットによりまが、元画像がPIXL[4000][200]ピクセルで、
    かつ、画像データ内のピクセルが一般的なX,Yで配列されていると仮定すると
     [X]→
     [0000]・・・・[3999]  // [Y]↓
     [4000]・・・・[7999]
     [8000]・・・・[11999]
        ・
        ・
        ・

    の様に並んでいると仮定できます。
    Xを170 Yを120まで切り取る場合は、画像上のインデックスを考慮して

     [X]→
     [0000]・・・・[0169]  // [Y]↓
     [4000]・・・・[4169]
     [8000]・・・・[8169]
        ・
        ・
        ・

    の様にコピーしなければならないのではないでしょうか。
    掲載のコードは一見してそうはなっていないように見えますがどうでしょう。
    これは複数の仮定を含みますのであくまで原理的な話にすぎません。
    しかもPIXLの中身とサイズが不明です。
    しかるに、正確なフォーマットの定義が必要なわけですね。

    2015年10月26日 8:00
  • 返信ありがとうございます。

    正確なフォーマットが、やはり必要でしょうか。メーカーのSDKに記載が無いか、再度確認をしてみます。


    今のところ、グレースケールという事らしいのですが、2bit必要という事なのでしょうか。

    xとyは逆転していますね。申し訳ありません。

    又、2回目のループ後に、+4000、ポインタを進める必要があるという理解で、いいのでしょうか。

    よろしくお願い致します。

    2015年10月26日 8:58
  • 2bitのグレースケールというのものはありません。
    それは一般的には「モノクロ」のフォーマットに使用されます。

    グレースケールと言う場合、黒(一般に0側)~白を数値で表しています。
    が、何ビットのグレースケールであるかの定義を見つけなければなりません。
    区切りの良い数値、8、16、32bitのグレースケールが良く使われますが、
    16、32の場合にはエンディアン(=バイトオーダー)が関わってきます。
    グレースケールであるとわかっていても、まず、

     1. 画像1[pixl]あたり、何Byteで表現されているか。
     2. 1[pixl]の内部の構造。及びスケールに使われるbit数は何ビットか。
     3. 1ラインの表現にパディングが含まれる場合がありえるか。
     4. pixlの並び順の定義。

    等がわかっていないと、作業を進めることは困難でしょう。
    あてずっぽうで進めても解決から遠ざかるばかりであると断言できます。

    2015年10月26日 9:52
  • 返信ありがとうございます。

    すみません。16bitのグレースケールで、1pixlあたり2bityという事でした。

    それ以外は、先頭からずーっと画像データが入っているとう仕様みたいです。

    2bitずつという事で、xが171であれば、「171 x 2」としていくという考え方で良いのでしょうか。

    基本的な部分だとは思いますが、何卒、ご教授をお願い致します。

    2015年10月26日 11:30
  • tmp は何型になっているのですか?
    unsigned 指定しかしていないようですので、きちんと unsigned char になっておらず、意図したバイト列にできていないのでは?

    1 pixel あたり 2bytes であれば、unsigned char としては width * height * 2 の領域が必要です。
    width * height の領域にして unsigned short で扱った方がやりやすいかもしれませんが。

    2015年10月26日 12:52
    モデレータ
  • Azulean 様

    返信ありがとうございます。

    すみません。記載が漏れていましたが、「unsigned char」です。

    2015年10月26日 13:00
  • 16bit値を扱いたいのであれば、C言語であれば #include <stdint.h>、C++言語であれば #include <cstdint> した上で、 uint16_t を使用されることをお勧めします。
    2015年10月26日 23:46
  • 佐祐理 様

    返信ありがとうございます。

    参考にさせて頂きます。

    2015年10月27日 3:12