質問

私のアプリには、保存しています Bitmap 2次元整数アレイのデータ(int[,])。 R、G、Bの値にアクセスするには、次のようなものを使用します。

// read:
int i = _data[x, y];
byte B = (byte)(i >> 0);
byte G = (byte)(i >> 8);
byte R = (byte)(i >> 16);
// write:
_data[x, y] = BitConverter.ToInt32(new byte[] { B, G, R, 0 }, 0);

実際の代わりに整数アレイを使用しています System.Drawing.Bitmap 私のアプリは、ビットマップの作成に使用できるメモリが非常に制限されているWindowsモバイルデバイスで実行されているためです。

しかし、このような構造を宣言する方が理にかなっているのではないかと思います。

public struct RGB
{
    public byte R;
    public byte G;
    public byte B;
}

...そして、の配列を使用します RGB の配列の代わりに int. 。このようにして、ビットシフトやビットコンバーターングを実行することなく、個別のR、G、およびBの値を簡単に書き込み、書き込むことができました。私は昔の時代から何かを漠然と覚えています byte 変数は32ビットシステムでブロックされているため、 byte 実際には、たった1つではなく4バイトのメモリを占有します(ただし、これは単なる視覚的な基本的なものでした)。

構造体の配列を使用します( RGB 例 `上記)intsの配列を使用するよりも速く、3/4メモリまたは3倍のメモリを使用しますか?

役に立ちましたか?

解決

あなたが取り組んでいるなら 速度, 、 それから 技術的に 私は期待します int[] より速くなるバージョン、 int アレイから(参照してください OpCodes.Ldelem_I4)。カスタム構造体を実行するには、アドレスを取得する必要があります(OpCodes.Ldelema)そして、構造体をコピーします(OpCodes.Ldobj) - これらの両方のステップのタイプメタデータを処理します。

要するに - int アプローチには、より良い最適化が必要です。しかし、これはです 微小最適化 - の 全般的 コードをより読みやすくするバージョンをお勧めします。あなたは何 そうかもしれない 検討することは、カスタム静的暗黙の変換演算子で構造体を書くことです int あなたの構造体に - あなたは持っていることができます int[] それでもそうします:

MyColor col = intArr[12];

(もちろん、中央で静的コールを行います)

また、aの使用を検討する場合があります 連合 だから、あなたはたくさんのシフトをする必要はありません:

重要 私はこれについて正気をチェックしていません。 r/g/bのオフセットを変更して変更してください。

class Program
{
    static void Main()
    {
        int[] i = { -1 };
        RGB rgb = i[0];
    }
}
[StructLayout( LayoutKind.Explicit)]
public struct RGB
{
    public RGB(int value) {
        this.R = this.G = this.B = 0; this.Value = value;
    }
    [FieldOffset(0)]
    public int Value;
    [FieldOffset(2)]
    public byte R;
    [FieldOffset(1)]
    public byte G;
    [FieldOffset(0)]
    public byte B;

    public static implicit operator RGB(int value) {
        return new RGB(value);
    }
    public static implicit operator int(RGB value) {
        return value.Value;
    }
}

他のヒント

ただ使用しないのはなぜですか Color 構造 System.Drawing?処理して参照する方が簡単です。確かに、4バイト(別の値はアルファを表します)がありますが、最初の実装もそうです。正しく思い出せば、3バイトはとにかく4バイトブロックに整列します。サンプルを見てください ここ.

単独で唯一のバイトはブロックアライメントされますが、構造体の複数のバイトを梱包できます。 Marshal.sizeofによると、RGB構造体は実際に3バイトのメモリしか占めていません。 (技術的には、これは管理されていないメモリにマーシャルするときのサイズであり、CLRはそれを別の方法でレイアウトすることを選択できます。しかし、実際にはこれは正しいと思います。)

ただし、CLRはまだRGBと他の構造体の間にパディングを挿入することができ、この動作はプロセッサ、CLRバージョンなどに依存する可能性があります。X86システムでは、3億RGBの配列を割り当てると、約900 MBがコミットされていると報告するタスクマネージャーになりました。 3億個のINTの配列を割り当てると、1200 MBがコミットされました。したがって、X86の2.0 CLRは25%の節約を提供しているようです。 (私はこれが私を驚かせたことを認めなければなりません。テクノロジーの男のように、私は3バイトの構造体が4バイトの境界に整合することを期待していました。だから私は何かが欠けているかもしれません。)ターゲットプラットフォームでテストすることによってのみ知っています。

IDは、何を達成したいかに依存していると思います。確かに構造化するために使用する方が読みやすく、そしてあなたはそれを安全に使用することができます

unsafe { }

ビットマップアクセスを本当にスピードアップします。 (何をすべきかを知っている場合 - 境界条件やそのようなものをチェックしないでください)、そして間違いなく、ビットマップの乗算、マスキング、グレイスケーリング、通常のグラフィックスのフィルタリングのためにオペレーターを作りたい場合は、intは速度の点であなたの友人です。しかし、残念ながら読みやすさの場合はそうではありません。 Matrix Filterは、RGB値を個別にではなく、とにかく問題ではないマーク構造を使用して、INTS(そのように書くことができる)のみのマルチアップのみです。それが役に立てば幸い

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top