A good way and with a good performance is to use LockBits function to access image data, using the LockBits you can create a Bitmap image using each byte of image, the lockBit lock the image data in memory to change each pixel data of the Bitmap Image. See this example:
Bitmap bm = new Bitmap(512, 512);
BitmapData bmd=bm.LockBits(new Rectangle(0, 0, 10, 10), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat);
int PixelSize=4;
for(int y=0; y<bmd.Height; y++)
{
byte* row=(byte *)bmd.Scan0+(y*bmd.Stride);
for(int x=0; x<bmd.Width; x++)
{
// Here you change your pixel data
row[x*PixelSize]=255;
}
}
bm.UnlockBits(bmd)
to draw in pictureBox you can just concatenate the member Image of pictureBox, or draw of a manually way. See these examples:
// concatenate
pict1.Image = bmp;
or
// Draw using CreateGraphics
Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
g.DrawImage(bmp, new Point(10, 10));
About the grayscale you can get a grayscale just using the value of one channel of image or getting an average value between RGB values and use the same value to these three channels, see this example:
// Average value between channels
Color oc = bmp.GetPixel(i, x);
int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
Color nc = Color.FromArgb(oc.A, grayScale, grayScale, grayScale);
d.SetPixel(x, y, nc); // if you are using bitmap
or
// value from one channel
Color pixelColor = c.GetPixel(x, y);
Color newColor = Color.FromArgb(pixelColor.R, pixelColor.R, pixelColor.R);
c.SetPixel(x, y, newColor); // Now greyscale
See more about the lockBits in this link: https://web.archive.org/web/20141229164101/http://bobpowell.net/lockingbits.aspx
and about grayscale: https://en.wikipedia.org/wiki/Grayscale