1

From a SDK I get images that have the pixel format BGR packed, i.e. BGRBGRBGR. For another application, I need to convert this format to RGB planar RRRGGGBBB.

I am using C# .NET 4.5 32bit and the data is in byte arrays which have the same size.

Right now I am iterating through the array source and assigning the BGR values to there appropriate places in the target array, but that takes too long (180ms for a 1,3megapixel image). The processor the code runs at has access to MMX, SSE, SSE2, SSE3, SSSE3.

Is there a way to speed up the conversion?

edit: Here is the conversion I am using:

// the array with the BGRBGRBGR pixel data
byte[] source;
// the array with the RRRGGGBBB pixel data
byte[] result;
// the amount of pixels in one channel, width*height
int imageSize;

for (int i = 0; i < source.Length; i += 3)
{
    result[i/3] = source[i + 2]; // R
    result[i/3 + imageSize] = source[i + 1]; // G
    result[i/3 + imageSize * 2] = source[i]; // B
}

edit: I tried splitting the access to the source array into three loops, one for each channel, but it didn't really help. So I'm open to suggestions.

for (int i = 0; i < source.Length; i += 3)
{
    result[i/3] = source[i + 2]; // R
}

for (int i = 0; i < source.Length; i += 3)
{
    result[i/3 + imageSize] = source[i + 1]; // G
}

for (int i = 0; i < source.Length; i += 3)
{
    result[i/3 + imageSize * 2] = source[i]; // B
}

Bump because the question is still unanswered. Any advise is very appreciated!

RBS
  • 137
  • 1
  • 10
  • 2
    It would be hard for anyone to see if a faster conversion could be made when the original conversion isn't available – Sayse Dec 12 '14 at 07:37
  • Please show some code for your current approach – MakePeaceGreatAgain Dec 12 '14 at 07:45
  • 1
    Vote to reopen. Seriously, he is not asking for a library. Even given the code I can see a couple of ways to speed it up - SIGNIFICANTLY - by rewriting it. There are valid answers to that within the .NET framework / the Visual Studio standard ecosystem WITHOUT a third party library. – TomTom Dec 12 '14 at 09:31
  • For the record, I vtc'ed because it was unclear without a code example. Voted to reopen – Sayse Dec 12 '14 at 10:18
  • I'd really like to hear your ideas, TomTom. But apparently getting the question back on-topic is not going to happen? – RBS Dec 12 '14 at 13:07
  • Multiplication is generally faster than division, so I advise using `i++` and `i*3` rather than `i+=3` and `i/3`. Also worth considering: do the aforementioned mathematical operation only once per iteration and store it in a variable, instead of executing it three times. – Nyerguds Jan 05 '18 at 14:17

2 Answers2

1

You could try to use SSE3's PSHUFB - Packed Shuffle Bytes instruction. Make sure you are using aligned memory read/writes. You will have to do something tricky to deal with the last dangling B value in each XMMWORD-sized block. Might be tough to get it right but should be a huge speedup. You could also look for library code. I'm guessing you will need to make a C or C++ DLL and use P/Invoke, but maybe there is a way to use SSE instructions from C# that I don't know about.

edit - this question is for a slightly different problem, ARGB to BGR, but the techniques used are similar to what you need.

Community
  • 1
  • 1
japreiss
  • 11,111
  • 2
  • 40
  • 77
  • Thanks for the help, but I unfortunately lack knowledge about intrinsics, so that code won't help me much and using libraries just for this small task is out of the question. – RBS Dec 17 '14 at 11:55
0

Basler company has a SDK for their cameras, called Basler Pylon, working in Windows and Linux.
This SDK has APIs for C++, C# and more.
It has an image conversion class PixelDataConverter, which seems to be what you need.

Tobias Knauss
  • 3,361
  • 1
  • 21
  • 45