I am new in SharpDX and I want to simulate code to render a 24-bit bitmap image straight from memory and display to PictureBox. *This code is to be use in later project to quickly render images from memory.
I have no issue render using standard DrawImage() method. I opt for SharpDX because DrawImage is too slow.
But when I try render using SharpDX, the image become grey in color and corrupted (see image below)
The image I want to render is in 24-bit RGB bitmap.
What is wrong with my code?
Below is my code:
using System;
using System.Windows.Forms;
using SharpDX;
using SharpDX.Direct2D1;
using System.Diagnostics;
namespace bitmap_test
{
public partial class Form1 : Form
{
private System.Drawing.Bitmap image1 = null;
private System.Drawing.Imaging.BitmapData bmpdata1 = null;
//target of rendering
WindowRenderTarget target;
//factory for creating 2D elements
SharpDX.Direct2D1.Factory factory = new SharpDX.Direct2D1.Factory();
//this one is for creating DirectWrite Elements
SharpDX.DirectWrite.Factory factoryWrite = new SharpDX.DirectWrite.Factory();
private SharpDX.DXGI.Format bmp_format = SharpDX.DXGI.Format.B8G8R8A8_UNorm;
private AlphaMode bmp_alphamode = AlphaMode.Ignore;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
InitSharpDX();
//load 24-bit depth bitmap
LoadBitmapFromFile(@"D:\lena.bmp"); //https://software.intel.com/sites/default/files/forum/351974/lena.bmp
}
private void InitSharpDX()
{
//Init Direct Draw
//Set Rendering properties
RenderTargetProperties renderProp = new RenderTargetProperties()
{
DpiX = 0,
DpiY = 0,
MinLevel = FeatureLevel.Level_10,
PixelFormat = new PixelFormat(bmp_format, bmp_alphamode),
Type = RenderTargetType.Hardware,
Usage = RenderTargetUsage.None
};
//set hwnd target properties (permit to attach Direct2D to window)
HwndRenderTargetProperties winProp = new HwndRenderTargetProperties()
{
Hwnd = this.pictureBox1.Handle,
PixelSize = new Size2(this.pictureBox1.ClientSize.Width, this.pictureBox1.ClientSize.Height),
PresentOptions = PresentOptions.Immediately
};
//target creation
target = new WindowRenderTarget(factory, renderProp, winProp);
}
//load bmp file into program memory
private void LoadBitmapFromFile(string file)
{
image1 = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(file, true);
var sourceArea = new System.Drawing.Rectangle(0, 0, image1.Width, image1.Height);
bmpdata1 = image1.LockBits(sourceArea, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
image1.UnlockBits(bmpdata1);
}
private void drawBitmap(IntPtr pBuffer, int len, int width, int height)
{
try
{
var bitmapProperties = new BitmapProperties(new PixelFormat(bmp_format, bmp_alphamode));
var size = new Size2(width, height);
int stride = width * 3; //only want RGB, ignore alpha
var bmp = new SharpDX.Direct2D1.Bitmap(target, size, new DataPointer(pBuffer, len), stride, bitmapProperties);
//draw elements
Draw(ref bmp);
bmp.Dispose();
}
finally
{
}
}
private void Draw(ref SharpDX.Direct2D1.Bitmap bmp)
{
//begin rendering
target.BeginDraw();
//clear target
target.Clear(null);
//draw bitmap
target.DrawBitmap(bmp, 1.0f, BitmapInterpolationMode.Linear);
//end drawing
target.EndDraw();
}
//draw image using SharpDX
private void cmdRender_Click(object sender, EventArgs e)
{
if (bmpdata1 != null)
{
int len = bmpdata1.Width * bmpdata1.Height * 3;
var sw = Stopwatch.StartNew();
drawBitmap(bmpdata1.Scan0, len, bmpdata1.Width, bmpdata1.Height);
sw.Stop();
Console.WriteLine("SharpDX: {0}us", sw.ElapsedTicks / (TimeSpan.TicksPerMillisecond / 1000));
}
}
//draw image using DrawImage()
private void cmdDrawImage_Click(object sender, EventArgs e)
{
if (image1 != null)
{
var g = pictureBox1.CreateGraphics();
var sourceArea = new System.Drawing.Rectangle(0, 0, image1.Width, image1.Height);
var sw = Stopwatch.StartNew();
g.DrawImage(image1, sourceArea); //DrawImage is slow
sw.Stop();
Console.WriteLine("DrawImage: {0}us", sw.ElapsedTicks/(TimeSpan.TicksPerMillisecond / 1000));
}
}
}
}
The
bmp_format
B8G8R8A8_UNorm
doesn't match the System.Drawing lock formatFormat24bppRgb
... also usebmpdata1.Stride
instead of calculating a potential invalid stride.