C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


■87529 / )  Re[3]: Icon について
□投稿者/ 魔界の仮面弁士 (1701回)-(2018/06/01(Fri) 12:04:22)
No87528 (夜叉丸 さん) に返信
> データの後半部分のデータが消えています。
> データサイズが正常な953バイトに対して682バイトしかなかったです。

連続実行させて検証していないので、思いつきになりますが、
> Icon icon = System.Drawing.Icon.FromHandle((new Bitmap(ms)).GetHicon());
HICON からの読み取り中に、Bitmap が Dispose されてしまったとか?
うーん。すぐには思い当たらないです。


>  byte[] ret = ms.GetBuffer();
GetBuffer には、未使用バイト領域が含まれる可能性がありえます。

今回は問題無いとしても、念のため ToArray を使った方が良いと思いますよ。
あるいは TryGetBuffer メソッドでも良いですけど。
http://8thway.blogspot.com/2015/12/memorystream.html


ちなみに、
  MemoryStream ms = new MemoryStream();
  ms.Write(Enumerable.Repeat(byte.MaxValue, 1024).ToArray(), 0, 1024);
  ms.WriteByte(byte.MaxValue);
  int i1 = ms.Capacity;
  int i2 = (int)ms.Length;
  byte[] b1 = ms.GetBuffer();
  byte[] b2 = ms.ToArray();
  ArraySegment<byte> b3; ms.TryGetBuffer(out b3);
  ms.Close();
というコードの場合、
  i1 は 2048 (バッファ長)
  i2 は 1025 (実データ長)
  b1.Length は 2048 (バッファ長)
  b2.Length は 1025 (実データ長)
  b3 は .Offset = 0, .Count = 1025, .Array.Length = 2048
という結果になりますね。



> private byte[] GetBytearrayFromIcon(Icon icon)
>  Bitmap bmp = icon.ToBitmap();

> private Icon GetIconFromByteArray(byte[] bytes)
>  bmp.Save(ms, ImageFormat.Png);

.ico フォーマットではなく .png フォーマットで永続化しているのは、
意図的なものでしょうか。


もしも Ico 形式のまま無加工で永続化するなら、こんな感じで書けそうです。

// 利用方法:
//  byte[] binary = srcIcon.ToBinary();
//  Icon dstIcon = bin.ToIcon();
public static class IconExtensions
{
 public static byte[] ToBinary(this Icon ico)
 {
  using (var ms = new MemoryStream())
  {
   ico.Save(ms);
   ms.Flush();
   return ms.ToArray();
  }
 }

 public static Icon FromBinary(this byte[] binary)
 {
  using (var ms = new MemoryStream(binary))
  {
   try { return new Icon(ms); } catch { return null; }
  }
 }
}



なお、画像の先頭 4 バイト見ることで、.ico / .png の判定ができます。

byte[] bin4 = BinaryOfYourIcon.Take(4).ToArray();
bool isIco = bin4.SequenceEqual(new byte[] { 0x00, 0x00, 0x01, 0x00 });
bool isPng = bin4.SequenceEqual(new byte[] { 0x89, (byte)'P', (byte)'N', (byte)'G' });


.ico 形式の場合、ファイル先頭の 0x00, 0x00, 0x01, 0x00 の後に続く 2 バイトが、
格納されているアイコンの数を表します。

System.Drawing.Icon の場合、それぞれのアイコンを個別に取り出す機能がありませんので、
正確な画像データを得たい場合には No87527 で紹介した IconLib 等を利用してみてください。
返信 編集キー/


管理者用

- Child Tree -