Can I copy this array faster?

Is this the fastest I could copy Bitmap to Byte[] in C# ?

If there is a faster way, I am dying to know!

 const int WIDTH = /* width */; const int HEIGHT = /* height */; Bitmap bitmap = new Bitmap(WIDTH, HEIGHT, PixelFormat.Format32bppRgb); Byte[] bytes = new byte[WIDTH * HEIGHT * 4]; BitmapToByteArray(bitmap, bytes); private unsafe void BitmapToByteArray(Bitmap bitmap, Byte[] bytes) { BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, WIDTH, HEIGHT), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb); fixed(byte* pBytes = &bytes[0]) { MoveMemory(pBytes, bitmapData.Scan0.ToPointer(), WIDTH * HEIGHT * 4); } bitmap.UnlockBits(bitmapData); } [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)] private static unsafe extern void MoveMemory(void* dest, void* src, int size); 
+6
optimization c # copy bytearray bitmap
source share
4 answers

Well, using Marshal.Copy() , it would be wiser here, which at least reduces the (one-time) cost of finding a DLL export. But in this they both use the memcpy() runtime function. The speed is completely limited by the bandwidth of the RAM bus, only buying a more expensive machine can speed it up.

Beware that profiling is a complex process, and at the same time, accessing bitmap data causes page errors to receive data in pixels. How long it takes is critically dependent on what your hard drive is doing and the state of the file system cache.

+6
source share

I read in this that you want to do pixel manipulation with a bitmap. So, logically, you want to access the pixels as an array to do this.

The problem is that your appearance is fundamentally wrong, and the other guys didn't pick it up - and maybe this is what they can take away?

Basically, you still get to the pointers from the bitmap images, I'm going to give you one of my earned “secrets”.

YOU NEED TO COPY A BITMAP TO AN ARRAY. Just use it as is.

Unsafe pointers are your friend in this case. When you hit "bitmapData.Scan0.ToPointer ()", you missed the trick.

As long as you have a pointer to the first pixel and Stride, and you know the number of bytes per pixel, you get into the winner.

I specifically define a bitmap with 32 bits per pixel (memory is efficient for UInt32 access), and I get a pointer to the first pixel. Then I treat the pointer as an array and can both read and write pixel data as UInt32 values.

Code speaks louder than words. Take a look.

I salute you for making this so far!

This is unverified code, but a lot is copied from my source.

 public delegate void BitmapWork(UInt32* ptr, int stride); /// <summary> /// you don't want to forget to unlock a bitmap do you? I've made that mistake too many times... /// </summary> unsafe private void UnlockBitmapAndDoWork(Bitmap bmp, BitmapWork work) { var s = new Rectangle (0, 0, bmp.Width, bmp.Height); var locker = bmp.LockBits(new Rectangle(0, 0, 320, 200), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); var ptr = (UInt32*)locker.Scan0.ToPointer(); // so many times I've forgotten the stride is expressed in bytes, but I'm accessing with UInt32's. So, divide by 4. var stride = locker.Stride / 4; work(ptr, stride); bmp.UnlockBits(locker); } //using System.Drawing.Imaging; unsafe private void randomPixels() { Random r = new Random(DateTime.Now.Millisecond); // 32 bits per pixel. You might need to concern youself with the Alpha part depending on your use of the bitmap Bitmap bmp = new Bitmap(300, 200, System.Drawing.Imaging.PixelFormat.Format32bppArgb); UnlockBitmapAndDoWork(bmp, (ptr, stride) => { var calcLength = 300 * 200; // so we only have one loop, not two. It quicker! for (int i = 0; i < calcLength; i++) { // You can use the pointer like an array. But there no bounds checking. ptr[i] = (UInt32)r.Next(); } }); } 
+3
source share

I would also look at System.Buffer.BlockCopy .
This feature is also very fast, and it can be competitive in this setting when copying from managed to managed in your case. Unfortunately, I can not give some performance tests.

+1
source share

I think this is faster (I really used it):

 // Bitmap bytes have to be created via a direct memory copy of the bitmap private byte[] BmpToBytes_MemStream (Bitmap bmp) { MemoryStream ms = new MemoryStream(); // Save to memory using the Jpeg format bmp.Save(ms, ImageFormat.Jpeg); // read to end byte[] bmpBytes = ms.GetBuffer(); bmp.Dispose(); ms.Close(); return bmpBytes; } 

Source source

-2
source share

All Articles