Jump to content
  • Advertisement
Sign in to follow this  
VanKurt

[.net] Fast Bitmap Access in C#

This topic is 3663 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there! I found several tutorials on the net showing how to get fast access to bitmap data in C# using the unsafe keyword (see code below). The strange thing is that it seems to work for everyone but me ;-) My problem is that the bitmap isn't changed when displayed, although I screwed all the pixels up. Take a look:
// Load bitmap
Bitmap bmp = new Bitmap("C:\\Users\\VanKurt\\Desktop\\test.png");

// Manipulate bitmap using tutorial code
UnsafeBitmap your_fast_bitmap = new UnsafeBitmap(bmp);
your_fast_bitmap.LockBitmap();
for (int y = 0; y < bmp.Height; y++)
            for (int x = 0; x < bmp.Width; x++)
            {
                    PixelData pixel = your_fast_bitmap.GetPixel(x, y);

                    pixel.red = 0;
                    pixel.blue /= 2;

                    your_fast_bitmap.SetPixel(x, y, pixel);
                }//end for
            your_fast_bitmap.UnlockBitmap();


// Show result in picture box
pictureBox2.Image = bmp;
pictureBox2.Size = bmp.Size;



So, where's the mistake? Why win't this code change anything? PS: Here's the (simple) UnsafeBitmap class:
namespace Gnarf
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing;
    using System.Drawing.Imaging;


    public unsafe class UnsafeBitmap
    {
        Bitmap bitmap;

        // three elements used for MakeGreyUnsafe
        int width;
        BitmapData bitmapData = null;
        Byte* pBase = null;

        public UnsafeBitmap(Bitmap bitmap)
        {
            this.bitmap = new Bitmap(bitmap);
        }

        public UnsafeBitmap(int width, int height)
        {
            this.bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        }

        public void Dispose()
        {
            bitmap.Dispose();
        }

        public Bitmap Bitmap
        {
            get
            {
                return (bitmap);
            }
        }

        private Point PixelSize
        {
            get
            {
                GraphicsUnit unit = GraphicsUnit.Pixel;
                RectangleF bounds = bitmap.GetBounds(ref unit);

                return new Point((int)bounds.Width, (int)bounds.Height);
            }
        }

        public void LockBitmap()
        {
            GraphicsUnit unit = GraphicsUnit.Pixel;
            RectangleF boundsF = bitmap.GetBounds(ref unit);
            Rectangle bounds = new Rectangle((int)boundsF.X,
          (int)boundsF.Y,
          (int)boundsF.Width,
          (int)boundsF.Height);

            // Figure out the number of bytes in a row
            // This is rounded up to be a multiple of 4
            // bytes, since a scan line in an image must always be a multiple of 4 bytes
            // in length.
            width = (int)boundsF.Width * sizeof(PixelData);
            if (width % 4 != 0)
            {
                width = 4 * (width / 4 + 1);
            }
            bitmapData =
          bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            pBase = (Byte*)bitmapData.Scan0.ToPointer();
        }

        public PixelData GetPixel(int x, int y)
        {
            PixelData returnValue = *PixelAt(x, y);
            return returnValue;
        }

        public void SetPixel(int x, int y, PixelData colour)
        {
            PixelData* pixel = PixelAt(x, y);
            *pixel = colour;
        }

        public void UnlockBitmap()
        {
            bitmap.UnlockBits(bitmapData);
            bitmapData = null;
            pBase = null;
        }
        public PixelData* PixelAt(int x, int y)
        {
            return (PixelData*)(pBase + y * width + x * sizeof(PixelData));
        }
    }
    public struct PixelData
    {
        public byte blue;
        public byte green;
        public byte red;
    }

}

Share this post


Link to post
Share on other sites
Advertisement
I'm not entirely sure, but something about your unsafe bitmap code makes me feel uneasy. I'm not sure how it would handle if you loaded a 32 bit ARGB image. I would imagine you could screw up all sorts of stuff.

I'm not sure if that's your problem. It may not be displaying for an entirely different reason; it's hard to tell from the code you've posted. If you'd like, check out my FastBitmap class, which is similar to your unsafe bitmap wrapper, with a lot more functionality thrown in. If, while using that, the image still doesn't show up, then you will know that your problem is somewhere else.

Share this post


Link to post
Share on other sites
After you assign the bitmap to the picturebox's Image property you need to refresh the picturebox. So try this:

pictureBox2.Image = bmp;
pictureBox2.Size = bmp.Size;
pictureBox2.Invalidate();

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!