DD surface pixel manipulation

From: byter (myoung_at_navnam.com)
Date: 02/23/04

Date: Mon, 23 Feb 2004 15:41:28 -0800

I have a need to inspect and change individual pixels in a DirectDraw surface and i need to do it quickly. I use the Surface.Lock method to get a system array, then i pin the array, then use Marshal.UnsafeAddrOfPinnedArrayElement(arraySecondary,0) to get a pointer to the beginning of the array. Then i index into the array to manipulate an individual pixel. The visible surface is a panel control on a Winform. Everything works perfectly until i get about 25% thorugh the array when the pointer suddenly becomes "uninitialized". I've tried casting the pointer to a byte pointer and in integer pointer with the same result.

Here is the heart of the code using a int pointer. The byte pointer code is a bit more complex but the logic is the same and the result is the same: the pointer becomes "uninitialized" about 25% through the array. Any suggestions would be greatly appreciated.

byte[,] arraySecondary = surfaceSecondary.Lock(LockFlags.Wait | LockFlags.SurfaceMemoryPointer);
GCHandle gch = GCHandle.Alloc(arraySecondary,GCHandleType.Pinned);
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(arraySecondary,0);
int surfaceSecondaryStride = surfaceSecondary.SurfaceDescription.Pitch; //byte width of scan line
int surfaceSecondaryWidth = surfaceSecondary.SurfaceDescription.Width; //pixel width of scan line
int surfaceSecondaryHeight = surfaceSecondary.SurfaceDescription.Height;//pixel width of scan line
int nOffset = (surfaceSecondaryStride - (surfaceSecondaryWidth * 4)) / 4; //amount of padding at end of line for 32bbp
        int * p = (int *)(void *)ptr;
        int pInitial = (int)p;
        p += (((nOffset + (surfaceSecondaryWidth)) * yDrawing) + (xDrawing)) + ((nOffset + ((surfaceSecondaryWidth))) * 16);
        for(int y = 0 ; y < 222 ; y++) //for each line
                        for(int x = 0 ; x < pnlDrawing.Width ; x++ ) //for each pixel on the line
                        // if green then change to blue, otherwise make green
                        // .....code to read/write pixel value

                        p ++; //point to next pixel
                p += nOffset + ((surfaceSecondaryWidth - width)); //if secondary width = primary width
                int pLast = (int)p;