1

私は現在これを持っています。

    private const int PixelSizeBGR = 3;

    [StructLayout(LayoutKind.Explicit)]
    private unsafe struct BGR5
    {
        [FieldOffset(0)]
        private fixed byte bgr[PixelSizeBGR * 5];

        public BGR5(byte b, byte g, byte r)
        {
            fixed (byte* v = bgr) 
            {
                int num = 0;
                do
                {
                    v[num++] = b; v[num++] = g; v[num++] = r;
                } while (num < (PixelSizeBGR * 5));
            }
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    private unsafe struct BGR3
    {
        [FieldOffset(0)]
        private fixed byte bgr[PixelSizeBGR * 3];

        public BGR3(byte b, byte g, byte r)
        {
            fixed (byte* v = bgr)
            {
                int num = 0;
                do
                {
                    v[num++] = b; v[num++] = g; v[num++] = r;
                } while (num < (PixelSizeBGR * 3));
            }
        }
    }

私が考えるパターンを見ることができます。

これらがもっと必要であることがわかるかもしれないので、動的にする方法はありますか?

または代替手段はありますか?

実際の例;

BEFORE、24000 ピクセル x 24000 ピクセルのビットマップ、2151 ミリ秒

            byte* row = (byte*)bmd.Scan0;

            /*** stuff ***/

            Offset1 = ((CurrentPos / GridX) * FullRow) + ((CurrentPos % GridX) * FullSquare);
            for (k = PixelSize; k <= w; k += PixelSize)
            {
                Offset1 += PixelSize;
                for (l = Stride; l <= h; l += Stride)
                {
                    row[l + Offset1] = 0; //b
                    row[l + Offset1 + 1] = 255; //g
                    row[l + Offset1 + 2] = 255; //r
                }
            }
            /*** more stuff ***/

AFTER、24000 ピクセル x 24000 ピクセルのビットマップ、944 ミリ秒

            byte* row = (byte*)bmd.Scan0;

            /*** stuff ***/

            np5.Set(0, 255, 255);
            Offset1 = ((CurrentPos / GridX) * FullRow) + ((CurrentPos % GridX) * FullSquare) + PixelSizeBGR;
            h = Stride;
            do
            {
                *((BGR5*)(row + h + Offset1)) = np5;
                h += Stride;
            } while (h < FullRow);

            /*** more stuff ***/

AFTER は 50% 以上高速です

4

2 に答える 2

1

これを行うべきかどうか、またはこれを行うためのより良い方法があるかどうかという問題には立ち入らずに、可変長メモリブロックのコピーに使用できるランタイムサイズの構造を作成したいという OP の要望に答えようとします。つまり、高性能なバイトレベルのデータ操作を実行することは、C# よりも C++ に適していますが、技術的にはまだ可能であるようです。

これを実現するには、マーシャリングを使用して可変サイズのアンマネージ メモリを動的に作成し、一時BGRnデータを保持してから、P/Invoke を使用してブロック メモリのコピーを実行します。

public unsafe class BGRn
{
    IntPtr bgrPtr;
    int totalSize;
    const int pixelSizeBGR = 3;

    public BGRn(byte b, byte g, byte r, int size)
    {
        totalSize = pixelSizeBGR * size;
        bgrPtr = Marshal.AllocHGlobal(totalSize);

        byte* v = (byte*)bgrPtr;

        int num = 0;

        do
        {
            v[num++] = b;
            v[num++] = g;
            v[num++] = r;
        } while (num < (totalSize));
    } 

    public void CopyTo(IntPtr buffer)
    {
        CopyMemory(buffer, bgrPtr, (uint) totalSize);
    }

    [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
    private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

}

その後、置換を除いて他のコードをそのままにしておくことができます。

BGR5 np5 = new BGR5(0, 255, 255);
// ...
*((BGR5*)(row + h + Offset1)) = np5;

と:

BGRn np5 = new BGRn(0, 255, 255, 5);
// ...
np5.CopyTo((IntPtr)(row + h + Offset1));

もちろん、Marshal.FreeHGlobalこのクラスに付随する を省略しましたが、いつ、どのようにメモリを解放するかを決定するのはユーザー次第です (おそらくIDisposableusingステートメントを実装することによって)。

このコードがどのように機能するか、または機能するかどうかは実際にはテストしていませんが、コンパイルはできます。

于 2013-08-16T04:24:37.423 に答える
0

抽象基本クラスを使用すると、ビットマップ幅ごとに個別のクラスを記述する必要がありますが、任意の幅のビットマップでの作業が容易になります。構造体は必要ありません。ビットマップのメモリに直接書き込むことができます。

using System.Drawing.Imaging;

namespace TestProject2
{
public abstract class BGRBase
{
    //init to your bitmap's BitmapData, obtained by calling Bitmap.LockBits
    protected readonly BitmapData data;

    public abstract void SetRow(int rowIndex, byte b, byte g, byte r);
}

public class BGR3 : BGRBase
{
    //use constructor to ensure that the bitmap's width is compatible

    public unsafe override void SetRow(int rowIndex, byte b, byte g, byte r)
    {
        byte* row = (byte*)data.Scan0 + rowIndex * data.Stride;
        row[0] = row[3] = row[6] = b;
        //etc
    }
}

public class BGR5 : BGRBase
{
    public override unsafe void SetRow(int rowIndex, byte b, byte g, byte r)
    {
        //code as adove
    }
}
}

または、デリゲートを使用して適切なメソッドをカプセル化し、ループで呼び出します

public static void Set5(byte* p, byte b, byte g, byte r)

public static void Set3(byte* p, byte b, byte g, byte r)

//usage
public void Draw(Rectangle rect, byte b, byte g, byte r)
{
    Action<byte*, byte, byte, byte> setRow = null;
    switch(rect.Width)
    {
        case 3: setRow = Set3; break;
        case 5: setRow = Set5; break;
        //etc
    }
    byte* p=(byte*)bmd.Scan0 + bmd.Stride * rect.Y + 3 * rect.X;
    while(p < endAddress)
    {
        setRow(p, b, g, r);
        p+=bmd.Stride;  
    }
}
于 2013-08-14T14:53:15.367 に答える