C# Bitmap object, color appearing as transparent
Asked Answered
J

3

7

I'm working on a program in C# that takes screenshots of a potion of the user's screen. For the most pert it works as it should, but I've recently run into one issue. There seems to be (at least) one pixel color that always appears as transparent in the output image. Any instance of the color #0D0B0C (RGB 13, 11, 12) appears transparent in the saved png. This is with the PixelFormat set to Format32bppArgb. If I set it to Format32bppRgb or Format24bppRgb, that same pixel color appears as black in the saved png.

I have no idea what could be causing this, but the only thing I've been able to do to "fix" it is to clear the graphics object to that color before doing CopyFromScreen(). I'm loathe to do that though for a few reasons. First, I don't know if that's the only color that has the issue (what with 16,777,216 colors there's quite a few possibilities), and second, I hate hack fixes, this seems like a hack fix.

Can anyone shed any light on what might be causing this issue? I've messed with the PixelFormat on the bitmap creation and with the CopyPixelOperation in the CopyFromScreen method, nothing seems to work. The fact that clearing the graphics object to that color "fixes" it seems to tell me that the transparency is coming from the screen data itself, but that doesn't make sense. I've been staring at this for too long, I think I need a fresh perspective on it. If anyone has any idea why this might be happening I'd love to hear it. Thank you.

Jackie answered 8/3, 2012 at 7:14 Comment(0)
L
3

I simply had to request the CopyFromScreen into a bitmap that does NOT have an Alpha channel at all, such as:

Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height,     System.Drawing.Imaging.PixelFormat.Format32bppRgb);
Graphics graphics = Graphics.FromImage(bitmap as Image);
graphics.CopyFromScreen(bounds.Location, new Point(0, 0), bitmap.Size);

I confirmed that this has transparent pixel holes with Format32bppArgb but not with Format32bppRgb

Latrena answered 11/5, 2016 at 17:39 Comment(0)
B
0

Is the alpha value maybe 0? Have you checked it?

Because the big different between Format32bppArgb and Format32bppRgb is that the second format does not know the alpha channel.

Bacterium answered 8/3, 2012 at 8:53 Comment(4)
A print screen results in an image that's correct, and like I said in the OP, when I set it to Format32bppRgb, the same pixels appear black (when they should be #0D0B0C). None of the other pixels appear transparent, and this sounds like something that would be present in a print screen as well.Jackie
how do you capture your screenshots?Bacterium
Like I said in the OP, I use a graphics object and CopyFromScreen().Jackie
Changing new Bitmap(width, height, PixelFormat.Format32bppArgb) to new Bitmap(width, height, PixelFormat.Format32bppRgb) fixed this issue for me.Aleen
R
0

Had the exact same issue when rendering a control to a bitmap. Managed to fix it by creating another bitmap with PixelFormat.Format32bppRgb and BitBlt'ing it to it. Hope this helps!

public class ScreenCapture
{
    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    private static extern bool BitBlt(
        IntPtr hdcDest, // handle to destination DC
        int nXDest, // x-coord of destination upper-left corner
        int nYDest, // y-coord of destination upper-left corner
        int nWidth, // width of destination rectangle
        int nHeight, // height of destination rectangle
        IntPtr hdcSrc, // handle to source DC
        int nXSrc, // x-coordinate of source upper-left corner
        int nYSrc, // y-coordinate of source upper-left corner
        System.Int32 dwRop // raster operation code
        );


    /// <summary>
    /// Returns an image of the control
    /// </summary>
    /// <param name="control">The control object whose image is wanted</param>
    /// <returns>Image of the control</returns>
    /// <remarks>This is based on code from 
    /// http://www.dotnet247.com/247reference/a.aspx?u=http://www.c-sharpcorner.com/Code/2002/April/ScreenCaptureUtility.asp 
    /// with changes made to prevent 0D0B0C transparency issues</remarks>
    public static Image GetControlImage(Control control)
    {
        Graphics g1 = control.CreateGraphics();

        // Create a bitmap the same size as the control
        Image MyImage = new Bitmap(control.ClientRectangle.Width, control.ClientRectangle.Height, PixelFormat.Format32bppRgb);
        (MyImage as Bitmap).SetResolution(g1.DpiX, g1.DpiY);

        Graphics g2 = Graphics.FromImage(MyImage);

        IntPtr dc1 = g1.GetHdc();
        IntPtr dc2 = g2.GetHdc();

        // BitBlt from one DC to the other
        BitBlt(dc2, 0, 0, control.ClientRectangle.Width, control.ClientRectangle.Height, dc1, 0, 0, 13369376);

        // Release Device Contexts
        g1.ReleaseHdc(dc1);
        g2.ReleaseHdc(dc2);

        // This statement runs the garbage collector manually
        // (If not present, uses up large amounts of memory...)
        GC.Collect();

        return MyImage;
    }
}
Reconstruct answered 18/4, 2012 at 22:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.