- PR -

Webサービスでビットマップを生成させて、それを戻り値にしたい。

1
投稿者投稿内容
やむ
会議室デビュー日: 2003/08/02
投稿数: 17
投稿日時: 2004-04-21 11:33
ASP.NETで実現している機能をWebサービスに移せるか、いろいろやっているのですが、
文字列やデータセットなどはサンプルも多く、実現できたのですが、画像を渡せません。
戻り値をBitmap にしたWebMethod は、どのように作ったらいいのでしょうか。
もし、作れないとしたら、他にどんな方法あるのでしょうか。
画像のパスを渡すことは、仕様上で不可です。

試しに作ってみたら、「System.Drawing.Bitmap に既定のパブリック コンストラクタが含まれていないため、シリアル化できません。」とエラーがでました。
[WebMethod]
public Bitmap GetImage(){
Bitmap bmp = new Bitmap( "test.jpg" );
return bmp;
}

ASP.NET では、
bmp.Save( Context.Response.OutputStream, Stem.Drawing.Imaging.ImageFormat.Jpeg );
で実現していました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-04-21 11:53
いい加減失礼:

ビットマップをメモリストリームにセーブして、それをバイト配列に取り込めば、一応シリアル化はできる。あとはどうやって「ビットマップ」であることをXML上で表現するか・・・

受取手があらかじめ「ビットマップ」であることがわかっているなら、受け取った文字列をバイト配列に変換し、メモリストリームに流し込んで、メモリストリームからビットマップを生成する。
やむ
会議室デビュー日: 2003/08/02
投稿数: 17
投稿日時: 2004-04-21 16:09

> 受取手があらかじめ「ビットマップ」であることがわかっているなら、受け取った文字列をバイト配列に変換し、メモリストリームに流し込んで、メモリストリームからビットマップを生成する。

これは一度やってみたのですが、なんかちょっと違うと思ってやめました。

[WebMethod]
public byte[] GetImageBytes(){
FileStream fs = new FileStream( "test.jpg", FileMode.Open, FileAccess.Read );
fs.Seek( 0, System.IO.SeekOrigin.Begin );
int size = (int)fs.Length;
byte[] buf = new byte[size];
fs.Read( buf, 0, buf.Length );
fs.Close();
return buf;
}

こうすると、利用側もbyte[]で受けてBitmapに渡すと、ちゃんと画像を
表示できますが、戻り値が、byte[] なのが気に入りません。
他に方法がないのなら諦めますが・・・。

1:Jittaさんも書いてらっしゃいますが、「あとはどうやって「ビットマップ」であることをXML上で表現するか・・・ 」が、分かりません。

2:
Bitmap bmp = new Bitmap( "test.jpg" );
が、最初に書いたようなエラーになってしまいます。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-04-22 08:42
引用:

やむさんの書き込み (2004-04-21 16:09) より:

1:Jittaさんも書いてらっしゃいますが、「あとはどうやって「ビットマップ」であることをXML上で表現するか・・・ 」が、分かりません。

2:
Bitmap bmp = new Bitmap( "test.jpg" );
が、最初に書いたようなエラーになってしまいます。


1:
 これはXML中にそう記述する、でしょうね。
<MyNS:bitmap filename="test.jpg">Encorded data</MyNS:bitmap>
とか、
<MyNS:binary type="bitmap" filename="test.jpg">Encorded data</MyMS:binary>
とか。。。


2:
Bitmap bmp = new Bitmap( "test.jpg" );ではなく、returnでは?
規定のコンストラクタ・・・引数なしのコンストラクタのことかな?それとも、シリアル解除する為のコンスタラクタかな?どっちもないけど。あれ?でも、これの基本クラスがISerializableを実装しているぞ?ということは、バイナリシリアライズが出来ると思います。
System.Runtime.Serialization.Formatters.Soap.SoapFormatter
を使って、文字列(というか、SOAP形式のXML)にシリアライズしてみてください。

 詳しくはMSDNページを。とりあえずやってみるなら、下の「www」リンクから私のページへいって、「.NET FrameworkおよびVS.NETに関するTips」の、「クラスをXML化する」(書きかけ)へ。
やむ
会議室デビュー日: 2003/08/02
投稿数: 17
投稿日時: 2004-04-22 14:19

Jittaさん、ありがとうございます。サイトを参考にさせて頂きました。
ありがとうございます。

2: 確かに Bitmap bmp = new Bitmap("test.jpg");ではなく、return bmp;
でした。
また、アドバイス頂いたとおり、"文字列(というか、SOAP形式のXML)"に変換し、byte[]を返すようにしてみました。

[WebMethod]
public byte[] GetBmpSoap(){
Bitmap bmp = new Bitmap( "test.jpg" );
MemoryStream ms = new MemoryStream();
IFormatter fmt = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();

fmt.Serialize( ms, bmp );

byte[] buf = new byte[(int)ms.Length];
ms.Seek( 0, System.IO.SeekOrigin.Begin );
ms.Read( buf, 0, buf.Length );
ms.Close();
return buf;
}

で、受け側で逆シリアライズすると確かにBitmapに戻ります。
が、これが画像などバイナリデータをSOAPで送る時のあるべき姿なんでしょうか。

[WebMethod]
public byte[] GetBmpSoap(){
FileStream fs = new FileStream( "test.jpg", FileMode.Open, FileAccess.Read );
fs.Seek( 0, System.IO.SeekOrigin.Begin );
int size = (int)fs.Length;
byte[] buf = new byte[size];
fs.Read( buf, 0, buf.Length );
fs.Close();
return buf;
}
このようにシリアライズしなくても、Bitmapを送れます。もちろん受け側でも逆シリアライズしません。
Bitmap をSOAPのXMLに変換するメリットって何?って思ってしまいました。

 
1:
引用:

 これはXML中にそう記述する、でしょうね。
<MyNS:bitmap filename="test.jpg">Encorded data</MyNS:bitmap>
とか、
<MyNS:binary type="bitmap" filename="test.jpg">Encorded data</MyMS:binary>
とか。。。



これを、環境というか、.NETがやってくれるんだと思ってました。DataSet の WriteXml() のような感覚でいたのですが、甘かった?


結局、「Bitmap を戻り値にはできない」ということですか。
dai
ベテラン
会議室デビュー日: 2001/08/28
投稿数: 85
投稿日時: 2004-04-22 14:40
> が、これが画像などバイナリデータをSOAPで送る時のあるべき姿なんでしょうか。

僕も前に色々調べたときに、結局ここに行き着いた気がします。
byte は立派な解のひとつでしょう。
ただ、Remoting の場合は、MarshalByRef の参照として、ネットワーク越しに渡せたような..。

興味があれば、Web Services Enhancements (WSE) を調べてみるとよいかもしれません。
DIME や WS-Attachments なんかが、バイナリデータをSOAPとは別ルートで転送する手段だったはずです。

#1,2年前の調査なのでもう時代が変わってる可能性がありますが...。
やむ
会議室デビュー日: 2003/08/02
投稿数: 17
投稿日時: 2004-04-22 14:51

> これを、環境というか、.NETがやってくれるんだと思ってました。DataSet
> の WriteXml() のような感覚でいたのですが、甘かった?

なんて書きましたが、受け側でデータを見ると

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:Bitmap id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/System.Drawing/System.Drawing%2C%20Version%3D1.0.5000.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db03f5f7f11d50a3a">
<Data href="#ref-3"/>
</a1:Bitmap>
<SOAP-ENC:Array id="ref-3" xsi:type="SOAP-ENC:base64">wB/DAAkGBwgHBgkIBwKCgkDhcPgwMDhUFRAXIR0
・・・
Bib1/vD86TevqPzoAN6+o/OkLr/eH5f//Z</SOAP-ENC:Array>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

ということで、SOAPの封筒部分は、作ってくれていました。

やむ
会議室デビュー日: 2003/08/02
投稿数: 17
投稿日時: 2004-04-24 22:12

Jittaさん、daiさん、ありがとうございます。
これで進めていきます。
1

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