もくじ
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f
画像に対していろいろやるシリーズ
- 画像に対していろいろ行う(System.Drawing.Bitmap版)
https://qiita.com/tera1707/items/385c9baca83f7c08e5e1 - 画像に対していろいろ行う(System.Windows.Imaging版)
https://qiita.com/tera1707/items/1dfef61ccab7f7e3a381
やりたいこと
WPFの画面表示や画像回りでいろいろやることがあるが、なんだかややこしくて、まとめようと思ってもまとめきれないまま時間が過ぎている。
いきなりまとめるのをちょっとあきらめて、やりたいこと、やったことのレシピ集みたいなのを作って経験値を貯めてから、見えてきたものを後でまとめようと思う。
→主に、System.Drawing.Bitmap
を使って画像をファイルに保存したり、編集したときのことをまずは書く。(あとは、出てきたやつを都度追記していく。)
画像ファイルを開いて、好きな文字やら図形を書き込んで、別のファイルに保存する(その1)
- 元画像ファイル(.bmp等)を
System.Drawing.Bitmap
に格納
-
System.Drawing.Graphics
で格納した画像を編集 - 出力先ファイルへの
FileStream
を作成 -
System.Drawing.Bitmap
のSave
メソッドで、**出力先ファイルへのFileStream
**を指定し保存 - →これで、出力先ファイルに保存される
using (var bmp = new Bitmap(@"input.bmp"))
using (var fs = new FileStream(@"output1.bmp", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var g = Graphics.FromImage(bmp))
{
g.DrawString("あいうえお", new Font("Arial", 16), System.Drawing.Brushes.Red, new PointF(10.0f, 10.0f));
g.DrawRectangle(Pens.Red, new System.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 (var bmp = new Bitmap(@"input.bmp"))
{
using (var g = Graphics.FromImage(bmp))
{
g.DrawString("あいうえお", new Font("Arial", 16), System.Drawing.Brushes.Red, new PointF(10.0f, 10.0f));
g.DrawRectangle(Pens.Red, new System.Drawing.Rectangle(100, 100, 100, 100));
}
// 保存方法② ファイルパス指定で保存 → "output2.bmp"に保存される
bmp.Save(@"output2.bmp");
}
画像ファイルを開いて、好きな文字やら図形を書き込んで、画面に表示する
FileStream
を使うやり方。
using (var bmp = new Bitmap(@"input.bmp"))
using (var fs = new FileStream(@"output1.bmp", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var g = Graphics.FromImage(bmp))
{
g.DrawString("あいうえお", new Font("Arial", 16), System.Drawing.Brushes.Red, new PointF(10.0f, 10.0f));
g.DrawRectangle(Pens.Red, new System.Drawing.Rectangle(100, 100, 100, 100));
}
// 画面に表示 ※MyImageは、xamlに配置された<Image Name="MyImage"/>
var a = BitmapFrame.Create(fs, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
MyImage.Source = a;
}
下記でも、同じことができる。(ファイルをかまさずに、メモリ(MemoryStream
)で済ます)
using (var bmp = new Bitmap(@"input.bmp"))
using (var ms = new MemoryStream())
{
using (var g = Graphics.FromImage(bmp))
{
g.DrawString("あいうえお", new Font("Arial", 16), System.Drawing.Brushes.Red, new PointF(10.0f, 10.0f));
g.DrawRectangle(Pens.Red, new System.Drawing.Rectangle(100, 100, 100, 100));
}
//// MemoryStreamに一旦保存
ms.SetLength(0);
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
// 画面に表示
var a = BitmapFrame.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
MyImage.Source = a;
}
画面表示を取り込んで、ファイルに保存する
以前の記事参照。
→BitmapSourceやその派生クラスから、System.Drawing.Bitmapに変換する
// BitmapSourceの派生クラス「RenderTargetBitmap」で、画像を取ってくる
var canvas = new RenderTargetBitmap((int)MyImage.ActualWidth, (int)MyImage.ActualHeight, 96, 96, PixelFormats.Pbgra32);
canvas.Render(MyImage); // canvasに画像を描画
// BmpBitmapEncoderに画像を入れる
using (var stream = new MemoryStream())
{
// BmpBitmapEncoderに画像を書きこむ(使うBitmapEncoderの派生クラスによって、いろんなフォーマットのファイルを作れる)
//BitmapEncoder encoder = new BmpBitmapEncoder();
BitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(canvas));// canvasからBitmapEncoder に書き込み
encoder.Save(stream);
// BmpBitmapEncoderからSystem.Drawing.Bitmapをつくる
var bitmap = new System.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を画面にセット)
- →おわり
※画面上の画像に四角を書き込む、ということがこれでもできそう。
できそうだが、画面上に四角を出したいなら、xaml上に<Canvas>とその中に<Rectangle/>を置いて、そのWidthやheight、Canvas.TopやCanvas.Bottomをプログラムで制御するほうが絶対いいなと思った。(テキストでも同様(<TextBlock>で。))
// 画面からRenderTargetBitmapに画像を描画
var canvas = new RenderTargetBitmap((int)MyImage.ActualWidth, (int)MyImage.ActualHeight, 96, 96, PixelFormats.Pbgra32);
canvas.Render(MyImage);
using (var stream = new MemoryStream())
{
// MemoryStreamに、RenderTargetBitmapから画像を流し込む
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(canvas));
encoder.Save(stream);
// MemoryStreamからBitmapを作成
var editted = new System.Drawing.Bitmap(stream);
// GraphicsでBitmapを編集(四角を書き込む)
using (var g = Graphics.FromImage(editted))
{
g.DrawRectangle(Pens.Green, new System.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に戻さないと例外
var bitmapSource = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
// それをImageのSourceにセット → 表示!
MyImage.Source = bitmapSource;
}
画像に別の画像を貼り付けて保存する(pngで透過も可)
ある画像に、別の画像を貼り付けて保存する。
貼り付ける側としては.jpg
や.bmp
、.png
などが使えるが、
pngで透過部分がある画像だと、貼り付けるとその部分が透過されるの。
(ロゴマークとかを貼り付けるときに使えそう)
using (var bmp = new Bitmap(@"src.jpg")) // 元の画像
{
using (var g = Graphics.FromImage(bmp)) // 元の画像からGraphicsをつくる
using (var pngbmp = new Bitmap("touka.png")) // 貼り付けたい画像を開く(この場合はpngで、透明部分を透過できる)
{
// 貼り付ける画像を(5,5)の位置に描画する
g.DrawImage(pngbmp, 5, 5, pngbmp.Width, pngbmp.Height);
}
// 保存する
bmp.Save(@"output.bmp");
}
透過部分を含む.pngの作り方
余談だが、実験用の.png
ファイルはエクセルを使って簡単に作れる。
→https://amaotolog.com/excel/42
(エクセルのシートをhtmlとして保存したときの副産物
的な保存のされ方)
参照
いろんな画像関連の型の変換
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で指定してるやつ。
よく出てくるがじつはわかってない。