7

ユーザーの画面の一部分のスクリーンショットを撮る C# のプログラムに取り組んでいます。ほとんどの場合、正常に動作しますが、最近 1 つの問題に遭遇しました。出力画像で常に透明として表示されるピクセルの色が (少なくとも) 1 つあるようです。色 #0D0B0C (RGB 13、11、12) のインスタンスは、保存された png で透明に表示されます。これは、PixelFormat を Format32bppArgb に設定したものです。Format32bppRgb または Format24bppRgb に設定すると、同じピクセルの色が保存された png で黒として表示されます。

何が原因なのかわかりませんが、「修正」するためにできる唯一のことは、CopyFromScreen() を実行する前にグラフィックス オブジェクトをその色にクリアすることです。いくつかの理由がありますが、私はそれをするのが嫌いです。まず、それが問題を抱えている唯一の色かどうかはわかりません (16,777,216 色の​​場合、かなりの数の可能性があります)。次に、ハック修正が嫌いです。これはハック修正のようです。

この問題の原因を特定できる人はいますか? ビットマップの作成時に PixelFormat をいじり、CopyFromScreen メソッドの CopyPixelOperation をいじりましたが、何も機能していないようです。グラフィックオブジェクトをその色にクリアすると「修正」されるという事実は、透明度が画面データ自体から来ていることを教えてくれるようですが、それは意味がありません。私はこれをあまりにも長い間見つめてきました。新しい視点が必要だと思います。なぜこれが起こっているのか、誰かが何か考えているなら、私はそれを聞いてみたい. ありがとうございました。

4

3 に答える 3

2

次のように、アルファ チャネルをまったく持たないビットマップに CopyFromScreen を要求するだけで済みました。

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 ではありません。

于 2016-05-11T17:39:43.293 に答える
0

アルファ値はおそらく0ですか?チェックしましたか?

Format32bppArgb と Format32bppRgb の大きな違いは、2 番目の形式がアルファ チャネルを認識しないことです。

于 2012-03-08T08:53:01.493 に答える
0

コントロールをビットマップにレンダリングするときに、まったく同じ問題が発生しました。PixelFormat.Format32bppRgb を使用して別のビットマップを作成し、それを BitBlt することで修正できました。お役に立てれば!

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;
    }
}
于 2012-04-18T22:12:07.967 に答える