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