Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a small problem with converting a bitmap to a Texture2D. The resulted image of the conversion has the red channel switched with the blue channel :/ I don't know why, because the pixel formats are the same. If someone can help me I will be very happy :)

      System.Drawing.Image image = 
        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(image);
        Texture2D mapTexture = new Texture2D(Screen.Game.GraphicsDevice, bitmap.Width, bitmap.Height,false,SurfaceFormat.Color);

        System.Drawing.Imaging.BitmapData data = 
            bitmap.LockBits(new System.Drawing.Rectangle(
            0, 0, bitmap.Width, bitmap.Height), 

        byte[] bytes = new byte[data.Height * data.Width*4];

        System.Runtime.InteropServices.Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);

        mapTexture.SetData<byte>(bytes, 0, data.Height * data.Width * 4);

share|improve this question
up vote 6 down vote accepted

What you are seeing is not unusual. Image data is often stored as either BGR or RGB. (Plus there's ARGB vs RGBA and also premultiplication to take into consideration.)

XNA's SurfaceFormat.Color is ARGB.

For XNA 4 you generally want premultiplied alpha (this has more to do with what blend settings you use or need to use). If your image is entirely opaque it won't matter.

I'm pretty sure that the problem in your code arises from your use of LockBits. While LockBits gives you an opportunity to select a pixel format, it doesn't actually perform any conversion. So you've basically told it that a ABGR image is ARGB - you've lied to it! (I believe ABGR is a common format for Windows bitmaps.)

The solution is, of course, to swap the Red and Blue bytes in your temporary buffer before you set them on the XNA texture.

share|improve this answer

Here's a method i figured out, that is fast and swaps the red and blue fast also:

    private Texture2D GetTexture(GraphicsDevice dev, System.Drawing.Bitmap bmp)
        int[] imgData = new int[bmp.Width * bmp.Height];
        Texture2D texture = new Texture2D(dev, bmp.Width, bmp.Height);

            // lock bitmap
            System.Drawing.Imaging.BitmapData origdata = 
                bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

            uint* byteData = (uint*)origdata.Scan0;

            // Switch bgra -> rgba
            for (int i = 0; i < imgData.Length; i++)
                byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);                        

            // copy data
            System.Runtime.InteropServices.Marshal.Copy(origdata.Scan0, imgData, 0, bmp.Width * bmp.Height);

            byteData = null;

            // unlock bitmap


        return texture;
share|improve this answer
This code is wrong. First you are modifying the original bitmap itself, and copying with Marshal.Copy is useless since you are already going through all pixels manually. See my correction. – trethaller May 20 '12 at 21:27
    public static Texture2D ConvertToTexture(System.Drawing.Bitmap b, GraphicsDevice graphicsDevice)
        Texture2D tx = null;
        using (MemoryStream s = new MemoryStream())
            b.Save(s, System.Drawing.Imaging.ImageFormat.Png);
            s.Seek(0, SeekOrigin.Begin);
            tx = Texture2D.FromStream(graphicsDevice, s);
        return tx;
share|improve this answer

This works:

// Assuming:
uint[] m_PixelsBuffer;
System.Drawing.Bitmap m_Bitmap;

unsafe {
    System.Drawing.Imaging.BitmapData origdata =
        m_Bitmap.LockBits(new System.Drawing.Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, m_Bitmap.PixelFormat);
    uint* byteData = (uint*)origdata.Scan0;
    for (int i = 0; i < m_PixelsBuffer.Length; i++) {
        m_PixelsBuffer[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.