On 8 Jul 2006 at 20:51, Kamilche wrote: > Peter Shinners wrote: > > On Sat, 2006-07-08 at 20:04 -0700, Kamilche wrote: > >> Hey Pete, I have another Numeric question for you, if you've got the time. > >> > >> Let's say I have a bunch of data in FFFFRGBA format, where FFFF is an > >> arbitrary floating point number, and RGBA are unsigned bytes. The > >> following routine will convert that to an RGBA picture, but it takes a > >> looooong, time. > >> > >> What's the magical incantation to get Numeric to assign the data > >> directly to the pixels of the surface? > > > > I'm not sure if that can be done actually. Numeric may have a way to do > > "casting" between data types, but I'm not really sure. I was thinking > > Numeric.array_constructor could bind an arbitrary sized and typed array > > onto a string buffer of data. But it looks like that does not work. > > > > You'll need a function like that in order for this to work. I know in > > Python 2.5 the struct module can precompile your formatting codes, which > > would speed this up. I also see that you unpack an "a" value out of the > > binary data, but then throw it away. > > > > Also, since you are doing such simple handling of the "float" data, you > > could probably just treat the whole pixel as a bunch of bytes. All this > > will help a bit, but won't make it orders of magnitude faster. > > > > xspan = range(w) > > ordfunc = ord > > setfunc = pic.set_at > > for y in range(h): > > for x in xspan: > > a = (ordfunc(data[ctr + 3]) & 0x7f < 0x46 and 255 or 0 > > setfunc((x, y), ( > > ordfunc(data[ctr + 4], > > ordfunc(data[ctr + 5], > > ordfunc(data[ctr + 6], > > a)) > > ctr += 8 > > > > > > Sadly, I'm kind of wildly guessing here if that code to compare with > > 0x46 will match a floating point value with less than 6 digits left of > > the decimal. But it works in some simplish tests. > > > > > > > > > > Darn. Well, that explains why my attempts to get it to work failed, > then. Thanks for the info! > > This is the file format for WorldBuilder ZBF files. There's no way to > render an alpha channel, but there IS a way to render with depth > information. That's that float number embedded in there. (The alpha > channel contains all 0's, even if you specify 'render with alpha > channels.') That simple check is in essence saying 'if the pixel is > near, it's opaque; if it's far, it's transparent', but that doesn't give > you antialiasing on the picture. So, I render it too big by a factor of > 3, apply the near/far algorithm, then shrink the result down. Then, > FINALLY, it gives me what I want. > > It would be far easier if WorldBuilder would just render with alpha > channels in the first place. :-P > Possibly this works. I have no zbf files to test it on.
# Array for extracting rgb information rgb = Numeric.fromstring(data, Numeric.UInt8) rgb.shape = (w, h, 8) # Array for extracting distances d = Numeric.fromstring(data, Numeric.Float32) d.shape = (w, h, 2) # Create alpha plane a = ((d[:,:,0] < 100000.0) * 255).astype(Numeric.UInt8) # Combine rgb and alpha information pic = pygame.Surface((w, h), pygame.SRCALPHA, 32) pygame.surfarray.blit_array(pic, rgb[:,:,4:7]) pygame.surfarray.pixels_alpha(pic)[:,:] = a There may be room for improvement. Possibly pygame.surfarray.make_surface() when passed a (w, h, 4) array will create a surface with alpha. I just don't know. The 3d array routines ignore alpha. Lenard Lindstrom <[EMAIL PROTECTED]>