First a bit of context.
I am trying to draw into a Gdk (actually pygtk) pixbuf with Cairo (actually pycairo). My original code looked like this:
import cairo as C
import gtk.gdk as GG
FMT = C.FORMAT_ARGB32
CSP = GG.COLORSPACE_RGB
st = C.ImageSurface.format_stride_for_width(FMT, zw)
surf = C.ImageSurface(FMT, zw, zh)
c = C.Context(surf)
# draw into c here ...
pixels = surf.get_data()
return GG.pixbuf_new_from_data(pixels, CSP, True, 8, zw, zh, st)
For a time, it looked like this would just work, until I tried to draw colors instead of just black text. It turns out the two libraries disagree on byte order, like so:
# !!! FIXME !!! cairo ARGB surfaces and gdk pixbufs disagree on bytesex:
# cairo: LSB --> B G R A <-- MSB
# gdk: LSB --> R G B A <-- MSB
# !!! WTF !!!
The result is (after blitting from the pixbuf to screen) an image with red and blue channels swapped :-(
So, if I keep using pixbufs (as I want to) I need to postprocess the data, swapping every 1st byte with every 3rd. I can do that in plain python:
def changesex(data):
i0 = 0
i2 = 2
l = len(data)
while i2 < l:
temp = data[i0]
data[i0] = data[i2]
data[i2] = temp
i0 += 4
i2 += 4
but I thought using numpy might be faster if there is a built-in operator for this written in C. Something like this:
a = np.frombuffer(data, dtype=np.uint8)
a.shape = (len(data) / 4, 4)
temp = a[:,0]
a[:,0] = a[:,2]
a[:,2] = temp
Am I just dreaming?
Noting a
your initial (N,4)
array of B,G,R,A
, you could get a (N,4)
representation as R,G,B,A
rather simply using some advanced indexing:
a = np.frombuffer(data, dtype=np.uint8)
a.shape = (-1, 4)
rearranged = a[:,[2,1,0,3]]