6

ビデオを作成するために、Windows アプリケーションの印刷画面を非常に高速に取得する必要があります... 私はずっと C# を使用してきましたが、このプロセスがより高速になる可能性のある言語であれば、どの言語でも使用できます。

私は多くのテクニックを使用しました:

  • .net 関数: Bitmap.CopyFromScreen()
  • GDI
  • Direct3d/DirectX

私が得た最速は GDI を使用することでしたが、それでも 1 秒あたり 10 個未満のフォトグラムしか取得できません。それよりも少し多く、少なくとも20または30が必要です...

このような単純な操作が非常に要求の厳しいものであることは、私には非常に奇妙に思えます。そして、より高速な CPU を使用しても状況は変わらないようです。

私に何ができる?gdi などを使用してアプリケーションの描画を直接キャプチャすることは可能ですか? それとも、グラフィックス カードにスローされる情報をキャッチするための低レベル関数でさえありますか?

この問題に関する任意の光は、非常に高く評価されます。どうもありがとう

4

2 に答える 2

1

多くのプログラムはドライバーを使用し、アプリケーションが下位レベルの表示ルーチンにフックできるようにします。これがどのように行われるかは正確にはわかりませんが、可能です。これは、Windows ドライバーを作成するための出発点です。http://msdn.microsoft.com/en-us/library/ms809956.aspx

Google経由で見つけたものは次のとおりです: http://www.hmelyoff.com/index.php?section=17

于 2009-04-13T15:20:42.750 に答える
1

おそらくCamtasiaのようなものを使いたいでしょう。動画を作る理由にもよります。

私は Jeff のUser-Friendly Exception Handlingの書き直したバージョンを使用し、彼は GDI の BitBlt を使用してスクリーンショットをキャプチャします。私には十分に高速に思えますが、ベンチマークは行っていません。未処理の例外がスローされたときに、一度に 1 回のショットに使用するだけです。

#region Win32 API screenshot calls

// Win32 API calls necessary to support screen capture
[DllImport("gdi32", EntryPoint = "BitBlt", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int BitBlt(int hDestDC, int x, int y, int nWidth, int nHeight, int hSrcDC, int xSrc,
                                 int ySrc, int dwRop);

[DllImport("user32", EntryPoint = "GetDC", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int GetDC(int hwnd);

[DllImport("user32", EntryPoint = "ReleaseDC", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int ReleaseDC(int hwnd, int hdc);

#endregion

private static ImageFormat screenshotImageFormat = ImageFormat.Png;

/// <summary>
/// Takes a screenshot of the desktop and saves to filename and format specified
/// </summary>
/// <param name="fileName"></param>
private static void TakeScreenshotPrivate(string fileName)
{
    Rectangle r = Screen.PrimaryScreen.Bounds;

    using (Bitmap bitmap = new Bitmap(r.Right, r.Bottom))
    {
        const int SRCCOPY = 13369376;

        using (Graphics g = Graphics.FromImage(bitmap))
        {
            // Get a device context to the windows desktop and our destination  bitmaps
            int hdcSrc = GetDC(0);
            IntPtr hdcDest = g.GetHdc();

            // Copy what is on the desktop to the bitmap
            BitBlt(hdcDest.ToInt32(), 0, 0, r.Right, r.Bottom, hdcSrc, 0, 0, SRCCOPY);

            // Release device contexts
            g.ReleaseHdc(hdcDest);
            ReleaseDC(0, hdcSrc);

            string formatExtension = screenshotImageFormat.ToString().ToLower();
            string expectedExtension = string.Format(".{0}", formatExtension);

            if (Path.GetExtension(fileName) != expectedExtension)
            {
                fileName += expectedExtension;
            }

            switch (formatExtension)
            {
                case "jpeg":
                    BitmapToJPEG(bitmap, fileName, 80);
                    break;
                default:
                    bitmap.Save(fileName, screenshotImageFormat);
                    break;
            }

            // Save the complete path/filename of the screenshot for possible later use
            ScreenshotFullPath = fileName;
        }
    }
}

/// <summary>
/// Save bitmap object to JPEG of specified quality level
/// </summary>
/// <param name="bitmap"></param>
/// <param name="fileName"></param>
/// <param name="compression"></param>
private static void BitmapToJPEG(Image bitmap, string fileName, long compression)
{
    EncoderParameters encoderParameters = new EncoderParameters(1);
    ImageCodecInfo codecInfo = GetEncoderInfo("image/jpeg");

    encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, compression);
    bitmap.Save(fileName, codecInfo, encoderParameters);
}
于 2009-04-13T15:30:49.137 に答える