- PR -

配列のポインタ操作

投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-25 13:35
引用:

Jubeiさんの書き込み (2004-02-25 11:20) より:



 フラッシュする必要はありませんでしたか?うろ覚えですみません・・・
ヨンジュン
常連さん
会議室デビュー日: 2003/09/29
投稿数: 22
投稿日時: 2004-02-25 15:09
引用:

1枚分の画像データ数は固定ですが、1回のRecieve()では受信できないと思い
Recieve()を繰り返して1枚分のデータをためてから表示しようと思います。
最終的にはbyte[]にたまった画像データをMemoryStreamに展開して



MemoryStreamに格納するのであれば、バイト配列にためる必要は無いと思います。
受信したバッファ(バイト配列)を、そのままMemoryStreamに書き込んでいけば
OKだと思います。

コード:
byte[] buf = new byte[1024];
MemoryStream ms = new MemoryStream();

while (受信完了まで) {
  int ret = soc.Reacive(buf);
  ms.Write(buf,0,ret);
}

Bitmap bm = new Bitmap(ms);

//以降、ビットマップクラスを利用する処理




[/quote]


受信したバッファ(バイト配列)を、そのままMemoryStreamにWriteしていったのですが、
既定データ数になった時点で、MemoryStreamを引数にBitmap型を作成しようとするところで
以下のエラーとなります。

'System ArgmentException'のハンドルされていない例外がSystem.drawing.dll
で発生しました。追加情報:使用されたパラメータが無効です。

例えば
Bitmap bmp = new Bitmap("image.bmp");
MemoryStream ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Bmp);
Bitmap bmp1 = new Bitmap(ms);

ならエラーにならなにのに、何が違うのでしょうか?

Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-02-25 16:54
諸農です。

サーバーソケットを作るのが面倒くさかったので(^^ゞ
ストリームからの読み込みをSocket.Recieve()に見立てて
テストしました。

コード:
//ソケットの代わり
FileStream fs = new FileStream(@"TEST.bmp",FileMode.Open);
byte[] buf = new byte[1024];

MemoryStream ms = new MemoryStream();
while(true){
   //次のREADはソケット受信の代替
   int cnt = fs.Read(buf,0,buf.Length);
   ms.Write(buf,0,cnt);
   if (buf.Length > cnt)break;
}
fs.Close();
Bitmap bm = new Bitmap(ms);
pictureBox1.Image = bm;
pictureBox1.Update();



上記のコードでフォームに貼り付けたPictureBoxに問題なく
画像表示ができました。
受信しなければいけないデータは全部受信していますか?

_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-02-25 23:49
諸農です。

簡単なサーバーを作ってテストしました。

サーバー側(コンソールアプリ)
コード:
class BmpServer
{
    [STAThread]
    static void Main(string[] args)
    {
        try
        {
            int p = 13000;
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            TcpListener sv = new TcpListener(ip,p);
            sv.Start();
            try
            {
                Console.Write("接続待ち");
                TcpClient cl = sv.AcceptTcpClient();            
                NetworkStream ns = cl.GetStream();
                Console.WriteLine("接続中");

                using(FileStream fs = new FileStream(@"E:\Data\TEST.bmp",FileMode.Open))
                {
                    byte[] data = new byte[fs.Length];
                    fs.Read(data,0,data.Length);
                    ns.Write(data,0,data.Length);
                    ns.Flush();
                }
                cl.Close();
            }
            finally
            {
                sv.Stop();
            }
        }
        catch(SocketException e)
        {
            Console.WriteLine(e.Message);
        }
        Console.WriteLine("終了します");
        Console.Read();
    }
}



クライアント側(WinFormアプリ)
コード:
private void button1_Click(object sender, System.EventArgs e)
{
    IPAddress ip = IPAddress.Parse("127.0.0.1");
    IPEndPoint iep = new IPEndPoint(ip,13000);
    Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
    s.Connect(iep);
    if (!s.Connected)
    {
        MessageBox.Show("接続失敗");
        return;
    }
    byte[] b = new byte[1024];
    NetworkStream ns = new NetworkStream(s);
    MemoryStream ms = new MemoryStream();
    while (ns.DataAvailable)
    {
        int ret = ns.Read(b,0,b.Length);      
        ms.Write(b,0,ret);
    }
    Bitmap bmp = new Bitmap(ms);
    pictureBox1.Image = bmp;
    pictureBox1.Update();
}



これで、画像表示が出来ました。
テストに使用した画像ファイルは2.5MBのビットマップファイルです。



_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-02-26 06:03
諸農です。

見落としてました。すみませんm(__)m

引用:

Jittaさんの書き込み (2004-02-25 13:35) より:
引用:

Jubeiさんの書き込み (2004-02-25 11:20) より:



 フラッシュする必要はありませんでしたか?うろ覚えですみません・・・



ソケット側へのストリームへ直接書き込む時はFlushが必要ですが
ローカルのストリームの時は必要なかったと思います。

いつもフォローアップありがとうございます(^^)

_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
ヨンジュン
常連さん
会議室デビュー日: 2003/09/29
投稿数: 22
投稿日時: 2004-02-26 15:11
Jubeiさん、皆さん丁寧なテストコードありがとうございます。

うまく表示できない私のコードをデバッグしながら、受信したデータが
どう違うのか色々調べた結果、どうやらファイルヘッダー(BITMAPFILEHEADER)部分が
受信できていませんでした。
というのも、送信元処理としてはカメラから取得した1024×768バイトの生データに
BITMAPINFOHEADERと256バイトのカラーパレットRGBQUADを、付け加えて
送信しています。(DIBデータ)
VC++で組んでいた時は、DIBを扱う関数で処理していたため上手くいっていました。

C#でMemoryStreamに格納されているDIBデータをPictureBoxに表示するには
どうすればよいのでしょうか? DIB ⇔ Bitmap 関連のメソッドはないのでしょうか?
受信したこのデータに14バイトのBITMAPFILEHEADER(ファイルヘッダー)部分を
手作業で挿入した新規のMemoryStreamを作成するしかないでしょうか?

それから、今まで使用していたBITMAPFILEHEADERのような構造体を
C#で定義したり利用したりできないのですか?
例えば、バッファ領域を確保する場合などに、

sizeof(BITMAPFILEHEADER)

のようにサイズを知りたいのです。

色々質問してすみません。


Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-26 15:38
使えるかどうかは、ご自分で確認してください。検索方法の一例ということで。


 MSDN(VS.NET2003に付属のもの)のキーワード検索タブで、「キーワード」に「dib」、「フィルタ条件」を「.NET Framework」とすると、「Dibフィールド」が出てきました。

 これをクリックして説明を表示し、これの上位であるDataFormatクラスを、「参照」にあるリンクから表示させました。

 そして「解説」にある「DataObject」あたりがあやしいと見当を付け、リンクをクリックしてみると、
引用:

データは GetData と互換性のある任意の形式で DataObject から取得できます。たとえば、テキストは Unicode に変換できます。データが格納されている形式でデータを取得するには、 autoConvert パラメータを false に設定して GetData を呼び出します。


変換してくれそうです。

スキルアップ/キャリアアップ(JOB@IT)