Argh!! Can't wrap my head around this Python stuff!
nospam.nospam.Cameron Simpson
cs at cskk.id.au
Sun Nov 26 04:01:00 EST 2017
On 26Nov2017 01:09, Greg Tibbet <gtibbet27 at 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 <cs at cskk.id.au> (formerly cs at zip.com.au)
More information about the Python-list
mailing list