Why SharpDX render my bitmap in grey and corrupted?

1.4k views Asked by At

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.

Using DrawImage enter image description here

Using SharpDX enter image description here

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));
            }
        }
    }
}
2

There are 2 answers

1
xoofx On

The bmp_format B8G8R8A8_UNorm doesn't match the System.Drawing lock format Format24bppRgb... also use bmpdata1.Stride instead of calculating a potential invalid stride.

0
ErnieDingo On

Your stride is usually the width of the bitmap multipled by the byte depth.

so 512 * 4 would be a 512 wide bitmap with a 32 bit palette. Eg RGBA