C#位图对象,颜色显示为透明

7
我正在使用C#编写一个程序,它可以截取用户屏幕的一部分。大多数情况下它能够正常工作,但是我最近遇到了一个问题。在输出图像中,#0D0B0C(RGB 13,11,12)颜色中至少有一个像素总是出现为透明。如果将PixelFormat设置为Format32bppArgb,则该颜色的任何实例都会在保存的png文件中显示为透明。如果我将其设置为Format32bppRgb或Format24bppRgb,则同一像素颜色显示为黑色。
我不知道可能导致这种情况,但我唯一能够做的“修复”它的方法就是在执行CopyFromScreen()之前将graphics对象清除为该颜色。然而,由于几个原因,我不愿意这样做。首先,我不知道是否只有这种颜色存在问题(有着16,777,216种颜色,可能有很多可能性),其次,我讨厌一些拼凑出来的解决办法,这似乎就是一个拼凑出来的解决办法。
有人能否阐明可能导致这个问题的原因?我已经尝试过在位图创建时和在CopyFromScreen方法中调用CopyPixelOperation函数时改变PixelFormat,但没有效果。将graphics对象清除为该颜色“修复”这个问题,似乎表明透明性来自屏幕数据本身,但这不合理。我已经盯着这个问题很长时间了,我认为我需要一个全新的视角。如果有人知道发生这种情况的原因,请告诉我。谢谢。
3个回答

2

我只需将CopyFromScreen请求到一个完全没有Alpha通道的位图中,例如:

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

我确认这个图像在使用Format32bppArgb格式时有透明的像素孔,但在使用Format32bppRgb格式时没有。


0

alpha值可能是0吗?你有检查过吗?

因为Format32bppArgb和Format32bppRgb之间的主要区别在于第二种格式不知道alpha通道。


打印屏幕会生成一个正确的图像,就像我在帖子中提到的那样,当我将其设置为Format32bppRgb时,相同的像素会出现黑色(而不是#0D0B0C)。没有其他像素呈透明状态,这听起来在打印屏幕中也应该存在。 - HaLo2FrEeEk
你是如何捕捉屏幕截图的? - cansik
就像我在原帖中所说的那样,我使用一个图形对象和CopyFromScreen()函数。 - HaLo2FrEeEk
new Bitmap(width, height, PixelFormat.Format32bppArgb) 改为 new Bitmap(width, height, PixelFormat.Format32bppRgb) 解决了我的问题。 - ghord

0

当将控件渲染到位图时,我遇到了完全相同的问题。通过创建另一个像素格式为PixelFormat.Format32bppRgb的位图并将其复制到该位图中来解决了该问题。希望这能有所帮助!

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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接