SharpDxを利用して、読み込んだ画像を画面表示し、再度画像データにして保存します。
ネットで検索しましたが、SharpDX.Direct2D1.BitmapRenderTargetで保持したデータを画像ファイルに保存するサンプルがなく非常に苦労しました。
サンプルでは、SharpDX.Direct2D1.BitmapRenderTargetからSharpDX.Direct2D1.WicRenderTargetに変換してから画像ファイルに保存します。
1.使用した画像
以下は、読み込んだ画像です。
以下は、書き込んだ画像で、背景を水色に変更し、サイズを半分にしています。
2.参考ソース
以下参考ソースです。
初期処理
初期処理では、画像に表示するためのWinRenderTargetを作成します。
注意点は、WinRenderTargetを作成するための引数であるRenderTargetPropertiesに、RenderTargetType.Softwareを指定する点です。
※Software以外はエラーになります。
また、画像保存処理でも、同じRenderTargetPropertiesを利用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
using SD = System.Drawing; using SDX = SharpDX; using SDX2D = SharpDX.Direct2D1; using SDXDW = SharpDX.DirectWrite; using SDXWin = SharpDX.Windows; using SDXMath = SharpDX.Mathematics.Interop; public void Initialize(Control control) { this.Factory2D = new SDX2D.Factory(); var hrtProps = new SDX2D.HwndRenderTargetProperties(); hrtProps.Hwnd = control.Handle; hrtProps.PixelSize = new SDX.Size2(control.ClientSize.Width, control.ClientSize.Height); hrtProps.PresentOptions = SDX2D.PresentOptions.None; this.RenderTargetProps = new SDX2D.RenderTargetProperties( SDX2D.RenderTargetType.Software, new SDX2D.PixelFormat(SDX.DXGI.Format.Unknown, SDX2D.AlphaMode.Unknown), 0, 0, SDX2D.RenderTargetUsage.None, SDX2D.FeatureLevel.Level_DEFAULT); this.WinRenderTarget = new SDX2D.WindowRenderTarget(Factory2D, this.RenderTargetProps, hrtProps); this.WinRenderTarget.AntialiasMode = SDX2D.AntialiasMode.PerPrimitive; this.WinRenderTarget.TextAntialiasMode = SDX2D.TextAntialiasMode.Cleartype; } |
画像読み込み
画像を読み込んで、SharpDX.Direct2D1.Bitmap型に変換します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public SDX2D.Bitmap LoadFromFile(string filename) { var bmp = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(filename); var bmpData = bmp.LockBits( new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); var stream = new SharpDX.DataStream(bmpData.Scan0, bmpData.Stride * bmpData.Height, true, false); var pFormat = new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, SDX2D.AlphaMode.Premultiplied); var bmpProps = new SharpDX.Direct2D1.BitmapProperties(pFormat); var result = new SharpDX.Direct2D1.Bitmap( this.WinRenderTarget, new SharpDX.Size2(bmp.Width, bmp.Height), stream, bmpData.Stride, bmpProps); bmp.UnlockBits(bmpData); stream.Dispose(); bmp.Dispose(); return result; } |
画像の表示
読み込んだ、SharpDX.Direct2D1.Bitmap型のデータを、一旦バッファ(BmpRenderTarget)に格納し、バッファのデータを画像に表示するためのWinRenderTargetにドローし、画面に表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public SDX2D.Bitmap DrawBitmap(SDX2D.Bitmap bitmap) { int width = (int)bitmap.Size.Width; int height = (int)bitmap.Size.Height; this.BmpRenderTarget = new SDX2D.BitmapRenderTarget(this.WinRenderTarget, SDX2D.CompatibleRenderTargetOptions.None, new SDX.Size2F(bitmap.Size.Width, bitmap.Size.Height), null, null); this.BmpRenderTarget.BeginDraw(); this.BmpRenderTarget.Clear(SDX.Color.LightBlue); this.BmpRenderTarget.DrawBitmap(bitmap, new SDX.RectangleF(0f, 0f, bitmap.Size.Width, bitmap.Size.Height), 1.0f, SDX2D.BitmapInterpolationMode.NearestNeighbor); this.BmpRenderTarget.EndDraw(); this.WinRenderTarget.BeginDraw(); this.WinRenderTarget.Clear(SDX.Color.White); this.WinRenderTarget.DrawBitmap(this.BmpRenderTarget.Bitmap, new SDX.RectangleF(0f, 0f, bitmap.Size.Width, bitmap.Size.Height), 1.0f, SDX2D.BitmapInterpolationMode.NearestNeighbor); this.WinRenderTarget.EndDraw(); return this.BmpRenderTarget.Bitmap; } |
画像ファイルへの保存
初期処理で作成したRenderTargetPropertiesを利用し、画像保存用のWicRenderTargetを作成します。
その後、WicRenderTargetに対し、読み込んだ、SharpDX.Direct2D1.Bitmap型のデータを、縮小ドローし、SharpDX.WIC.Bitmap型に格納します。
その後、SharpDX.WIC.Bitmap型->byte[]->System.Drawing.Bitmap型に変換し、
画像ファイルに保存します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public void SaveFile(SDX2D.Bitmap bitmap, string filename) { int width = (int)this.BmpRenderTarget.Bitmap.Size.Width; int height = (int)this.BmpRenderTarget.Bitmap.Size.Height; this.WicFactory = new SDX.WIC.ImagingFactory(); this.WicBitmap = new SDX.WIC.Bitmap(this.WicFactory, width, height, SDX.WIC.PixelFormat.Format32bppBGR, SDX.WIC.BitmapCreateCacheOption.CacheOnLoad); this.WicRenderTarget = new SDX2D.WicRenderTarget(this.Factory2D, this.WicBitmap, this.RenderTargetProps); this.WicRenderTarget.BeginDraw(); this.WicRenderTarget.Clear(SDX.Color.White); this.WicRenderTarget.DrawBitmap(bitmap, new SDX.RectangleF(0f, 0f, width / 2, height / 2), 1.0f, SDX2D.BitmapInterpolationMode.NearestNeighbor); this.WicRenderTarget.EndDraw(); var pixelData = new byte[width * height * 4]; this.WicBitmap.CopyPixels(pixelData, width * 4); var bmp = new System.Drawing.Bitmap(width, height); var bd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); Marshal.Copy(pixelData, 0, bd.Scan0, pixelData.Length); bmp.UnlockBits(bd); bmp.Save(filename); } |
サンプルクラスの実装
上記のメソッドを順に呼びます。
1 2 3 4 |
var render = new RenderToBitmap(this); var btmap = render.LoadFromFile(@"C:\temp\SharpDxTest\image\whale.png"); var btmap2 = render.DrawBitmap(btmap); render.SaveFile(btmap2, @"C:\temp\SharpDxTest\image\whale2.png"); |