Change RGBA to BGRA

Hello all

I need to get a BGRA byte array. The reason is: it seems that this is one of the ‘native’ form of interleaved pixels to display them hardware accelerated out of memory. There are also forms like ARGB in the world for different purposes. However that’s not what I’m actually searching, but anyhow I can imagine others would like to use that too.

Actually, I know how to get RGBA with “permute CXYZ”. Okay, I admit that I copied this from the C-library code. :wink: But I didn’t found any way to permute it differently than RGBA.

I’m pretty sure I just didn’t found the right way. It would be something like swapping channels before permute or so.

Has anybody an idea how that could be done?

@boessu Welcome to the forum! If swapping channels is all you would like to do, try

gmic sp lena to_rgba s c rv[0,2] a c

s c → split channels
rv → reverse R and B
a c → append channels

G’MIC reference: http://gmic.eu/reference.shtml

Thanks alot. What a great community G’MIC has. An answer in a day, even if it is a basic question. That’s really cool!

Yes, that’s what I’ve basically searched. I’m in the situation that I need to get at the end (Byte) BGRA in Integer (32 bit) values for a little-endian display; e.g. Intel. :wink:
In my case I had to re-calculate that in Java if it is not possible to fill the memory buffer in the right order. For that sort of tasks, Java is not the preferred way to do (performance-wise).

The more advanced question is how to get “pre-multiplied” BGRA. Actually I’m not sure what I must ask for that, or if that’s even out of the G’MIC target. If the float values would be max 1.0, it’s a simple multiplication of every color channel with the alpha channel. Or at least the alpha channel should be something between 0.0 and 1.0, but at the end the Alpha channel needs to be something in the byte range 0-255 (or max of the image value range, if it will be converted to UByte). As far as I understood that, that’s not how G’MIC works with float. Maybe I missed there the right way too.

I’m a bit late, but I’d suggest this trick, that is probably faster than the previous solution and avoid extra buffer copies (using shared memory images):

gmic sp lena to_rgba sh. 0,2 mirror. c rm.

And now with some more explanation please :wink:

Yes, please explain. I never use sh because I can’t wrap my head around it even though I have read the tutorial :blush:.

Yes, that’s around 25% faster. At least here.
As the other ones already written: I don’t understand what’s going on, but it’s remarkably faster. :wink:

Is it possible to premultiply that for display too? In the example it would be something like “every Colorchannel * Alphachannel / 255” (if 255 is the max. Alpha value). Or directly in Java spoken it’s “color * alpha >>> 8”… I think it could be done with some sort of blending?

Of course in a normal picture without a transparent alpha channel (like the lena sample here) this has no effect at all… So it makes only real sense if the input picture itself is RGBA.

Command shared (eq. to sh) is one of the dangerous command of G’MIC :slight_smile: Basically, you can make the G’MIC interpreter segfault if you use it the wrong way.
That being said, it is also a very useful command !

Basically, sh[img] ind0,ind1 will insert a new image at the end of the list, that has the particularity to share its data buffer with image img, more precisely only for the channels from ind0 to ind1
(there are also ways to get other kind of shared portions of an image than channels, but I won’t detail it here).

So, if you have a RGB or RGBA image img (image with 3 or 4 channels), invoking sh[img] 0,2 will insert a new RGB-only shared image. Now if you process this new image, you’ll also modify the original image img (that is what a shared image is defined for!).

If I go back to my example, this means that :

sh. 0,2      # Get only the RGB-portion of the latest RGB or RGBA image.
mirror.  c   # Apply mirroring along the c-channel, so RGB becomes BGR.
rm.          # Remove the shared image, we don't need it anymore.

This is faster because no buffer copies are involved during the process. A shared image by definition does not copy the original data, and the mirror command just acts in-place.

2 Likes

I guess a quite fast way to do that would be:

  sh. 0,2           # Get the shared RGB portion of the latest RGBA image.
  mirror. c         # RGB becomes BGR
  sh.. 3            # Get the shared alpha from the BGRA image.
  *[-2,-1] /. 255   # Multiply BGR and alpha together and divide result by 255.
  rm.               # Remove remaining shared BGR image

Thanks a lot. That really works, and is fast.
I’ll try to contribute a commands file on github with these two filters.

1 Like