[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Numeric Question



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
<len-l@xxxxxxxxx>