もくじ
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f
やりたいこと
WPFの画面表示や画像回りでいろいろやることがあるが、なんだかややこしくて、まとめようと思ってもまとめきれないまま時間が過ぎている。
いきなりまとめるのをちょっとあきらめて、やりたいこと、やったことのレシピ集みたいなのを作って経験値を貯めてから、見えてきたものを後でまとめようと思う。
→主に、System.Drawing.Bitmap
を使って画像をファイルに保存したり、編集したときのことをまずは書く。(あとは、出てきたやつを都度追記していく。)
画像ファイルを開いて、好きな文字やら図形を書き込んで、別のファイルに保存する(その1)
- 元画像ファイル(.bmp等)を
System.Drawing.Bitmap
に格納 System.Drawing.Graphics
で格納した画像を編集- 出力先ファイルへの
FileStream
を作成 System.Drawing.Bitmap
のSave
メソッドで、出力先ファイルへのFileStream
を指定し保存- →これで、出力先ファイルに保存される
using(varbmp=newBitmap(@"input.bmp"))using(varfs=newFileStream(@"output1.bmp",FileMode.OpenOrCreate,FileAccess.ReadWrite)){using(varg=Graphics.FromImage(bmp)){g.DrawString("あいうえお",newFont("Arial",16),System.Drawing.Brushes.Red,newPointF(10.0f,10.0f));g.DrawRectangle(Pens.Red,newSystem.Drawing.Rectangle(100,100,100,100));}// 保存方法① streamで保存 → "output1.bmp"に保存されるfs.SetLength(0);bmp.Save(fs,System.Drawing.Imaging.ImageFormat.Bmp);}
※fs(ファイルストリーム)がClose=Disposeされた時点(つまり、usingを抜けた時点)で、実際にbmpファイルに書き出される。
画像ファイルを開いて、好きな文字やら図形を書き込んで、別のファイルに保存する(その2)
- 元画像ファイル(.bmp等)を
System.Drawing.Bitmap
に格納 System.Drawing.Graphics
で格納した画像を編集System.Drawing.Bitmap
のSave
メソッドで、出力先ファイルのパスを指定し保存- →これで、出力先ファイルに保存される
using(varbmp=newBitmap(@"input.bmp")){using(varg=Graphics.FromImage(bmp)){g.DrawString("あいうえお",newFont("Arial",16),System.Drawing.Brushes.Red,newPointF(10.0f,10.0f));g.DrawRectangle(Pens.Red,newSystem.Drawing.Rectangle(100,100,100,100));}// 保存方法② ファイルパス指定で保存 → "output2.bmp"に保存されるbmp.Save(@"output2.bmp");}
画像ファイルを開いて、好きな文字やら図形を書き込んで、画面に表示する
FileStream
を使うやり方。
using(varbmp=newBitmap(@"input.bmp"))using(varfs=newFileStream(@"output1.bmp",FileMode.OpenOrCreate,FileAccess.ReadWrite)){using(varg=Graphics.FromImage(bmp)){g.DrawString("あいうえお",newFont("Arial",16),System.Drawing.Brushes.Red,newPointF(10.0f,10.0f));g.DrawRectangle(Pens.Red,newSystem.Drawing.Rectangle(100,100,100,100));}// 画面に表示 ※MyImageは、xamlに配置された<Image Name="MyImage"/>vara=BitmapFrame.Create(fs,BitmapCreateOptions.None,BitmapCacheOption.OnLoad);MyImage.Source=a;}
下記でも、同じことができる。(ファイルをかまさずに、メモリ(MemoryStream
)で済ます)
using(varbmp=newBitmap(@"input.bmp"))using(varms=newMemoryStream()){using(varg=Graphics.FromImage(bmp)){g.DrawString("あいうえお",newFont("Arial",16),System.Drawing.Brushes.Red,newPointF(10.0f,10.0f));g.DrawRectangle(Pens.Red,newSystem.Drawing.Rectangle(100,100,100,100));}//// MemoryStreamに一旦保存ms.SetLength(0);bmp.Save(ms,System.Drawing.Imaging.ImageFormat.Bmp);// 画面に表示vara=BitmapFrame.Create(ms,BitmapCreateOptions.None,BitmapCacheOption.OnLoad);MyImage.Source=a;}
画面表示を取り込んで、ファイルに保存する
以前の記事参照。
→BitmapSourceやその派生クラスから、System.Drawing.Bitmapに変換する
// BitmapSourceの派生クラス「RenderTargetBitmap」で、画像を取ってくるvarcanvas=newRenderTargetBitmap((int)MyImage.ActualWidth,(int)MyImage.ActualHeight,96,96,PixelFormats.Pbgra32);canvas.Render(MyImage);// canvasに画像を描画// BmpBitmapEncoderに画像を入れるusing(varstream=newMemoryStream()){// BmpBitmapEncoderに画像を書きこむ(使うBitmapEncoderの派生クラスによって、いろんなフォーマットのファイルを作れる)//BitmapEncoder encoder = new BmpBitmapEncoder();BitmapEncoderencoder=newJpegBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(canvas));// canvasからBitmapEncoder に書き込みencoder.Save(stream);// BmpBitmapEncoderからSystem.Drawing.Bitmapをつくるvarbitmap=newSystem.Drawing.Bitmap(stream);bitmap.Save(@".\out.jpeg");}
画面表示を取り込んで、画像に四角を書き込んで、それをもう一回画面に表示する
ややこしい。下記のようなクラスを経由していく流れ。
- RenderTargetBitmap(画面から画像の取り込み)
- BmpBitmapEncoder(RenderTargetBitmapをMemoryStreamに流し込む)
- MemoryStream(編集前の画像が流れてる)
- System.Drawing.Bitmap(MemoryStreamからBitmap作成)
- Graphics(BitmapをGraphicsで編集)
- MemoryStream(編集後の画像が流れてる)
- BitmapFrame(MemoryStreamからBitmapFrameを作成)
- Image.Source(BitmapFrameを画面にセット)
- →おわり
// 画面からRenderTargetBitmapに画像を描画varcanvas=newRenderTargetBitmap((int)MyImage.ActualWidth,(int)MyImage.ActualHeight,96,96,PixelFormats.Pbgra32);canvas.Render(MyImage);using(varstream=newMemoryStream()){// MemoryStreamに、RenderTargetBitmapから画像を流し込むBitmapEncoderencoder=newBmpBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(canvas));encoder.Save(stream);// MemoryStreamからBitmapを作成vareditted=newSystem.Drawing.Bitmap(stream);// GraphicsでBitmapを編集(四角を書き込む)using(varg=Graphics.FromImage(editted)){g.DrawRectangle(Pens.Green,newSystem.Drawing.Rectangle(3,3,200,200));}// →この時点で、editted(Bitmap)に緑の四角が書き込まれてる// Streamはまだ。// 四角を書き込んだ画像をstreamに流し込むeditted.Save(stream,System.Drawing.Imaging.ImageFormat.Bmp);editted.Dispose();// MemoryStreamからBitmapを作成から、BitmapFrame(BitmapSourceの子クラス)を作成stream.Seek(0,SeekOrigin.Begin);// seekでBeginに戻さないと例外varbitmapSource=BitmapFrame.Create(stream,BitmapCreateOptions.None,BitmapCacheOption.OnLoad);// それをImageのSourceにセット → 表示!MyImage.Source=bitmapSource;}
参照
いろんな画像関連の型の変換
https://qiita.com/YSRKEN/items/a24bf2173f0129a5825c
これで画像に四角とか書き足す、できんか?(System.Drawingではないやつで)
https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/graphics-multimedia/painting-with-images-drawings-and-visuals
しらべたいこと
PixelFormats.Pbgra32 ってなに?
https://water2litter.net/gin/?p=987でやってるCreateで指定してるやつ。
よく出てくるがじつはわかってない。