トップページ > 過去ログ > 記事閲覧
受信した画像データからグラフィックハンドルを作成する方法
名前:モンペチ 日時: 2008/01/23 12:50

はじめまして,モンペチと申します. 通信対戦ゲームを作っているのですが,自分のアイコンを相手に表示してもらうために,画像データを送信し合って,受信したデータから画像ハンドルを作成したいと思っています. 以下のようなプログラムを用いて,同一PCでの重複起動により通信をすると MyIcon.jpg と test.jpg は同じ画像になるはずなのですが,バイナリエディタで中身を見たところ,サイズは等しいのですがデータがでたらめなものになっていました. 関係ないとは思いますが,SetUseDXNetWorkProtocol(FALSE); として,DxLibの通信形態は使用しておりません. どなたか,おわかりいただけるようならご教授の程お願いします. void ChangeIcon() { FILE *fp; int i; int MySize, YourSize; unsigned char *MyData, *YourData; fp = fopen("MyIcon.jpg", "rb"); fseek(fp, 0L, SEEK_END); MySize = ftell(fp); fseek(fp, 0L, SEEK_SET); MyData = (unsigned char *)malloc(MySize); fread(MyData, MySize, 1, fp); fclose(fp); /***** ファイルのサイズを教え合う *****/ NetWorkSend(NetHandle, &MySize, sizeof(int)); while(!ProcessMessage() && GetNetWorkDataLength(NetHandle) <= 0) WaitTimer(100); NetWorkRecv(NetHandle, &YourSize, sizeof(int)); /**************************************/ YourData = (unsigned char *)malloc(YourSize); /********** ファイルの送受信 **********/ NetWorkSend(NetHandle, &MyData, MySize); while(!ProcessMessage() && GetNetWorkDataLength(NetHandle) <= 0) WaitTimer(100); NetWorkRecv(NetHandle, YourData, YourSize); /**************************************/ YourIcon = CreateGraphFromMem(YourData, YourSize); if(host == SERVER) { if((fp = fopen("test.jpg", "wb")) != NULL) fwrite(&YourData, YourSize, 1, fp); fclose(fp); } free(MyData); free(YourData); }

Page: 1 | 2 |

Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.3 )
名前: 日時:2008/01/24 00:22

>DxLibの通信形態は使用しておりません との事なのでGetNetWorkDataLength関数や NetWorkSend関数、NetWorkRecv関数の動作が 一切代わります。関係大有りだったりします。 GetNetWorkDataLength関数 DXライブラリの通信形態がOFFの場合 この関数は受信データの有無を0か1で返します NetWorkSend関数 DXライブラリの通信形態がOFFの場合 この関数は通常のsend関数と同じでどの程度 データが送信されるのか不定で、返却値として 実際に送信されたサイズが帰ってきます。 自分が送信したいサイズまでデータをずらしながら 全てを送信するまでこの関数を呼び続ける必要が あります。 NetWorkRecv関数 DXライブラリの通信形態がOFFの場合 この関数は通常のrecvと同じ動作になります。 受信されるデータサイズはもちろん不定で、 自分が欲しいデータのサイズを受信できるまで 呼び続ける必要があります。
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.4 )
名前:モンペチ 日時:2008/01/24 02:46

>>通様 大変詳しい説明をありがとうございました. このプログラムでUNIX上で動作するロビーサーバとも接続するので,パケットに余分なデータを付加して正常な通信が出来なくなるのを恐れての配慮だったのですが,裏目に出たようです…
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.5 )
名前:モンペチ 日時:2008/01/24 11:15

>>通様 DxLibの通信形態を使用して while(!ProcessMessage() && GetNetWorkDataLength(NetHandle) < MySize) としたのですが,やはり作成した test.jpg のデータはでたらめなものになっていました.
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.6 )
名前:Will 日時:2008/01/25 13:39

モンペチさんに確認したいことがあります。 1.DxLib_InitはChangeIconがコールされるよりも前に実行されていますよね? 2.画像ファイルからのリードデータをMyDataにコピーしていますが、その時点での内容は正しいですか 3.画像ファイル以外のもっとデータサイズの小さいバイナリデータの場合でもダメですか?
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.7 )
名前:モンペチ 日時:2008/01/25 16:42

>>Wii様 >1.DxLib_InitはChangeIconがコールされるよりも前に実行されていますよね? はい >2.画像ファイルからのリードデータをMyDataにコピーしていますが、その時点での内容は正しいですか 以下に先頭80バイト分のデータを示します. オリジナルファイル(MyIcon.jpg) FF D8 FF E0 00 10 4A 46 49 46 00 01 01 00 00 01 00 01 00 00 FF DB 00 43 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 FF DB 00 43 01 01 01 MyDataの中身 F8 2D 00 01 00 00 00 00 C2 27 00 00 78 FF 12 00 9A 59 40 00 B8 E3 55 00 88 FF 12 00 50 66 40 00 CC C0 55 00 D7 23 14 00 B8 FF 12 00 13 19 41 00 00 00 40 00 00 00 00 00 D7 23 14 00 01 00 00 00 38 00 31 00 33 00 36 00 00 E0 FD 7F 00 E0 FD 7F E0 FF 12 00 78 84 40 00 F0 FF 12 00 00 00 00 00 test.jpg C0 55 00 01 F8 2D 00 01 C2 27 00 00 C2 27 00 00 78 FF 12 00 9A 59 40 00 B8 E3 55 00 88 FF 12 00 50 66 40 00 CC C0 55 00 D7 23 14 00 B8 FF 12 00 13 19 41 00 00 00 40 00 00 00 00 00 D7 23 14 00 01 00 00 00 38 00 31 00 33 00 36 00 00 E0 FD 7F 00 E0 FD 7F E0 FF 12 00 78 84 40 00 F0 FF 12 00 MyDataの時点で正しくコピーできてなかったです. バイナリファイルに対しSEEK_ENDを指定したからでしょうか? 送信されたデータも変化しています. 3.画像ファイル以外のもっとデータサイズの小さいバイナリデータの場合でもダメですか? >a.txt 中身は abcdefghijklmnopqrtuvwxyz[EOF] を用いて同様に実験してみました. オリジナルファイル(a.txt) 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 74 75 76 77 78 79 7A MyDataの中身 F8 2D 00 01 00 00 00 00 19 00 00 00 78 FF 12 00 9A 59 40 00 AC E3 55 00 88 受信後のデータ,YourDataの中身 18 2E 00 01 F8 2D 00 01 19 00 00 00 19 00 00 00 78 FF 12 00 9A 59 40 00 AC ファイルの種類とサイズは関係ないようです.
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.8 )
名前:モンペチ 日時:2008/01/25 17:14

追記です. 通信関係の使用ポートについて ttp://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=past&no=334 の管理人様のコメントに DXライブラリの通信機能は NetWorkSend 関数で渡されたデータに ちょっとした追加情報を加えて飛ばしていますので(NetWorkSend に渡された データの長さを先頭4バイトに加えて相手にパケットを飛ばしている) とあるので,受信後のデータに4バイト分のヘッダが付加されるため DXライブラリの通信形態を使うと,バイナリデータの受信は上手くいかないようです. 先頭4バイトの,1バイト目はデータ長フィールドというのは一目瞭然なのですが 2~4バイトは何を意味してるのでしょうか…
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.9 )
名前: 日時:2008/01/25 18:12

>データの長さを先頭4バイトに加えて >相手にパケットを飛ばしている) これはDXライブラリが内部的につけて送信している という意味で、DXライブラリの通信形態を利用して 居る場合NetWorkRecvの受信処理内部でそのサイズは DXライブラリが受信して使うためライブラリの使用 者には見えないという意味でしょう。 #でなければ仕様的に使い物になりません。 これは使用者は意識する必要は無いはずです。 #いまちょっと試せる環境ではないので #画像の送受信少しつくってみます。。。
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.10 )
名前:モンペチ 日時:2008/01/25 18:28

>>通様 コメントありがとうございます. 作成中のプログラムの締切が間近なので,少し焦ってます… DXライブラリの通信がよくわからないので パケットをダンプして見たいと思います. >#画像の送受信少しつくってみます。。。 本当にありがとうございますm( __ __ )m
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.11 )
名前:Will 日時:2008/01/26 11:53

MyDataの中身が画像データの場合とテキストファイルの場合でほとんど一緒なのが気になりますね。 fopen後のfpがNULLではないか(ファイルオープン失敗)をチェックしていませんが、画像の場合もテキストファイルの場合もファイルのオープンには成功しているのでしょうか? ファイルのオープンに失敗し、NULLポインタでfseekとかftellを実行し、ポインタがぶっ飛んでどこかのメモリ空間をコピーしているのかなと思いました。
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.12 )
名前:モンペチ 日時:2008/01/26 13:12

>>Will様 >fopen後のfpがNULLではないか(ファイルオープン失敗)をチェックしていませんが、画像の場合もテキストファイルの場合もファイルのオープンには成功しているのでしょうか? はい
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.13 )
名前:Will 日時:2008/01/26 17:42

開発環境が書かれていないのでBuilderのほうで以下のようなサンプルプログラムを組んでみました。 #include <stdio.h> #include <stdlib.h> int main(void) { int len; int rlen; int i; FILE *fp; unsigned char *pdat; if ((fp = fopen("test.jpg", "rb")) == NULL) { fprintf(stderr, "file open error.\n"); return (1); } fseek(fp, 0L, SEEK_END); len = ftell(fp); fseek(fp, 0L, SEEK_SET); pdat = (unsigned char *)malloc(len); fclose(fp); rlen = fread(pdat, 1, len, fp); if (rlen != len) { fprintf(stderr, "file read error. len = %d, rlen = %d\n", len, rlen); free(pdat); return (1); } for (i = 0; i < len; i++) { printf("%02x ", pdat[i]); } free(pdat); return (0); } 80Kbyteのjpegファイルを読ませてみましたが出力されたデータとjpegの内容は同じになりました。 builderのほうではfseekは正常動作するようです。
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.14 )
名前:Will 日時:2008/01/26 17:45

わかった! 誤: NetWorkSend(NetHandle, &MyData, MySize); ↓ 正: NetWorkSend(NetHandle, MyData, MySize); じゃないですか?
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.15 )
名前:モンペチ 日時:2008/01/27 01:15

>>Will様 遅くなってすみません.先ほど確認したところ NetWorkSend(NetHandle, MyData, MySize); を直しただけで,ちゃんと相手に自分のアイコン が表示されました. うっかりミスのようでした. お時間を割いていただいた,Will様 通様 本当にありがとうございました.
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.16 )
名前:モンペチ 日時:2008/01/27 01:27

完成版を載せるので,受信したデータから グラフィックハンドルを作成したい人は参考にしてみてください. void ChangeIcon() { FILE *fp; int i; int MySize = 0, YourSize = 0; unsigned char *MyData, *YourData; if((fp = fopen(MY_ICON, "rb") != NULL) // バイナリモードで開く { fseek(fp, 0L, SEEK_END); // ファイルポインタをファイルの末端に MySize = ftell(fp); // ファイルの末端でファイルポインタのアドレスを取得すれば,それはファイルのサイズ fseek(fp, 0L, SEEK_SET); // ファイルポインタをファイルの先頭に戻す MyData = (unsigned char *)malloc(MySize); // ファイルを丸々読み込めるメモリリ領域を確保する fread(MyData, MySize, 1, fp); // ファイルを丸々読み込む fclose(fp); } /***** ファイルのサイズを教え合う *****/ NetWorkSend(NetHandle, &MySize, sizeof(int)); while(!ProcessMessage() && GetNetWorkDataLength(NetHandle) < sizeof(int)) WaitTimer(100); NetWorkRecv(NetHandle, &YourSize, sizeof(int)); // バッファからデータを取得 /**************************************/ // 受信ファイルを丸々読み込めるメモリ領域を確保する YourData = (unsigned char *)malloc(YourSize); /********** ファイルの送受信 **********/ NetWorkSend(NetHandle, MyData, MySize); while(!ProcessMessage() && GetNetWorkDataLength(NetHandle) < MySize) WaitTimer(100); NetWorkRecv(NetHandle, YourData, YourSize); // バッファからデータを取得 /**************************************/ // 受信したデータでグラフィックハンドルを作成する YourIcon = CreateGraphFromMem(YourData, YourSize); // グラフィックを作成し終わったらグラフィックデータを // 格納していたメモリ領域を開放する free(MyData); free(YourData); //DrawGraph(0, 0, YourIcon, FALSE);ScreenFlip();WaitKey(); }
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.17 )
名前:モンペチ 日時:2008/01/27 01:42

すみません,修正です. 誤:if((fp = fopen(MY_ICON, "rb") != NULL) 正:if((fp = fopen(MY_ICON, "rb")) != NULL) カッコの数が違いました. YourIcon = CreateGraphFromMem(YourData, YourSize); のYourIconはint型のグローバル変数です.
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.18 )
名前: 日時:2008/01/27 14:37

返信遅くなってすみません。。。 時間が無くてレスできなかったのですが、 解決したようですね。。。orz C言語の標準ではバイナリ形式でfopenした ファイルのサイズを明確に取得する方法は無く 最初から最後までデータを読み込んでカウントする 方法のみです。 テキトウですが以下のような関数を用意しました。 この関数は第2引数にNULLを指定して渡すと、 第1引数に指定されたファイルのサイズを 第3引数に返し、第2引数がNULL以外の場合 第1引数のファイルサイズよりも第3引数で指定 されたサイズが小さければそのサイズを格納して 処理を返します。 int GetFileData( const char* file, void** data, size_t* psize ) { size_t cnt, i; FILE* fp; if( file == NULL || psize == NULL ){ return 1; } fp = fopen( file, "rb" ); if ( fp == NULL ){ return 2; } for( i=0; fgetc(fp)!=EOF; i++ ); fclose(fp); if( data == NULL ){ *psize = i; return 0; } if( *psize < i ){ *psize = i; return -1; } fp = fopen( file, "rb" ); if ( fp == NULL ){ return 2; } cnt = fread((*data), (*psize), 1, fp ); if( cnt != 1 ){ fclose(fp); return 3; } fclose(fp); return 0; } #ファイルをメモリ上にマップする為にファイルを #3回も読まないといけないのですが。。。。 呼び出し側の例(エラー処理は省略してます) GetFileData( "test.jpg", NULL, &file_size ); file_data = malloc( file_size ); GetFileData( "test.jpg", &file_data, &file_size ); free(file_data);
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.19 )
名前:モンペチ 日時:2008/01/27 17:41

>>通様 汎用性があるので色々使えそうですね >C言語の標準ではバイナリ形式でfopenした >ファイルのサイズを明確に取得する方法は無く ちょっと調べてみたんですが,FILE構造体のメンバに ファイルサイズを調べるのに使えそうな変数がありました. コンパイラによって変数名が違うので,実用的ではありませんが… 参考URL ttp://www.geocities.co.jp/SiliconValley-Bay/7437/c/file.htm >#ファイルをメモリ上にマップする為にファイルを >#3回も読まないといけないのですが。。。。 FILE *fp, *tmp; として,退避用のファイルポインタを 使うっていうのはどうでしょうか? 試してないので分かりませんが…
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.20 )
名前:Will 日時:2008/01/27 18:53

>C言語の標準ではバイナリ形式でfopenした >ファイルのサイズを明確に取得する方法は無く fp = fopen("***.bin", "ab"); size = ftell(fp); って言う方法もある。 ただし、追記バイナリオープンした場合にファイルポインタが必ずしもファイルの最後であるとは限らないためこれも処理系依存。 参考ソースなので蛇足かもしれませんがNo.16のソース if((fp = fopen(MY_ICON, "rb") != NULL) // バイナリモードで開く : } else { return; } として、ファイルオープンに失敗した場合は直ちに関数抜けたほうがいいと思う。 オープンに失敗している時はMyDataもYourDataも実体が無い上に初期化していないので最後のfreeで落ちる可能性がある。
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.21 )
名前: 日時:2008/01/28 00:05

>コンパイラによって変数名が違うので, >実用的ではありませんが そもそもCにおいてファイルの管理や アクセスをどの様に行うかを決めている訳ではなく 管理の方法や操作の方法がfopenなどの関数で 同じようにできれば良いので、場合によっては そのメンバが無い可能性もあるかもしれないのです。 #実際はほぼないでしょうが。 >退避用のファイルポインタを >使うっていうのはどうでしょうか? fseek(SEEK_SET)でOKです。 ただ、読み込みの回数は最低でも2回は 必要でしょう。 私が3回読むように実装しているのは、 関数を使用する側にメモリの領域を確保させる為で GetFileData関数が内部で領域を確保するならば 1度開けば良いように作れますが、それだと 使用している側がメモリを確保したことを意識 できずにメモリのの解放を怠る可能性がある為、 このような実装にしています。 >追記バイナリオープンした場合にファイルポインタ >が必ずしもファイルの最後であるとは >限らないためこれも処理系依存 これは私に??? つまり標準では取れないって事じゃないの。。。? #意味が違ってたらすみません
Re: 受信した画像データからグラフィックハンドルを作成する方法 ( No.22 )
名前:モンペチ 日時:2008/01/28 17:00

>>Will様 配布するつもりではないので,全体的にエラー処理を甘くしています. >>通様 >fseek(SEEK_SET)でOKです。 >>No.1を受けて あえて 使ってないと察します(笑 >使用している側がメモリを確保したことを意識 >>No.14のようなミスをしてしまう私への配慮だと捕らえさせて頂きます. スレの趣旨から脱線しつつあるので これにて私からのコメントは控えさせていただきます.

Page: 1 | 2 |