<p>I have a memory buffer corresponding to my screen resolution (1280x800 at 24-bits-per-pixel) that contains my screen contents at 24bpp. I want to convert this to 8-bpp (ie. Halftone color palette in Windows).
I currently do this:
1. Use CreateDIBSection to allocate a new 1280x800 24-bpp buffer and access it as a DC, as well as a plain memory buffer
2. Use memcpy to copy from my original buffer to this new buffer from step 1
3. Use BitBlt to let GDI perform the color conversion</p>

<p>I want to avoid the extra memcpy of step 2. To do this, I can think of two approaches:</p>

<p>a. Wrap my original mem buf in a DC to perform BitBlt directly from it</p>

<p>b. Write my own 24-bpp to 8-bpp color conversion. I can't find any info on how Windows implements this halftone color conversion. Besides even if I find out, I won't be using the accelerated features of GDI that BitBlt has access to.</p>

<p>So how do I do either (a) or (b)?</p>

<p>thanks!</p>

OK, to address the two parts of the problem.
the following code shows how to get at the pixels inside of a bitmap, change them and put them back into the bitmap.  You could always generate a dummy bitmap of the correct size and format, open it up, copy over your data and you then have a bitmap object with your data:
```
```
private void LockUnlockBitsExample(PaintEventArgs e)
{

   // Create a new bitmap.
   Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");

   // Lock the bitmap's bits.  
   Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
   System.Drawing.Imaging.BitmapData bmpData =
         bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
         bmp.PixelFormat);

   // Get the address of the first line.
   IntPtr ptr = bmpData.Scan0;

   // Declare an array to hold the bytes of the bitmap.
   int bytes  = bmpData.Stride * bmp.Height;
   byte[] rgbValues = new byte[bytes];

   // Copy the RGB values into the array.
   System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

   // Set every third value to 255. A 24bpp bitmap will look red.  
   for (int counter = 2; counter < rgbValues.Length; counter += 3)
       rgbValues[counter] = 255;

   // Copy the RGB values back to the bitmap
   System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

   // Unlock the bits.
   bmp.UnlockBits(bmpData);

   // Draw the modified image.
   e.Graphics.DrawImage(bmp, 0, 150);
}
```
```
To convert the contents to 8bpp you'll want to use the System.Drawing.Imaging.ColorMatrix class.  I don't have at hand the correct matrix values for half-tone, but this example grayscales and adjustment of the values should give you an idea of the effect:
```
```
Graphics g = e.Graphics;
Bitmap bmp = new Bitmap("sample.jpg");
g.FillRectangle(Brushes.White, this.ClientRectangle);

// Create a color matrix
// The value 0.6 in row 4, column 4 specifies the alpha value
float[][] matrixItems = {
                            new float[] {1, 0, 0, 0, 0},
                            new float[] {0, 1, 0, 0, 0},
                            new float[] {0, 0, 1, 0, 0},
                            new float[] {0, 0, 0, 0.6f, 0}, 
                            new float[] {0, 0, 0, 0, 1}};
ColorMatrix colorMatrix = new ColorMatrix(matrixItems);

// Create an ImageAttributes object and set its color matrix
ImageAttributes imageAtt = new ImageAttributes();
imageAtt.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

// Now draw the semitransparent bitmap image.
g.DrawImage(bmp, this.ClientRectangle, 0.0f, 0.0f, bmp.Width, bmp.Height, 
            GraphicsUnit.Pixel, imageAtt);

imageAtt.Dispose();
```
```
I shall try and update later with the matrix values for half-tone, it's likely to be lots 0.5 or 0.333 values in there!