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

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

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

Imaging.BitmapSourceの記述方法について

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■83923 / inTopicNo.1)  Imaging.BitmapSourceの記述方法について
  
□投稿者/ Ark (5回)-(2017/04/24(Mon) 23:19:25)

分類:[C#] 

当方、Visual Studio Community 2017でc#を用いて書いているものです。

昔windowsフォームで作った簡易画像変換ソフトを、WPFで作り直そうとしているのですが、画像処理についてイマイチ分からないため質問させていただます。

string files = ((string[])e.Data.GetData(DataFormats.FileDrop))[0];
string name = Path.GetFileNameWithoutExtension(files);
string directory = Path.GetDirectoryName(files);

Bitmap bmp = new Bitmap(files);
float hRes = bmp.HorizontalResolution;
float vRes = bmp.VerticalResolution;

Bitmap dst = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format48bppRgb);
dst.SetResolution(hRes, vRes);

Graphics gfx = Graphics.FromImage(dst);
gfx.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
dst.Save(directory + "\\" + name + ".bmp", ImageFormat.Bmp);

このDrawing.Imagingで書かれたプログラムと同じ動きをImaging.BitmapSourceで書きたいのですが記述方法がイマイチわかりません。
(参照してDrawing.Imagingの利用はしない方針を取っています)

var uri = new Uri(files, UriKind.Relative);
var bitmap = new BitmapImage(uri);

using (var fs = new FileStream(directory + "\\" + name + ".bmp", FileMode.Create))
{
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(fs);
}

と書いて一応動くには動くのですが、アルファチャンネルを含んでいるpng→bmpとした場合、おかしくなります。

記述方法はこれで問題ないのでしょうか?また、アルファチャンネルの部分は真っ白or真っ黒にする、のような動作はどうすればいいのでしょうか?
引用返信 編集キー/
■83926 / inTopicNo.2)  Re[1]: Imaging.BitmapSourceの記述方法について
□投稿者/ Hongliang (531回)-(2017/04/25(Tue) 13:22:06)
> アルファチャンネルを含んでいるpng→bmpとした場合、おかしくなります。
具体的にどのように「おかしく」なりますか?

> 記述方法はこれで問題ないのでしょうか?
問題ないと言えばないです。
もちろん、元コードと完全に等価ではないですが。
// まあそもそも使うコンポーネントが違うんで完全に等価にはできないと思いますが。
実現したいことができていないのなら、そういう意味では問題あるんでしょう。
実現したいことと現状の結果が分からないので、改善点を挙げることはできませんが。

> また、アルファチャンネルの部分は真っ白or真っ黒にする、のような動作はどうすればいいのでしょうか?
私の理解では、argb32な場合、各ピクセル毎に0-255までの範囲で持っているのがアルファチャネルであるという認識ですが、
「アルファチャネルの部分は真っ白」というのがどういう意味なのかちょっと図りかねます。
引用返信 編集キー/
■83931 / inTopicNo.3)  Re[2]: Imaging.BitmapSourceの記述方法について
□投稿者/ Ark (6回)-(2017/04/25(Tue) 18:53:59)
2017/04/25(Tue) 18:56:04 編集(投稿者)
2017/04/25(Tue) 18:55:19 編集(投稿者)

No83926 (Hongliang さん) に返信
>>アルファチャンネルを含んでいるpng→bmpとした場合、おかしくなります。
> 具体的にどのように「おかしく」なりますか?

上記のコードで実行して使うと、このような感じになります。
https://sukusho.nu/1Fa1

透明な部分をbmpで保存するときに、真っ白、又は真っ黒にして保存できたらいいなと思っています。
引用返信 編集キー/
■83934 / inTopicNo.4)  Re[3]: Imaging.BitmapSourceの記述方法について
□投稿者/ Hongliang (532回)-(2017/04/25(Tue) 20:18:43)
> 上記のコードで実行して使うと、このような感じになります。
> https://sukusho.nu/1Fa1
画像が2個あるように見えるので、どっちがどのような感じなのか…。
どうなるのが正しい結果なのでしょうか。
hogehogeというのが元画像?
下の画像には中途半端な大きさの四角形がありますがこれはどこから?

> 透明な部分をbmpで保存するときに、真っ白、又は真っ黒にして保存できたらいいなと思っています。
完全透明のピクセルについてのみ、色を変えたいと言うことでしょうか。
半透明なピクセルは気にしなくて良い、と。
引用返信 編集キー/
■83937 / inTopicNo.5)  Re[4]: Imaging.BitmapSourceの記述方法について
□投稿者/ Ark (7回)-(2017/04/25(Tue) 21:37:10)
No83934 (Hongliang さん) に返信
>>上記のコードで実行して使うと、このような感じになります。
>>https://sukusho.nu/1Fa1
> 画像が2個あるように見えるので、どっちがどのような感じなのか…。
> どうなるのが正しい結果なのでしょうか。
> hogehogeというのが元画像?
> 下の画像には中途半端な大きさの四角形がありますがこれはどこから?
>
hogehogeと書いてあるのが元の画像です。
そちらを上のコードのプログラムに通すと下のような画像になってしまいます。

>完全透明のピクセルについてのみ、色を変えたいと言うことでしょうか。
>半透明なピクセルは気にしなくて良い、と。

言われてから気が付きました。
おかしくならないようにbmpに変換したいと思います。
引用返信 編集キー/
■83943 / inTopicNo.6)  Re[5]: Imaging.BitmapSourceの記述方法について
□投稿者/ Hongliang (533回)-(2017/04/26(Wed) 12:13:41)
余り見ない現象だな、と思ってペイントソフトで例示されている画像を調べました。
Save後に水色の矩形で塗りつぶされる部分(のうち元々は透明部分)は、A=0,R=76,G=132,B=176となっています。矩形外の部分はA=0,R=255,G=255,B=255でした。
Aが0なので元画像単体で見た場合は矩形部分は完全透過されて表示されますが、BmpBitmapEncoderは、単純にAの値を無視しているようです。なので、BmpBitmapEncoderで保存された画像は、元画像ではA=0のために見えていなかった水色が表に出てくる、ということのようです。

対策としては、System.Drawingと同様に一旦ビットマップを新しいビットマップに描画する、という方法でしょうか。
System.Windows.Media.Imagingでは、以下のような手順で実施します。
1. RenderTargetBitmapをnewする。
※PixelFormatはPixelFormats.Defaultぐらいしか有効ではない。
2. DrawingVisualをnewする。
3. DrawingVisualのRenderOpen()を呼び出してDrawingContextを取得する。
4. DrawingContextを使い、まずDrawRectangle()で背景色を塗りつぶし、その後DrawImage()で元画像を描画する。
 ※描画時のwidth, heightは元画像のPixelWidth/PixelHeightではなく元画像のWidth/Heightを使用する。
5. DrawingContextをCloseする(usingでよい)。
6. RenderTargetBitmapのRender()でDrawingVisualを指定する。
引用返信 編集キー/
■83951 / inTopicNo.7)  Re[6]: Imaging.BitmapSourceの記述方法について
□投稿者/ Ark (8回)-(2017/04/26(Wed) 21:28:26)
No83943 (Hongliang さん) に返信
返信ありがとうございます。

言われたとおりにプログラムを書こうと思ったのですが、理解が足りずに記述方法がわかりませんでした。
まずRenderTargetBitmap bitmap = new RenderTargetBitmap(, , , , PixelFormats.Default);
こちらの引数をどう扱えばいいのかもわかりません。

申し訳ないのですが、代わりに書いていただくことは可能でしょうか?
引用返信 編集キー/
■83955 / inTopicNo.8)  Re[7]: Imaging.BitmapSourceの記述方法について
□投稿者/ Hongliang (535回)-(2017/04/27(Thu) 14:50:11)
がわかりませんでした。
> まずRenderTargetBitmap bitmap = new RenderTargetBitmap(, , , , PixelFormats.Default);
> こちらの引数をどう扱えばいいのかもわかりません。
元画像のBitmapImageのPixelWidth/PixelHeightとDpiX/DpiYを使うだけです。
System.Drawingの時と(プロパティ名とかがちょっと違うけど)やってることは同じですよ?
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ