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

Re: [pygame] PixelArray question



On, Thu Aug 23, 2007, Brian Fisher wrote:

> Marcus,
> The feature set you are aiming at sounds like it has some very useful
> features in it. Thanks for explaining it more.
> 
> On 8/23/07, Marcus von Appen <mva@xxxxxxxxxxxx> wrote:

[...]
> > > would become this:
> > >         sf = pygame.Surface ((10, 20))
> > >         sf.fill ((0, 0, 0))
> > >         ar2 = sf[0]
> >
> > Personally I'd (especially if I'd be new to pygame) expect the latter to
> > return a Surface of size 1x20, not a PixelArray. So in my recognition
> > it'd serve a different purpose (being subjective of course).
> >
> Well lets say that is what they'd expect... maybe it should return a
> (sub)surface in that case... However I completely disagree that a user
> would expect Surface[0] to return another surface. I'd expect it to
> return a column of indexable of pixels.

And that's exactly one of the problems. The intention, expectation and
recognition and what it really does in the end. Especially for languages
such as python, where you do not need to work explicitly with
enumerators, iterators, casts. As you initially said - where to separate
and why not putting this to that, etc. Hard to determine, but my
personal assumption is, that using an explicit wrapper is better than
such a direct access. It is less confusing as the user explicitly knows,
that it is somewhat different.


> 
> > > The advantages as I see it are:
> > > 1. you type less when you know how to do stuff
> >
> > p.i.l(file) also would let you type less, when you know how to do stuff,
> > it does not make it more clear, however, especially for newcomers. p.i.l
> > means pygame.image.load() by the way ;-).
> >
> Excellent Point - I shouldn't have said "type less" - I'm for
> variables and functions being long.
> 
> What I should have said is it lets you "do less". If there is not
> benefit to me to create the object as a user of the library, then why
> make me create it? Basically let me have less to think about and read,
> unless giving me more to think about and read helps me.

That's what's done with explicitly wrapping it up in my opinion. It
helps to clarify what such an access in contrast to sf[x] does.

> 
> > > 2. If you construct a PixelArray from a surface, it's not clear at all
> > > that it's data and functionality are intertwined with the Surface's
> > > content. However if you get a PixelArray through buffer/slicing
> > > access, It is fairly clear that ar2 is actually meaningfully
> > > intertwined with sf's data (because you got it as being an element of
> > > the surface)
> >
> > That applies to a lot of problems, libraries, classes, etc.. The
> > surfarray module suffers from them as well. Not to mention python's
> > buffer() function, which either uses a copy or direct access of an
> > object's data stream. Documentation is the key to use here.
> >
> This is another logical fallacy. It's jumping on the bandwagon. Just
> because some other library/class/whatever may have issues like this,
> doesn't mean that it isn't better to be without it in this case.

I never said (or wrote that) and never meant that either. What I wanted
to say is: if there could be doubts, clarify anything in the docs.

> 
> So tell me what you think of this:
> 
>   string = "hello world"
>   reader = CharacterReader(string)
>   print reader[0]
> 
> instead of this:
> 
>   string = "hello world"
>   print string[0]
> 
> does one look like a better interface to you?

That depends on the functionality of both and what purpose they
serve. The first looks (by a first glance) like a iterator based system,
that reads characters from a stream. Depdendant on its docs and
implementation it uses either a copy or direct access. The second
directly accesses string. For the first I'd read the docs, for the
latter I would not care, but assume this and that.

So what's the better interface then? The one, that clearly states what
it does, or the second, that (especially for the surface case) depends
on user recognition?

> 
> > > 3. It's kind of what someone completely fresh to the problem would
> > > expect to be able to
> >
> > I gave you a counter-example above. It's subjective (hello purpose ;-).
> >
> I agree that people could have different initial thoughts about how to
> index pixels in a surface. I think I worded what I was trying to say
> poorly.
> 
> What I meant was surfaces have pixels, python has indexing operations,
> why couldn't I index the pixels in my surface? I know I expected to be
> able to do this as a by product of locking the surface (like DirectX
> and SDL work)

I guess, it's free to everyone to create such an interface directly
within the Surface. In my opinion however, it'd cause the user to read
up the docs in order to not be confused about the meaning of surface[x],
surface[x:y], etc.
PixelArray (except the naming maybe as you mentioned later in your mail)
does not suffer from that (that much - once more my opinion).

>
>
> 
> > > The possible disadvantages that I see are:
> > > 1. It's kind of what someone completely fresh to the problem would
> > > expect to be able to... but it may not be signficantly differently
> > > from what they'd expect to be able to do in?
> >
> > No idea, what you mean here.
> >
> I just meant that an api that looks like it behaves one way, but
> either doesn't behave that way or has a bunch of gotchas in it, is
> worse than one that maybe puts more work on the user upfront, but
> reads well and behaves well.

Right - this is why the PixelArray wrapping was called intp existance :-).

> One point along those lines,  when I first read PixelArray, I thought
> that the object would own the array and therefore have a copy. I
> actually think a name more like PixelAccessor or something would more
> clearly identify that it doesn't own it's own array, and actually
> modifies the surface.

The naming might not be perfect, especially in regard to the long-term
naming of surfarray.arrayXX and surfarray.pixelsXX. PixelAccessor
however let's me assume linear access, not a 2D access ;-). I'll discuss
that with Rene. Alternative namings are welcome.
 
> 
> > See the purpose, user expectation and recognition discussion we had so
> > far, when it comes to design. One big implementation issue might be the
> > buffer interface and locking we need for it. As it is uncertain at which
> > time the requester of the buffer does not need it anymore, we have to
> > rely on the user's explicit unlock (by using del array or in your
> > example a call to sf.unlock():
> >
> >         sf = pygame.Surface ((10, 20))
> >         sf.fill ((0, 0, 0))
> >         buffer_request (sf)
> >         sf.unlock()
> >
> I don't see why you'd have to do that - if buffer access to the
> surface returned an object, then the returned object can manage
> locking & unlocking for you with it's lifetime. It would work for

The C buffer interface just returns a pointer to the internal buffer, it
does not construct any python object, thus no locking would be possible
as we do not exactly know, at which time the object will be released.
Instead the user code would have to take care of it.

[... ]
> Basically I don't think I know the answer of the best way to implement
> peformant surface content access - others are deeper in it than I, and
> know more about the details. But just based on what I've read,
> Lenard's original post seems like it makes a valid point, and I
> haven't seen any reason in this thread to make me think it wouldn't be
> better to have buffer access on a surface than have a PixelArray
> interface.

I've given you several, not all of them being THE reason why, but in my
opinion with sufficient weight. I only can rely on the experience I made
for now and this is what tells me, that such an implementation is better
for several reasons (as discussed so far).

Regards
Marcus

Attachment: pgpxDuiptMdLx.pgp
Description: PGP signature