On 26Nov2017 01:09, Greg Tibbet <gtibbe...@msn.com> wrote:
>I've got a small program that uses PIL to create an image, draw some
>primitives (rectanges, ellipses, etc...) and save it.  Works fine...
>no issues.
>
>I've found in the past, the best way to "really learn" the language
>was to "dig into the guts" and understand it,.. I thought I was making
>progress, but when looking into the PIL library to see what's going on
>behind the scenes, I find the following code in ImageDraw.py
>
>def ellipse(self, xy, fill=None, outline=None):
>        """Draw an ellipse."""
>        ink, fill = self._getink(outline, fill)
>        if fill is not None:
>            self.draw.draw_ellipse(xy, fill, 1)
><...snipped...>
>
>ellipse() uses the method  self.draw.draw_ellipse()   Okay, fine...
>but WHERE is draw_ellipse defined??  What magic is happening there?
>I've searched the entire PIL directory tree, and the ONLY two places
>draw_ellipse is mentioned are right there in the ellipse() function...
>WHAT am I missing??

"ellispse()" is a method in the ImageDraw class. Looking at the __init__ method
 of that class we see:

  self.draw = Image.core.draw(self.im, blend)

so "self.draw" in your code above is the result of "Image.core.draw(self.im,
blend)". "Image" is the Image module imported at the top of ImageDraw.py. So we
 hop over to Image.py, which has this code:

    try:
        # If the _imaging C module is not present, you can still use
        # the "open" function to identify files, but you cannot load
        # them.  Note that other modules should not refer to _imaging
        # directly; import Image and use the Image.core variable instead.
        import _imaging
        core = _imaging
        del _imaging
    except ImportError, v:
        core = _imaging_not_installed()
        if str(v)[:20] == "Module use of python" and warnings:
            # The _imaging C module is present, but not compiled for
            # the right version (windows only).  Print a warning, if
            # possible.
            warnings.warn(
                "The _imaging extension was built for another version "
                "of Python; most PIL functions will be disabled",
                RuntimeWarning
                )

Now the import works (because you'd get exceptions otherwise), so code which
matters is that the top of that:

    import _imaging
    core = _imaging
    del _imaging

So "core" is a reference to the "_imaging" module (and the name "_imaging" has
been discarded). So... The name Image.core is now a reference to that module.

So back in ImageDraw, the call to "Image.core.draw()" called the function
"draw" from the _imaging module, which presumably returns some kind of drawing
object, and _that_ object has a "draw_ellispe" method.

Now, dynamic languages like Python don't lend themselves to screamingly fast
compute, so expensive stuff like drawing graphics is usually done by hooking
into special purpose libraries written in C or something that compiles to
efficient machine level code (C++, Go, what have you).

You can ship C code with Python to be compiled on the target and presented to
Python as a library, and by convention such modules are named with a leading
underscore. So we can expect that _imaging is a C code module.

And if you go up a level you'll find _imaging.c, with a draw_ellipse function
inside it.

Cheers,
Cameron Simpson <c...@cskk.id.au> (formerly c...@zip.com.au)

-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to