I have a RGB image (RGB 4:4:4 colorspace, 24-bit per pixel), captured from camera. I use Gorgon 2D library (build base on SharpDX) to display this image as a texture so i have to convert it to ARGB. I use this code (not my code) to convert from RGB camera image to RGBA.
[StructLayout(LayoutKind.Sequential)]
public struct RGBA
{
public byte r;
public byte g;
public byte b;
public byte a;
}
[StructLayout(LayoutKind.Sequential)]
public struct RGB
{
public byte r;
public byte g;
public byte b;
}
unsafe void internalCvt(long pixelCount, byte* rgbP, byte* rgbaP)
{
for (long i = 0, offsetRgb = 0; i < pixelCount; i += 4, offsetRgb += 12)
{
uint c1 = *(uint*)(rgbP + offsetRgb);
uint c2 = *(uint*)(rgbP + offsetRgb + 3);
uint c3 = *(uint*)(rgbP + offsetRgb + 6);
uint c4 = *(uint*)(rgbP + offsetRgb + 9);
((uint*)rgbaP)[i] = c1 | 0xff000000;
((uint*)rgbaP)[i + 1] = c2 | 0xff000000;
((uint*)rgbaP)[i + 2] = c3 | 0xff000000;
((uint*)rgbaP)[i + 3] = c4 | 0xff000000;
}
}
public unsafe void RGB2RGBA(int pixelCount, byte[] rgbData, byte[] rgbaData)
{
if ((pixelCount & 3) != 0) throw new ArgumentException();
fixed (byte* rgbP = &rgbData[0], rgbaP = &rgbaData[0])
{
internalCvt(pixelCount, rgbP, rgbaP);
}
}
Then convert RGB to RGBA like this:
byte[] rgb = new byte[800*600*3]; //Stored data
byte[] rgba = new byte[800 * 600 * 4];
RGB2RGBA(800*600, rgb, rgba)
And I use rgba as data of Gorgon texture:
unsafe
{
fixed(void* rgbaPtr = rgba)
{
var buff = new GorgonNativeBuffer<byte>(rgbaPtr, 800*600*4);
GorgonImageBuffer imb = new GorgonImageBuffer(buff, 800, 600, BufferFormat.R8G8B8A8_UNorm);
//Set Texture data GorgonTexture2D
Texture.SetData(imb, new SharpDX.Rectangle(0, 0, 800, 600), 0, 0, CopyMode.NoOverwrite);
}
}
But the color of texture image is not like the color of camera image.
so I think I have to convert camera image to ARGB, (not RGBA) so that it can display with Gorgon texture but i dont know how to do it with the code above. Can you guys please point me some hints?
Thanks!
Below are the links to types of Gorgon Library i used in the code above
GorgonTexture2D
GorgonNativeBuffer
GorgonImageBuffer
The byte order of the target is, in memory, R G B A
. The byte order of the source is, in memory, B G R
. So in addition to expanding every 3 bytes to 4 bytes and putting FF in the new A channel, the R and B channel need to swap position. For example,
unsafe void internalCvt(long pixelCount, byte* rgbP, uint* rgbaP)
{
for (long i = 0, offsetRgb = 0; i < pixelCount; i += 4, offsetRgb += 12)
{
uint c1 = *(uint*)(rgbP + offsetRgb);
uint c2 = *(uint*)(rgbP + offsetRgb + 3);
uint c3 = *(uint*)(rgbP + offsetRgb + 6);
uint c4 = *(uint*)(rgbP + offsetRgb + 9);
// swap R and B
c1 = (c1 << 16) | (c1 & 0xFF00) | ((c1 >> 16) & 0xFF);
c2 = (c2 << 16) | (c2 & 0xFF00) | ((c2 >> 16) & 0xFF);
c3 = (c3 << 16) | (c3 & 0xFF00) | ((c3 >> 16) & 0xFF);
c4 = (c4 << 16) | (c4 & 0xFF00) | ((c4 >> 16) & 0xFF);
// set alpha to FF
rgbaP[i] = c1 | 0xff000000;
rgbaP[i + 1] = c2 | 0xff000000;
rgbaP[i + 2] = c3 | 0xff000000;
rgbaP[i + 3] = c4 | 0xff000000;
}
}
Or a simpler version that processes one pixel per iteration and doesn't use unsafe
,
void internalCvt(long pixelCount, byte[] bgr, byte[] rgba)
{
long byteCount = pixelCount * 4;
for (long i = 0, offsetBgr = 0; i < byteCount; i += 4, offsetRgb += 3)
{
// R
rgba[i] = bgr[offsetBgr + 2];
// G
rgba[i + 1] = bgr[offsetBgr + 1];
// B
rgba[i + 2] = bgr[offsetBgr];
// A
rgba[i + 3] = 0xFF;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With