[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>