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

わんくま同盟

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

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

ツリー一括表示

Icon について /夜叉丸 (18/05/30(Wed) 15:12) #87523
Re[1]: Icon について /Hongliang (18/05/30(Wed) 15:34) #87525
│└ Re[2]: Icon について /Hongliang (18/05/30(Wed) 17:24) #87526
Re[1]: Icon について /Jitta (18/05/30(Wed) 15:24) #87524
Re[1]: Icon について /魔界の仮面弁士 (18/05/31(Thu) 10:47) #87527
  └ Re[2]: Icon について /夜叉丸 (18/06/01(Fri) 08:49) #87528
    └ Re[3]: Icon について /魔界の仮面弁士 (18/06/01(Fri) 12:04) #87529
      └ Re[4]: Icon について /夜叉丸 (18/06/01(Fri) 14:20) #87530
        └ Re[5]: Icon について /魔界の仮面弁士 (18/06/01(Fri) 14:38) #87531
          └ Re[6]: Icon について /夜叉丸 (18/06/04(Mon) 09:18) #87538
            └ Re[7]: Icon について /魔界の仮面弁士 (18/06/04(Mon) 09:55) #87539
              └ Re[8]: Icon について /夜叉丸 (18/06/04(Mon) 17:42) #87544
                ├ Re[9]: Icon について /shu (18/06/06(Wed) 06:45) #87560
                │└ Re[10]: Icon について /夜叉丸 (18/06/06(Wed) 10:48) #87565 解決済み
                └ Re[9]: Icon について /Jitta (18/06/06(Wed) 20:50) #87569 解決済み


親記事 / ▼[ 87525 ] ▼[ 87524 ] ▼[ 87527 ]
■87523 / 親階層)  Icon について
□投稿者/ 夜叉丸 (110回)-(2018/05/30(Wed) 15:12:06)

分類:[C#] 

MemoryStream ms;
Icon icon;
icon.Save(ms);
Byte[] bytes = ms.ToArray();
ms.Close();

にて Byte[] が取得できるのですが、

MemoryStream ms = new MemoryStream(bytes);
icon.Load(ms);
ms.Close();

のように icon.Load する方法がみつかりません。
どのようにすればよいのでしょうか?

目的は、Icon → byte[] , byte[] → Icon
の双方向変換したいのです。


[ □ Tree ] 返信 編集キー/

▲[ 87523 ] / ▼[ 87526 ]
■87525 / 1階層)  Re[1]: Icon について
□投稿者/ Hongliang (644回)-(2018/05/30(Wed) 15:34:29)
.NETの標準ライブラリには、画像処理ライブラリとしてSystem.Drawing (GDI+) とSystem.Windows.Media.Imaging (WIC) の2つが用意されていますが、両方ともico形式へのエンコーダはサポートされていません。
そのため、System.Drawing.Iconオブジェクトを保存しようとしてもpngやbmp形式でしか保存できず、読み込む際はBitmapオブジェクトにしかできません(icon.Save(ms)はpng形式での保存になります)。
一応、BitmapオブジェクトからはGetHiconを使ったアイコンハンドル経由でIconオブジェクトを作成できますが、色がすごく劣化するのでお勧めできません。

目的のアイコンが元々ファイル等のバイナリであるなら、まず一旦byte[]に読み込んでおき、Iconが必要な時にbyte[]から(MemoryStream経由で)読み込む、逆方向はやらない(バイナリが必要ならbyte[]を使う)、というのが一案。
それがご希望のシナリオに沿わないのであれば、何らかの外部ライブラリを使用することになるでしょう。とりあえずはNugetパッケージマネージャでiconって入れて探してみるとか。
[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87525 ] / 返信無し
■87526 / 2階層)  Re[2]: Icon について
□投稿者/ Hongliang (645回)-(2018/05/30(Wed) 17:24:29)
すいません、訂正です。
Icon.Saveはico形式で保存できますね。
読込もnew Icon(Stream)で大丈夫です(MemoryStreamの場合Positionに注意)。

Bitmapオブジェクトをico形式で保存することができない、というのとごっちゃになっていました。
[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87523 ] / 返信無し
■87524 / 1階層)  Re[1]: Icon について
□投稿者/ Jitta (377回)-(2018/05/30(Wed) 15:24:02)
Icon に Stream を受け取るコンストラクタがあるけど?
[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87523 ] / ▼[ 87528 ]
■87527 / 1階層)  Re[1]: Icon について
□投稿者/ 魔界の仮面弁士 (1700回)-(2018/05/31(Thu) 10:47:13)
No87523 (夜叉丸 さん) に返信
> 目的は、Icon → byte[] , byte[] → Icon
> の双方向変換したいのです。

無加工永続化なら、MemoryStream だけで OK でしょう。

アイコンの動的生成や加工が必要なら、IconLib あたりで。
https://www.codeproject.com/Articles/16178/IconLib-Icons-Unfolded-MultiIcon-and-Windows-Vista
http://bbs.wankuma.com/index.cgi?mode=al2&namber=86110&KLOG=147

[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87527 ] / ▼[ 87529 ]
■87528 / 2階層)  Re[2]: Icon について
□投稿者/ 夜叉丸 (111回)-(2018/06/01(Fri) 08:49:16)
2018/06/01(Fri) 10:20:31 編集(投稿者)
2018/06/01(Fri) 09:38:39 編集(投稿者)
2018/06/01(Fri) 08:51:29 編集(投稿者)

<pre><pre>Icon→byte[]
private byte[] GetBytearrayFromIcon(Icon icon)
{
 MemoryStream ms = new MemoryStream();
 Bitmap bmp = icon.ToBitmap();
 bmp.Save(ms, ImageFormat.Png);
 byte[] ret = ms.GetBuffer();
 ms.Close();
 return (ret);
}

private Icon GetIconFromByteArray(byte[] bytes)
{
 try
 {
  MemoryStream ms = new MemoryStream(bytes);
  Icon icon = System.Drawing.Icon.FromHandle((new Bitmap(ms)).GetHicon());
  ms.Close();
  return (icon);
 }
 catch
 {
  return (null);
 }
}

以上のようにしてアイコン←→Byte[] の変換をすることができました

[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87528 ] / ▼[ 87530 ]
■87529 / 3階層)  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 等を利用してみてください。
[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87529 ] / ▼[ 87531 ]
■87530 / 4階層)  Re[4]: Icon について
□投稿者/ 夜叉丸 (112回)-(2018/06/01(Fri) 14:20:53)
No87529 (魔界の仮面弁士 さん) に返信

> 連続実行させて検証していないので、思いつきになりますが、
>>Icon icon = System.Drawing.Icon.FromHandle((new Bitmap(ms)).GetHicon());
> HICON からの読み取り中に、Bitmap が Dispose されてしまったとか?
> うーん。すぐには思い当たらないです。
>
すみません。アイコンから取得したデータは正常でした。
データを保存するところに問題がありました。

>
> GetBuffer には、未使用バイト領域が含まれる可能性がありえます。
>
> 今回は問題無いとしても、念のため ToArray を使った方が良いと思いますよ。
> あるいは TryGetBuffer メソッドでも良いですけど。
> http://8thway.blogspot.com/2015/12/memorystream.html
>
ms.GetBuffer() → ms.ToArray()
に変更しました。
(VisualStudio2017 C# .Net) ですが、ms.TryGetBuffer()は存在しなかったです。

>
> .ico フォーマットではなく .png フォーマットで永続化しているのは、
> 意図的なものでしょうか。
>
意図しているものではなくて
サンプルで引っ張ってきたもの(http://4423lab.wpblog.jp/archives/170)を使用しました。


>
> もしも Ico 形式のまま無加工で永続化するなら、こんな感じで書けそうです。
>
> // 利用方法:
> //  byte[] binary = srcIcon.ToBinary();
> //  Icon dstIcon = bin.ToIcon();

bin は byte[] = binary だと思うのですが
(VisualStudio2017 C# .Net) ですが、bin.ToIcon() は使えませんでした。


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

現状では複数存在したとしてもどれを選べばよいかの
条件判断ができないので、デフォルトで入ってくるアイコンでとりあえずは充分です。

試しにIconLibを使ってアイコンを取得する方法も試してみます。

[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87530 ] / ▼[ 87538 ]
■87531 / 5階層)  Re[5]: Icon について
□投稿者/ 魔界の仮面弁士 (1702回)-(2018/06/01(Fri) 14:38:02)
No87530 (夜叉丸 さん) に返信
> (VisualStudio2017 C# .Net) ですが、ms.TryGetBuffer()は存在しなかったです。
TryGetBuffer は、.NET Framework 4.6 で追加されたメソッドです。
現在のプロジェクトのターゲット フレームワークは何になっていますか?


> サンプルで引っ張ってきたもの(http://4423lab.wpblog.jp/archives/170)を使用しました。
最初の質問は
 icon.Save(ms);
 Byte[] bytes = ms.ToArray();
だったのに、何故変更したのかな…と思っていました。


> bin は byte[] = binary だと思うのですが
> (VisualStudio2017 C# .Net) ですが、bin.ToIcon() は使えませんでした。

ありゃ、済みません。先の拡張メソッドのサンプルの
 public static Icon FromBinary(this byte[] binary) { … }
の部分を
 public static Icon ToIcon(this byte[] binary) { … }
にリネームしておいてください。
[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87531 ] / ▼[ 87539 ]
■87538 / 6階層)  Re[6]: Icon について
□投稿者/ 夜叉丸 (113回)-(2018/06/04(Mon) 09:18:12)
No87531 (魔界の仮面弁士 さん) に返信
.net のバージョンは4.5 でした。
プロジェクトのただ、ターゲットフレームワークでの
バージョンは 4.0を設定しています。

なぜ ToArray を変更したのか
最初自力でやった時には配列にするから一般的な ToArray を使ったのですが
うまくいかなかったので、ネットからそのまま持ってきたときに
変更したのだと思います。

最後に
このバイナリデータを WebBrowseer に直接表示させる方法はありますか?
現状では一時フォルダ Temp を作成して
File.WriteAllBytes でファイル出力してから Navigate にファイル名を
指定して表示させています。


[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87538 ] / ▼[ 87544 ]
■87539 / 7階層)  Re[7]: Icon について
□投稿者/ 魔界の仮面弁士 (1704回)-(2018/06/04(Mon) 09:55:08)
No87538 (夜叉丸 さん) に返信
> このバイナリデータを WebBrowseer に直接表示させる方法はありますか?

webBrowser1.ScrollBarsEnabled = false;
using (var stm = new MemoryStream())
{
 ico.Save(stm);
 stm.Flush();

 var sb = new StringBuilder("<style>html,body{{padding:0;margin:0}}</style>");
 sb.Append("<IMG src='data:image/x-icon;base64,");
 sb.Append(Convert.ToBase64String(stm.ToArray()));
 webBrowser1.DocumentText = sb.Append("'/>").ToString();
}
[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87539 ] / ▼[ 87560 ] ▼[ 87569 ]
■87544 / 8階層)  Re[8]: Icon について
□投稿者/ 夜叉丸 (114回)-(2018/06/04(Mon) 17:42:32)
No87539 (魔界の仮面弁士 さん) に返信

DataTableに ICON,NAME, DATA の列があり、
それぞれ byte[], string, byte[] になっています。
NAMEにはファイル名が入っています。
DATAにはファイルのデータが入っています。

アイコンの方は DrrawImage で名前とともに一覧表示するようにしました。
その一覧から選択をしたときに、WBにデータを表示します。
Data には TXTとかPDFとかイメージとかいろいろなデータが含まれています。
これらを表示するためにはどうすればよいのでしょうか?
わからないままに
IMG src → TXT src とか変更してテキストを表示しようとしたり
してみたのですが表示されませんでした。
データを渡すだけで自動で表示されるのかとも思い
sb.Append(Convert.ToBase64String(stm.ToArray()));
だけにしてみましたが、やはり表示されませんでした。


[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87544 ] / ▼[ 87565 ]
■87560 / 9階層)  Re[9]: Icon について
□投稿者/ shu (1121回)-(2018/06/06(Wed) 06:45:40)
No87544 (夜叉丸 さん) に返信
> ■No87539 (魔界の仮面弁士 さん) に返信
>
> DataTableに ICON,NAME, DATA の列があり、
> それぞれ byte[], string, byte[] になっています。
> NAMEにはファイル名が入っています。
> DATAにはファイルのデータが入っています。
>
> アイコンの方は DrrawImage で名前とともに一覧表示するようにしました。
> その一覧から選択をしたときに、WBにデータを表示します。
> Data には TXTとかPDFとかイメージとかいろいろなデータが含まれています。
> これらを表示するためにはどうすればよいのでしょうか?
いろいろなデータがどんな形式であるのか特定する情報がまず必要となると思います。

次に形式毎にどのようにDataを可視化するかを決める必要があります。

それからその手段を探るとよいと思います。

[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87560 ] / 返信無し
■87565 / 10階層)  Re[10]: Icon について
□投稿者/ 夜叉丸 (121回)-(2018/06/06(Wed) 10:48:04)
No87560 (shu さん) に返信
要するに一筋縄ではいかないということですね。
やはり、一度ファイルを作業フォルダに作成してから
ファイル名を指定するほうがよいということですね。

ありがとうございました。


解決済み
[ 親 87523 / □ Tree ] 返信 編集キー/

▲[ 87544 ] / 返信無し
■87569 / 9階層)  Re[9]: Icon について
□投稿者/ Jitta (378回)-(2018/06/06(Wed) 20:50:10)
No87544 (夜叉丸 さん) に返信
>
> DataTableに ICON,NAME, DATA の列があり、
> それぞれ byte[], string, byte[] になっています。
> NAMEにはファイル名が入っています。
> DATAにはファイルのデータが入っています。
>
> アイコンの方は DrrawImage で名前とともに一覧表示するようにしました。
> その一覧から選択をしたときに、WBにデータを表示します。
> Data には TXTとかPDFとかイメージとかいろいろなデータが含まれています。
> これらを表示するためにはどうすればよいのでしょうか?
> わからないままに
> IMG src → TXT src とか変更してテキストを表示しようとしたり
> してみたのですが表示されませんでした。
> データを渡すだけで自動で表示されるのかとも思い
> sb.Append(Convert.ToBase64String(stm.ToArray()));
> だけにしてみましたが、やはり表示されませんでした。
>
>
 あなたは、一体、何をしたいのでしょうか。
プログラムを作っているわけですが、プログラムって、何ですか?
あなたは、ここ、ウェブ上の掲示板で、会ったこともない人に、何かを聞こうとしているわけですが、プログラムも一緒です。
あなたのことを全く知らない、コンピュータというものに、あなたがしたいことを伝えるのが、プログラムです。

なんだか、あなたは知っているけど、他の人は知らないことを、「自分は知っているから」と、説明を端折っているように思います。
あなたの隣にいる人は、普段のあなたの行動という情報から、あなたのしたいことをある程度理解してくれるでしょう。
ウェブの向こうにいる人も、提示されている内容や、自分の経験から類推するでしょう。
しかし、コンピュータは、今はやりの言葉で言うと忖度することも、推測することもしません。
言われた=プログラムしてあることをその通りに実行します。

ということは、あなた=プログラマーは、プログラムのある時点でコンピュータが理解していることを理解して、
するべき事をなすために必要な情報がそろっているか、考えなければなりません。
こういう場でされている多くの質問は、プログラマーが、コンピュータが理解している情報を理解していないために発生しています。

質問を投稿する前に、自分が知っていることを整理してみてください。
尋ねたいことを整理してみてください。
投稿欄にいきなり書くのではなく、メモ帳などに一度書いて、数十分後にもう一度読み直してみてください。
そして、自分のことを全く知らない人が読んだときに、自分が書いたことを理解できるかどうか、確認してみてください。
「そんなに時間を掛けられない」と、返答されたことがあります。
しかし、こういう時間を掛けた方が、いきなり投稿するより、トータルとして短い時間で解決に至ることでしょう。


> アイコンの方は DrrawImage で名前とともに一覧表示するようにしました。
> その一覧から選択をしたときに、WBにデータを表示します。
> Data には TXTとかPDFとかイメージとかいろいろなデータが含まれています。
> これらを表示するためにはどうすればよいのでしょうか?

WBってなんですか。WebBrowser コントロール?
いろいろなデータが含まれていて、それを、どのように表示したいのですか?
バイト配列を表示したい?PDFなら文字列として、画像なら画像として表示したい、ということ?
いろいろ抜けてますよね。
解決済み
[ 親 87523 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -