7

rgba バッファを argb に変換しようとしていますが、次のアルゴリズムを改善する方法、またはそのような操作を実行するための他の高速な方法はありますか? alpha 値は argb バッファでは重要ではなく、常に 0xFF になる必要があることを考慮してください。

int y, x, pixel;

for (y = 0; y < height; y++)
{
    for (x = 0; x < width; x++)
    {
     pixel = rgbaBuffer[y * width + x];
     argbBuffer[(height - y - 1) * width + x] = (pixel & 0xff00ff00) | ((pixel << 16) & 0x00ff0000) | ((pixel >> 16) & 0xff);
    }
}
4

6 に答える 6

1

コードにバグがなく (非効率的)、毎秒 (偶数) バイトを交換する (そしてもちろんバッファを反転する) だけでよいと推測できますね。

したがって、次の方法でいくつかの最適化を実現できます。

  • シフトおよびマスキング操作の回避
  • ループの最適化 (インデックス計算での節約など)

次のようにコードを書き直します。

int y, x;

for (y = 0; y < height; y++)
{
    unsigned char *pRGBA= (unsigned char *)(rgbaBuffer+y*width);
    unsigned char *pARGB= (unsigned char *)(argbBuffer+(height-y-1)*width);
    for (x = 4*(width-1); x>=0; x-=4)
    {
        pARGB[x  ]   = pRGBA[x+2];
        pARGB[x+1]   = pRGBA[x+1];
        pARGB[x+2]   = pRGBA[x  ];
        pARGB[x+3]   = 0xFF;
    }
}

より複雑なインデックスの計算は、外側のループでのみ実行されることに注意してください。ピクセルごとに rgbaBuffer と argbBuffer の両方に 4 つのアクセスがありますが、これはビット単位の操作とインデックスの計算を回避することでオフセット以上のものになると思います。別の方法は(コードのように)一度に1ピクセル(int)をフェッチ/ストアし、ローカルで処理を行います(これによりメモリアクセスが節約されます)が、2バイトを交換して設定する効率的な方法がない限りアルファをローカルに (たとえば、すべてがレジスタ レベルで実行されるようにするためのインライン アセンブリなど)、実際には役に立ちません。

于 2012-06-29T13:25:37.250 に答える
1

あなたが提供したコードは、rgba->argb ではなく rgba->rabg ではなく色成分をシャッフルするため、非常に奇妙です。

このルーチンの正確で最適化されたバージョンを作成しました。

int pixel;
int size = width * height;

for (unsigned int * rgba_ptr = rgbaBuffer, * argb_ptr = argbBuffer + size - 1; argb_ptr >= argbBuffer; rgba_ptr++, argb_ptr--)
{
    // *argb_ptr = *rgba_ptr >> 8 | 0xff000000;  // - this version doesn't change endianess
    *argb_ptr = __builtin_bswap32(*rgba_ptr) >> 8 | 0xff000000;  // This does
}

私が最初に作ったのは、シャッフル式を単純化することです。XRGB が単に RGBA >> 8 であることは明らかです。また、各反復での配列インデックスの計算を削除し、ポインターをループ変数として使用しました。このバージョンは、私のマシンのオリジナルよりも約 2 倍高速です。

このコードが x86 CPU を対象としている場合は、シャッフルに SSE を使用することもできます。

于 2012-06-29T13:52:23.967 に答える
0

アセンブリを使用します。以下は Intel の場合です。

この例では、赤と青を入れ替えています。

void* b = pixels;
UINT len = textureWidth*textureHeight;

__asm                                                       
{
    mov ecx, len                // Set loop counter to pixels memory block size
    mov ebx, b                  // Set ebx to pixels pointer
    label:                      
        mov al,[ebx+0]          // Load Red to al
        mov ah,[ebx+2]          // Load Blue to ah
        mov [ebx+0],ah          // Swap Red
        mov [ebx+2],al          // Swap Blue
        add ebx,4               // Move by 4 bytes to next pixel
        dec ecx                 // Decrease loop counter
        jnz label               // If not zero jump to label
}
于 2016-06-04T06:52:32.167 に答える