2

私はこのコードを使用して画面をキャプチャしています:

public Bitmap CaptureWindow(IntPtr handle)
{
    // get te hDC of the target window
    IntPtr hdcSrc = User32.GetWindowDC(handle);
    // get the size
    User32.RECT windowRect = new User32.RECT();
    User32.GetWindowRect(handle, ref windowRect);
    int width = windowRect.right - windowRect.left;
    int height = windowRect.bottom - windowRect.top;
    // create a device context we can copy to
    IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
    // create a bitmap we can copy it to,
    // using GetDeviceCaps to get the width/height
    IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
    // select the bitmap object
    IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
    // bitblt over
    GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
    // restore selection
    GDI32.SelectObject(hdcDest, hOld);
    // clean up 
    GDI32.DeleteDC(hdcDest);
    User32.ReleaseDC(handle, hdcSrc);
    // get a .NET image object for it
    Bitmap img = Image.FromHbitmap(hBitmap);
    // free up the Bitmap object
    GDI32.DeleteObject(hBitmap);
    return img;
}

次に、ビットマップを256色(8ビット)に変換します。このコードを試しましたが、インデックス付きのビットマップ形式から画像を作成できないというエラーが発生しました。

Bitmap img8bit = new Bitmap(img.Width,img.Height,
                           System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
Graphics g = Graphics.FromImage(img8bit);
g.DrawImage(img,new Point(0,0));

異なるフォーマット間でビットマップを変換するいくつかの例を見ましたが、私の場合、画面からキャプチャしながらこれを行うための最良の方法を探しています。たとえば、最初に8ビットビットマップを作成してから画面をそれにブリットすることでうまく機能する方法がある場合は、最初に画面をキャプチャして互換性のあるビットマップに変換してから変換するよりも優先されます。キャプチャして変換する方が良い場合を除いて、とにかく変換​​します。

Borland Builder 6.0VCLを使用してC++で記述されたプログラムがあり、それを模倣しようとしています。その場合、VCLのTBitmapオブジェクトのピクセルフォーマットを設定するだけです。Bitmap.PixelFormatは.NETでは読み取り専用です。

更新:私の場合、元のビットマップは画面からのものであり、画面からのものではないため、画面DCを使用するGraphics.GetHalftonePaletteは問題ないはずなので、答えは、最適なパレットエントリを見つける必要がある他の使用法ほど複雑ではないと思います。 file / email / download/etcから来る可能性のあるランダムなビットマップ。DIBとGetHalftonePaletteを含む20行のコードで実行できることがあると思いますが、まだそれを見つけることができません。

4

2 に答える 2

7

フルカラービットマップを8bppに変換するのは難しい操作です。画像内のすべての色のヒストグラムを作成し、元の色に最適にマッピングされる最適化された色のセットを含むパレットを作成する必要があります。次に、ディザリングや誤差拡散などの手法を使用して、色がパレットと完全に一致しないピクセルを置き換えます。

これは、ImageToolsのようなプロのグラフィックライブラリに任せるのが最善です。.NETFrameworkでだまされる可能性のある安価な方法が1つあります。256色のファイル形式であるGIFエンコーダーを使用できます。結果は最高ではありません、それはディザリングを使用します、そしてそれは時々かなり目に見えることができます。繰り返しになりますが、本当に画質を気にするなら、とにかく8bppを使用しないでしょう。

    public static Bitmap ConvertTo8bpp(Image img) {
        var ms = new System.IO.MemoryStream();   // Don't use using!!!
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
        ms.Position = 0;
        return new Bitmap(ms);
    }
于 2012-04-17T05:07:57.330 に答える
1

通常のPixelFormatを使用して画面をキャプチャし、Bitmap.Clone()を使用して、次のように最適化された256インデックスカラーに変換します。

public static Bitmap CaptureScreen256()
{
    Rectangle bounds = SystemInformation.VirtualScreen;

    using (Bitmap Temp = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format24bppRgb))
    {
        using (Graphics g = Graphics.FromImage(Temp))
        {
            g.CopyFromScreen(0, 0, 0, 0, Temp.Size);
        }

        return Temp.Clone(new Rectangle(0, 0, bounds.Width, bounds.Height), PixelFormat.Format8bppIndexed);
    }
}
于 2016-01-09T20:26:54.630 に答える