Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DX11 convert pixel format BGRA to RGBA

Tags:

directx-11

I have currently the problem that a library creates a DX11 texture with BGRA pixel format. But the displaying library can only display RGBA correctly. (This means the colors are swapped in the rendered image)

After looking around I found a simple for-loop to solve the problem, but the performance is not very good and scales bad with higher resolutions. I'm new to DirectX and maybe I just missed a simple function to do the converting.

// Get the image data
unsigned char* pDest = view->image->getPixels();

// Prepare source texture
ID3D11Texture2D* pTexture = static_cast<ID3D11Texture2D*>( tex );

// Get context
ID3D11DeviceContext* pContext = NULL;
dxDevice11->GetImmediateContext(&pContext);

// Copy data, fast operation
pContext->CopySubresourceRegion(texStaging, 0, 0, 0, 0, tex, 0, nullptr);

// Create mapping 
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( texStaging, 0, D3D11_MAP_READ, 0, &mapped );

if ( FAILED( hr ) )
{
    return;
}

// Calculate size
const size_t size = _width * _height * 4;

// Access pixel data
unsigned char* pSrc = static_cast<unsigned char*>( mapped.pData );

// Offsets
int offsetSrc = 0;
int offsetDst = 0;
int rowOffset = mapped.RowPitch % _width;

// Loop through it, BRGA to RGBA conversation
for (int row = 0; row < _height; ++row)
{
    for (int col = 0; col < _width; ++col)
    {
        pDest[offsetDst] = pSrc[offsetSrc+2];
        pDest[offsetDst+1] = pSrc[offsetSrc+1];
        pDest[offsetDst+2] = pSrc[offsetSrc];
        pDest[offsetDst+3] = pSrc[offsetSrc+3];

        offsetSrc += 4;
        offsetDst += 4;
    }

    // Adjuste offset
    offsetSrc += rowOffset;
}

// Unmap texture
pContext->Unmap( texStaging, 0 );

Solution:

    Texture2D txDiffuse : register(t0);
SamplerState texSampler : register(s0);

struct VSScreenQuadOutput
{
float4 Position : SV_POSITION;
float2 TexCoords0 : TEXCOORD0;
};

float4 PSMain(VSScreenQuadOutput input) : SV_Target
{
return txDiffuse.Sample(texSampler, input.TexCoords0).rgba;
}
like image 449
MAGYS Avatar asked Jun 10 '14 18:06

MAGYS


1 Answers

Obviously iterating over a texture on you CPU is not the most effective way. If you know that colors in a texture are always swapped like that and you don't want to modify the texture itself in your C++ code, the most straightforward way would be to do it in the pixel shader. When you sample the texture, simply swap colors there. You won't even notice any performance drop.

like image 65
Elvithari Avatar answered Oct 21 '22 05:10

Elvithari