如何在SharpDX上获取Direct2D位图的像素颜色

本文关键字:位图 像素 颜色 Direct2D 获取 SharpDX | 更新日期: 2024-09-22 11:48:30

我使用SharpDX,不知道如何在位图中获得像素颜色。我找到了CopySubresourceRegion方法,但它在Direct3D上工作。我有一个奇怪的想法:

我可以创建RenderForm并在表单上绘制位图。然后获取表单的图形。然后通过"新位图(宽度、高度、图形)"创建位图。然后从新位图中获取像素颜色;

如何在SharpDX上获取Direct2D位图的像素颜色

我编写了获取像素颜色的特殊函数。这解决了我的问题;)C#-SharpDX

Color4 GetPixel(Bitmap image, int x, int y, RenderTarget renderTarget) {
        var deviceContext2d = renderTarget.QueryInterface<DeviceContext>();
        var bitmapProperties = new BitmapProperties1();
        bitmapProperties.BitmapOptions = BitmapOptions.CannotDraw | BitmapOptions.CpuRead;
        bitmapProperties.PixelFormat = image.PixelFormat;
        var bitmap1 = new Bitmap1(deviceContext2d, new Size2((int)image.Size.Width, (int)image.Size.Height), bitmapProperties);
        bitmap1.CopyFromBitmap(image);
        var map = bitmap1.Map(MapOptions.Read);
        var size = (int)image.Size.Width * (int)image.Size.Height * 4;
        byte[] bytes = new byte[size];
        Marshal.Copy(map.DataPointer, bytes, 0, size);
        bitmap1.Unmap();
        bitmap1.Dispose();
        deviceContext2d.Dispose();
        var position = (y * (int)image.Size.Width + x) * 4;
        return new Color4(bytes[position], bytes[position + 1], bytes[position + 2], bytes[position + 3]);
    }

如果您的目标是Direct2D 1.1(或更高版本),则可以使用ID2D1Bitmap1::Map方法。这将要求您在创建位图时在位图上设置D2D1_BITMAP_OPTIONS_CPU_READD2D1_BITMAP_OPTONS_CANNOT_DRAW标志。

对于仍在寻找从位图中获取像素的有效方法的人,我已经编写了一个类,它克隆和映射位图,提供对生成的DataRectangle(也称为像素数据)的直接访问,并最终自动取消映射位图。

using SharpDX;
using SharpDX.Direct2D1;
public unsafe class ReadableBitmap
{
    private readonly Bitmap1 origin;
    private readonly Color32* pixels;
    private readonly int pitch;
    public Size2 Size { get; private set; }
    public Color32 this[int x, int y]
    {
        get
        {
            if (x < 0 || y < 0 || x >= Size.Width || y >= Size.Height)
                throw new IndexOutOfRangeException("Cannot get a pixel outside of the bitmap.");
            var rowPtr = (Color32*)((byte*)pixels + y * pitch);
            return rowPtr[x];
        }
    }
    public ReadableBitmap(RenderTarget target, Bitmap bitmap)
    {
        var deviceContext2d = target.QueryInterface<DeviceContext>();
        var bitmapProperties = new BitmapProperties1
        {
            BitmapOptions = BitmapOptions.CannotDraw | BitmapOptions.CpuRead,
            PixelFormat = bitmap.PixelFormat
        };
        Size = bitmap.PixelSize;
        origin = new Bitmap1(deviceContext2d, Size, bitmapProperties);
        deviceContext2d.Dispose();
        origin.CopyFromBitmap(bitmap);
        var map = origin.Map(MapOptions.Read);
        pitch = map.Pitch;
        pixels = (Color32*)map.DataPointer;
        origin.Disposing += OnBitmapDisposing;
    }
    private static void OnBitmapDisposing(object? sender, EventArgs e)
    {
        if (sender is not Bitmap1 bmp)
            return;
        bmp.Unmap();
    }
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct Color32
    {
        public byte R;
        public byte G;
        public byte B;
        public byte A;
    }
}

示例用法:

var read = new ReadableBitmap(renderTarget, bitmap);
Console.WriteLine($"The top left pixel has an alpha of {read[0, 0].A}.");