How to wrap an existing memory buffer as DC for GDI

I have a memory buffer corresponding to my screen resolution (1280x800 with 24 bits per pixel), which contains my 24bpp screen content. I want to convert this to 8-bpp (i.e. a Halftone color palette on Windows). I am doing this now: 1. Use CreateDIBSection to allocate a new 2480pb 2480pp buffer and access it as a DC, as well as a simple memory buffer 2. Use memcpy to copy from my source buffer to this new buffer from step 1 3. Use BitBlt to allow GDI to perform color conversion

I want to avoid the extra memcpy step 2. To do this, I can introduce two approaches:

and. Wrap my original mem buf in DC to execute BitBlt directly from it

b. Write my own color conversion with 24-bit resolution up to 8 bits. I cannot find information on how Windows implements this halftone color conversion. Also, even if I find out, I won’t use the accelerated GDI features that BitBlt has access to.

So how do I do (a) or (b)?

thank!

+3
source share
4 answers

OK to solve two parts of the problem.

  • the following code shows how to get pixels inside a bitmap, change them, and put them back into the bitmap. You can always create a fictitious bitmap of the correct size and format, open it, copy it according to your data, and then you 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 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);
    }
    

8bpp, System.Drawing.Imaging.ColorMatrix. , :

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();

, , , 0,5 0,333!

+2

CreateDIBitmap, CreateDIBSection.

+1

( 2), CreateDIBSection . DC BitBlt.

.. CreateDIBSection blitting, CreateDIBSection .

, , CreateDIBSection, " ", CreateCompatibleDC, , .

0

24bpp ?

memcpy - screengrab, DIBSection 24bpp screengrab .

, GDI , BITMAPINFOHEADER, , StretchDIBits, 8bpp DIBSection.

0

Source: https://habr.com/ru/post/1697115/


All Articles