CINXE.COM
PEP 368 – Standard image protocol and class | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 368 – Standard image protocol and class | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0368/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 368 – Standard image protocol and class | peps.python.org'> <meta property="og:description" content="The current situation of image storage and manipulation in the Python world is extremely fragmented: almost every library that uses image objects has implemented its own image class, incompatible with everyone else’s and often not very pythonic. A basi..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0368/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="The current situation of image storage and manipulation in the Python world is extremely fragmented: almost every library that uses image objects has implemented its own image class, incompatible with everyone else’s and often not very pythonic. A basi..."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 368</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 368 – Standard image protocol and class</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Lino Mastrodomenico <l.mastrodomenico at gmail.com></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Inactive draft that may be taken up again at a later time">Deferred</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">28-Jun-2007</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">2.6, 3.0</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even"><p></p></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#pep-deferral">PEP Deferral</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#python-api">Python API</a><ul> <li><a class="reference internal" href="#mode-objects">Mode Objects</a></li> <li><a class="reference internal" href="#image-protocol">Image Protocol</a></li> <li><a class="reference internal" href="#image-and-imagemixin-classes"><code class="docutils literal notranslate"><span class="pre">Image</span></code> and <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> Classes</a></li> <li><a class="reference internal" href="#line-objects">Line Objects</a></li> <li><a class="reference internal" href="#pixel-objects">Pixel Objects</a></li> <li><a class="reference internal" href="#imagesize-class"><code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> Class</a></li> </ul> </li> <li><a class="reference internal" href="#c-api">C API</a></li> </ul> </li> <li><a class="reference internal" href="#examples">Examples</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>The current situation of image storage and manipulation in the Python world is extremely fragmented: almost every library that uses image objects has implemented its own image class, incompatible with everyone else’s and often not very pythonic. A basic RGB image class exists in the standard library (<code class="docutils literal notranslate"><span class="pre">Tkinter.PhotoImage</span></code>), but is pretty much unusable, and unused, for anything except Tkinter programming.</p> <p>This fragmentation not only takes up valuable space in the developers minds, but also makes the exchange of images between different libraries (needed in relatively common use cases) slower and more complex than it needs to be.</p> <p>This PEP proposes to improve the situation by defining a simple and pythonic image protocol/interface that can be hopefully accepted and implemented by existing image classes inside and outside the standard library <em>without breaking backward compatibility</em> with their existing user bases. In practice this is a definition of how a minimal <em>image-like</em> object should look and act (in a similar way to the <code class="docutils literal notranslate"><span class="pre">read()</span></code> and <code class="docutils literal notranslate"><span class="pre">write()</span></code> methods in <em>file-like</em> objects).</p> <p>The inclusion in the standard library of a class that provides basic image manipulation functionality and implements the new protocol is also proposed, together with a mixin class that helps adding support for the protocol to existing image classes.</p> </section> <section id="pep-deferral"> <h2><a class="toc-backref" href="#pep-deferral" role="doc-backlink">PEP Deferral</a></h2> <p>Further exploration of the concepts covered in this PEP has been deferred for lack of a current champion interested in promoting the goals of the PEP and collecting and incorporating feedback, and with sufficient available time to do so effectively.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>A good way to have high quality modules ready for inclusion in the Python standard library is to simply wait for natural selection among competing external libraries to provide a clear winner with useful functionality and a big user base. Then the de facto standard can be officially sanctioned by including it in the standard library.</p> <p>Unfortunately this approach hasn’t worked well for the creation of a dominant image class in the Python world: almost every third-party library that requires an image object creates its own class incompatible with the ones from other libraries. This is a real problem because it’s entirely reasonable for a program to create and manipulate an image using, e.g., PIL (the Python Imaging Library) and then display it using wxPython or pygame. But these libraries have different and incompatible image classes, and the usual solution is to manually “export” an image from the source to a (width, height, bytes_string) tuple and “import” it creating a new instance in the target format. This approach <em>works</em>, but is both uglier and slower than it needs to be.</p> <p>Another “solution” that has been sometimes used is the creation of specific adapters and/or converters from a class to another (e.g. PIL offers the <code class="docutils literal notranslate"><span class="pre">ImageTk</span></code> module for converting PIL images to a class compatible with the Tkinter one). But this approach doesn’t scale well with the number of libraries involved and it’s still annoying for the user: if I have a perfectly good image object why should I convert before passing it to the next method, why can’t it simply accept my image as-is?</p> <p>The problem isn’t by any stretch limited to the three mentioned libraries and has probably multiple causes, including two that IMO are very important to understand before solving it:</p> <ul class="simple"> <li>in today’s computing world an image is a basic type not strictly tied to a specific domain. This is why there will never be a clear winner between the image classes from the three libraries mentioned above (PIL, wxPython and pygame): they cover different domains and don’t really compete with each other;</li> <li>the Python standard library has never provided a good image class that can be adopted or imitated by third part modules. <code class="docutils literal notranslate"><span class="pre">Tkinter.PhotoImage</span></code> provides basic RGB functionality, but it’s by far the slowest and ugliest of the bunch and it can be instantiated only after the Tkinter root window has been created.</li> </ul> <p>This PEP tries to improve this situation in four ways:</p> <ol class="arabic simple"> <li>It defines a simple and pythonic image protocol/interface (both on the Python and the C side) that can be hopefully accepted and implemented by existing image classes inside and outside the standard library <em>without breaking backward compatibility</em> with their existing user bases.</li> <li>It proposes the inclusion in the standard library of three new classes:<ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> provides almost everything necessary to implement the new protocol; its main purpose is to make as simple as possible to support this interface for existing libraries, in some cases as simple as adding it to the list of base classes and doing minor additions to the constructor.</li> <li><code class="docutils literal notranslate"><span class="pre">Image</span></code> is a subclass of <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> and will add a constructor that can resize and/or convert an image between different pixel formats. This is intended to provide a fast and efficient default implementation of the new protocol.</li> <li><code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> is a minor helper class. See below for details.</li> </ul> </li> <li><code class="docutils literal notranslate"><span class="pre">Tkinter.PhotoImage</span></code> will implement the new protocol (mostly through the <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> class) and all the Tkinter methods that can receive an image will be modified the accept any object that implements the interface. As an aside the author of this PEP will collaborate with the developers of the most common external libraries to achieve the same goal (supporting the protocol in their classes and accepting any class that implements it).</li> <li>New <code class="docutils literal notranslate"><span class="pre">PyImage_*</span></code> functions will be added to the CPython C API: they implement the C side of the protocol and accept as first parameter <strong>any</strong> object that supports it, even if it isn’t an instance of the <code class="docutils literal notranslate"><span class="pre">Image</span></code>/<code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> classes.</li> </ol> <p>The main effects for the end user will be a simplification of the interchange of images between different libraries (if everything goes well, any Python library will accept images from any other library) and the out-of-the-box availability of the new <code class="docutils literal notranslate"><span class="pre">Image</span></code> class. The new class is intended to cover simple but common use cases like cropping and/or resizing a photograph to the desired size and passing it an appropriate widget for displaying it on a window, or darkening a texture and passing it to a 3D library.</p> <p>The <code class="docutils literal notranslate"><span class="pre">Image</span></code> class is not intended to replace or compete with PIL, Pythonmagick or NumPy, even if it provides a (very small) subset of the functionality of these three libraries. In particular PIL offers very rich image manipulation features with <em>dozens</em> of classes, filters, transformations and file formats. The inclusion of PIL (or something similar) in the standard library may, or may not, be a worthy goal but it’s completely outside the scope of this PEP.</p> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <p>The <code class="docutils literal notranslate"><span class="pre">imageop</span></code> module is used as the <em>default</em> location for the new classes and objects because it has for a long time hosted functions that provided a somewhat similar functionality, but a new module may be created if preferred (e.g. a new “<code class="docutils literal notranslate"><span class="pre">image</span></code>” or “<code class="docutils literal notranslate"><span class="pre">media</span></code>” module; the latter may eventually include other multimedia classes).</p> <p><code class="docutils literal notranslate"><span class="pre">MODES</span></code> is a new module level constant: it is a set of the pixel formats supported by the <code class="docutils literal notranslate"><span class="pre">Image</span></code> class. Any image object that implements the new protocol is guaranteed to be formatted in one of these modes, but libraries that accept images are allowed to support only a subset of them.</p> <p>These modes are in turn also available as module level constants (e.g. <code class="docutils literal notranslate"><span class="pre">imageop.RGB</span></code>).</p> <p>The following table is a summary of the modes currently supported and their properties:</p> <table class="docutils align-default"> <thead> <tr class="row-odd"><th class="head">Name</th> <th class="head">Component names</th> <th class="head">Bits per component</th> <th class="head">Subsampling</th> <th class="head">Valid intervals</th> </tr> </thead> <tbody> <tr class="row-even"><td>L</td> <td>l (lowercase L)</td> <td>8</td> <td>no</td> <td>full range</td> </tr> <tr class="row-odd"><td>L16</td> <td>l</td> <td>16</td> <td>no</td> <td>full range</td> </tr> <tr class="row-even"><td>L32</td> <td>l</td> <td>32</td> <td>no</td> <td>full range</td> </tr> <tr class="row-odd"><td>LA</td> <td>l, a</td> <td>8</td> <td>no</td> <td>full range</td> </tr> <tr class="row-even"><td>LA32</td> <td>l, a</td> <td>16</td> <td>no</td> <td>full range</td> </tr> <tr class="row-odd"><td>RGB</td> <td>r, g, b</td> <td>8</td> <td>no</td> <td>full range</td> </tr> <tr class="row-even"><td>RGB48</td> <td>r, g, b</td> <td>16</td> <td>no</td> <td>full range</td> </tr> <tr class="row-odd"><td>RGBA</td> <td>r, g, b, a</td> <td>8</td> <td>no</td> <td>full range</td> </tr> <tr class="row-even"><td>RGBA64</td> <td>r, g, b, a</td> <td>16</td> <td>no</td> <td>full range</td> </tr> <tr class="row-odd"><td>YV12</td> <td>y, cr, cb</td> <td>8</td> <td>1, 2, 2</td> <td>16-235, 16-240, 16-240</td> </tr> <tr class="row-even"><td>JPEG_YV12</td> <td>y, cr, cb</td> <td>8</td> <td>1, 2, 2</td> <td>full range</td> </tr> <tr class="row-odd"><td>CMYK</td> <td>c, m, y, k</td> <td>8</td> <td>no</td> <td>full range</td> </tr> <tr class="row-even"><td>CMYK64</td> <td>c, m, y, k</td> <td>16</td> <td>no</td> <td>full range</td> </tr> </tbody> </table> <p>When the name of a mode ends with a number, it represents the average number of bits per pixel. All the other modes simply use a byte per component per pixel.</p> <p>No palette modes or modes with less than 8 bits per component are supported. Welcome to the 21st century.</p> <p>Here’s a quick description of the modes and the rationale for their inclusion; there are four groups of modes:</p> <ol class="arabic"> <li><strong>grayscale</strong> (<code class="docutils literal notranslate"><span class="pre">L*</span></code> modes): they are heavily used in scientific computing (those people may also need a very high dynamic range and precision, hence <code class="docutils literal notranslate"><span class="pre">L32</span></code>, the only mode with 32 bits per component) and sometimes it can be useful to consider a single component of a color image as a grayscale image (this is used by the individual planes of the planar images, see <code class="docutils literal notranslate"><span class="pre">YV12</span></code> below); the name of the component (<code class="docutils literal notranslate"><span class="pre">'l'</span></code>, lowercase letter L) stands for luminance, the second optional component (<code class="docutils literal notranslate"><span class="pre">'a'</span></code>) is the alpha value and represents the opacity of the pixels: alpha = 0 means full transparency, alpha = 255/65535 represents a fully opaque pixel;</li> <li><strong>RGB* modes</strong>: the garden variety color images. The optional alpha component has the same meaning as in grayscale modes;</li> <li><strong>YCbCr</strong>, a.k.a. YUV (<code class="docutils literal notranslate"><span class="pre">*YV12</span></code> modes). These modes are planar (i.e. the values of all the pixel for each component are stored in a consecutive memory area, instead of the usual arrangement where all the components of a pixel reside in consecutive bytes) and use a 1, 2, 2 (a.k.a. 4:2:0) subsampling (i.e. each pixel has its own Y value, but the Cb and Cr components are shared between groups of 2x2 adjacent pixels) because this is the format that’s by far the most common for YCbCr images. Please note that the V (Cr) plane is stored before the U (Cb) plane.<p><code class="docutils literal notranslate"><span class="pre">YV12</span></code> is commonly used for MPEG2 (including DVDs), MPEG4 (both ASP/DivX and AVC/H.264) and Theora video frames. Valid values for Y are in range(16, 236) (excluding 236), and valid values for Cb and Cr are in range(16, 241). <code class="docutils literal notranslate"><span class="pre">JPEG_YV12</span></code> is similar to <code class="docutils literal notranslate"><span class="pre">YV12</span></code>, but the three components can have the full range of 256 values. It’s the native format used by almost all JPEG/JFIF files and by MJPEG video frames. The “strangeness” of these two wrt all the other supported modes derives from the fact that they are widely used that way by a lot of existing libraries and applications; this is also the reason why they are included (and the fact that they can’t losslessly converted to RGB because YCbCr is a bigger color space); the funny 4:2:0 planar arrangement of the pixel values is relatively easy to support because in most cases the three planes can be considered three separate grayscale images;</p> </li> <li><strong>CMYK* modes</strong> (cyan, magenta, yellow and black) are subtractive color modes, used for printing color images on dead trees. Professional designers love to pretend that they can’t live without them, so here they are.</li> </ol> <section id="python-api"> <h3><a class="toc-backref" href="#python-api" role="doc-backlink">Python API</a></h3> <p>See the <a class="reference internal" href="#examples">examples</a> below.</p> <p>In Python 2.x, all the new classes defined here are new-style classes.</p> <section id="mode-objects"> <h4><a class="toc-backref" href="#mode-objects" role="doc-backlink">Mode Objects</a></h4> <p>The mode objects offer a number of attributes and methods that can be used for implementing generic algorithms that work on different types of images:</p> <p><code class="docutils literal notranslate"><span class="pre">components</span></code></p> <blockquote> <div>The number of components per pixel (e.g. 4 for an RGBA image).</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">component_names</span></code></p> <blockquote> <div>A tuple of strings; see the column “Component names” in the above table.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">bits_per_component</span></code></p> <blockquote> <div>8, 16 or 32; see “Bits per component” in the above table.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">bytes_per_pixel</span></code></p> <blockquote> <div><code class="docutils literal notranslate"><span class="pre">components</span> <span class="pre">*</span> <span class="pre">bits_per_component</span> <span class="pre">//</span> <span class="pre">8</span></code>, only available for non planar modes (see below).</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">planar</span></code></p> <blockquote> <div>Boolean; <code class="docutils literal notranslate"><span class="pre">True</span></code> if the image components reside each in a separate plane. Currently this happens if and only if the mode uses subsampling.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">subsampling</span></code></p> <blockquote> <div>A tuple that for each component in the mode contains a tuple of two integers that represent the amount of downsampling in the horizontal and vertical direction, respectively. In practice it’s <code class="docutils literal notranslate"><span class="pre">((1,</span> <span class="pre">1),</span> <span class="pre">(2,</span> <span class="pre">2),</span> <span class="pre">(2,</span> <span class="pre">2))</span></code> for <code class="docutils literal notranslate"><span class="pre">YV12</span></code> and <code class="docutils literal notranslate"><span class="pre">JPEG_YV12</span></code> and <code class="docutils literal notranslate"><span class="pre">((1,</span> <span class="pre">1),)</span> <span class="pre">*</span> <span class="pre">components</span></code> for everything else.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">x_divisor</span></code></p> <blockquote> <div><code class="docutils literal notranslate"><span class="pre">max(x</span> <span class="pre">for</span> <span class="pre">x,</span> <span class="pre">y</span> <span class="pre">in</span> <span class="pre">subsampling)</span></code>; the width of an image that uses this mode must be divisible for this value.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">y_divisor</span></code></p> <blockquote> <div><code class="docutils literal notranslate"><span class="pre">max(y</span> <span class="pre">for</span> <span class="pre">x,</span> <span class="pre">y</span> <span class="pre">in</span> <span class="pre">subsampling)</span></code>; the height of an image that uses this mode must be divisible for this value.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">intervals</span></code></p> <blockquote> <div>A tuple that for each component in the mode contains a tuple of two integers: the minimum and maximum valid value for the component. Its value is <code class="docutils literal notranslate"><span class="pre">((16,</span> <span class="pre">235),</span> <span class="pre">(16,</span> <span class="pre">240),</span> <span class="pre">(16,</span> <span class="pre">240))</span></code> for <code class="docutils literal notranslate"><span class="pre">YV12</span></code> and <code class="docutils literal notranslate"><span class="pre">((0,</span> <span class="pre">2</span> <span class="pre">**</span> <span class="pre">bits_per_component</span> <span class="pre">-</span> <span class="pre">1),)</span> <span class="pre">*</span> <span class="pre">components</span></code> for everything else.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">get_length(iterable[integer])</span> <span class="pre">-></span> <span class="pre">int</span></code></p> <blockquote> <div>The parameter must be an iterable that contains two integers: the width and height of an image; it returns the number of bytes needed to store an image of these dimensions with this mode.</div></blockquote> <p>Implementation detail: the modes are instances of a subclass of <code class="docutils literal notranslate"><span class="pre">str</span></code> and have a value equal to their name (e.g. <code class="docutils literal notranslate"><span class="pre">imageop.RGB</span> <span class="pre">==</span> <span class="pre">'RGB'</span></code>) except for <code class="docutils literal notranslate"><span class="pre">L32</span></code> that has value <code class="docutils literal notranslate"><span class="pre">'I'</span></code>. This is only intended for backward compatibility with existing PIL users; new code that uses the image protocol proposed here should not rely on this detail.</p> </section> <section id="image-protocol"> <h4><a class="toc-backref" href="#image-protocol" role="doc-backlink">Image Protocol</a></h4> <p>Any object that supports the image protocol must provide the following methods and attributes:</p> <p><code class="docutils literal notranslate"><span class="pre">mode</span></code></p> <blockquote> <div>The format and the arrangement of the pixels in this image; it’s one of the constants in the <code class="docutils literal notranslate"><span class="pre">MODES</span></code> set.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">size</span></code></p> <blockquote> <div>An instance of the <a class="reference internal" href="#imagesize-class">ImageSize class</a>; it’s a named tuple of two integers: the width and the height of the image in pixels; both of them must be >= 1 and can also be accessed as the <code class="docutils literal notranslate"><span class="pre">width</span></code> and <code class="docutils literal notranslate"><span class="pre">height</span></code> attributes of <code class="docutils literal notranslate"><span class="pre">size</span></code>.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">buffer</span></code></p> <blockquote> <div>A sequence of integers between 0 and 255; they are the actual bytes used for storing the image data (i.e. modifying their values affects the image pixels and vice versa); the data has a row-major/C-contiguous order without padding and without any special memory alignment, even when there are more than 8 bits per component. The only supported methods are <code class="docutils literal notranslate"><span class="pre">__len__</span></code>, <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code>/<code class="docutils literal notranslate"><span class="pre">__setitem__</span></code> (with both integers and slice indexes) and <code class="docutils literal notranslate"><span class="pre">__iter__</span></code>; on the C side it implements the buffer protocol.<p>This is a pretty low level interface to the image and the user is responsible for using the correct (native) byte order for modes with more than 8 bit per component and the correct value ranges for <code class="docutils literal notranslate"><span class="pre">YV12</span></code> images. A buffer may or may not keep a reference to its image, but it’s still safe (if useless) to use the buffer even after the corresponding image has been destroyed by the garbage collector (this will require changes to the image class of wxPython and possibly other libraries). Implementation detail: this can be an <code class="docutils literal notranslate"><span class="pre">array('B')</span></code>, a <code class="docutils literal notranslate"><span class="pre">bytes()</span></code> object or a specialized fixed-length type.</p> </div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">info</span></code></p> <blockquote> <div>A <code class="docutils literal notranslate"><span class="pre">dict</span></code> object that can contain arbitrary metadata associated with the image (e.g. DPI, gamma, ICC profile, exposure time…); the interpretation of this data is beyond the scope of this PEP and probably depends on the library used to create and/or to save the image; if a method of the image returns a new image, it can copy or adapt metadata from its own <code class="docutils literal notranslate"><span class="pre">info</span></code> attribute (the <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> implementation always creates a new image with an empty <code class="docutils literal notranslate"><span class="pre">info</span></code> dictionary).</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">bits_per_component</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">bytes_per_pixel</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">component_names</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">components</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">intervals</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">planar</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">subsampling</span></code></div> </div> <blockquote> <div>Shortcuts for the corresponding <code class="docutils literal notranslate"><span class="pre">mode.*</span></code> attributes.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">map(function[,</span> <span class="pre">function...])</span> <span class="pre">-></span> <span class="pre">None</span></code></p> <blockquote> <div>For every pixel in the image, maps each component through the corresponding function. If only one function is passed, it is used repeatedly for each component. This method modifies the image <strong>in place</strong> and is usually very fast (most of the time the functions are called only a small number of times, possibly only once for simple functions without branches), but it imposes a number of restrictions on the function(s) passed:<ul class="simple"> <li>it must accept a single integer argument and return a number (<code class="docutils literal notranslate"><span class="pre">map</span></code> will round the result to the nearest integer and clip it to <code class="docutils literal notranslate"><span class="pre">range(0,</span> <span class="pre">2</span> <span class="pre">**</span> <span class="pre">bits_per_component)</span></code>, if necessary);</li> <li>it must <em>not</em> try to intercept any <code class="docutils literal notranslate"><span class="pre">BaseException</span></code>, <code class="docutils literal notranslate"><span class="pre">Exception</span></code> or any unknown subclass of <code class="docutils literal notranslate"><span class="pre">Exception</span></code> raised by any operation on the argument (implementations may try to optimize the speed by passing funny objects, so even a simple <code class="docutils literal notranslate"><span class="pre">"if</span> <span class="pre">n</span> <span class="pre">==</span> <span class="pre">10:"</span></code> may raise an exception: simply ignore it, <code class="docutils literal notranslate"><span class="pre">map</span></code> will take care of it); catching any other exception is fine;</li> <li>it should be side-effect free and its result should not depend on values (other than the argument) that may change during a single invocation of <code class="docutils literal notranslate"><span class="pre">map</span></code>.</li> </ul> </div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">rotate90()</span> <span class="pre">-></span> <span class="pre">image</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">rotate180()</span> <span class="pre">-></span> <span class="pre">image</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">rotate270()</span> <span class="pre">-></span> <span class="pre">image</span></code></div> </div> <blockquote> <div>Return a copy of the image rotated 90, 180 or 270 degrees counterclockwise around its center.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">clip()</span> <span class="pre">-></span> <span class="pre">None</span></code></p> <blockquote> <div>Saturates invalid component values in <code class="docutils literal notranslate"><span class="pre">YV12</span></code> images to the minimum or the maximum allowed (see <code class="docutils literal notranslate"><span class="pre">mode.intervals</span></code>), for other image modes this method does nothing, very fast; libraries that save/export <code class="docutils literal notranslate"><span class="pre">YV12</span></code> images are encouraged to always call this method, since intermediate operations (e.g. the <code class="docutils literal notranslate"><span class="pre">map</span></code> method) may assign to pixels values outside the valid intervals.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">split()</span> <span class="pre">-></span> <span class="pre">tuple[image]</span></code></p> <blockquote> <div>Returns a tuple of <code class="docutils literal notranslate"><span class="pre">L</span></code>, <code class="docutils literal notranslate"><span class="pre">L16</span></code> or <code class="docutils literal notranslate"><span class="pre">L32</span></code> images corresponding to the individual components in the image.</div></blockquote> <p>Planar images also supports attributes with the same names defined in <code class="docutils literal notranslate"><span class="pre">component_names</span></code>: they contain grayscale (mode <code class="docutils literal notranslate"><span class="pre">L</span></code>) images that offer a view on the pixel values for the corresponding component; any change to the subimages is immediately reflected on the parent image and vice versa (their buffers refer to the same memory location).</p> <p>Non-planar images offer the following additional methods:</p> <p><code class="docutils literal notranslate"><span class="pre">pixels()</span> <span class="pre">-></span> <span class="pre">iterator[pixel]</span></code></p> <blockquote> <div>Returns an iterator that iterates over all the pixels in the image, starting from the top line and scanning each line from left to right. See below for a description of the <a class="reference internal" href="#pixel-objects">pixel objects</a>.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__iter__()</span> <span class="pre">-></span> <span class="pre">iterator[line]</span></code></p> <blockquote> <div>Returns an iterator that iterates over all the lines in the image, from top to bottom. See below for a description of the <a class="reference internal" href="#line-objects">line objects</a>.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__len__()</span> <span class="pre">-></span> <span class="pre">int</span></code></p> <blockquote> <div>Returns the number of lines in the image (<code class="docutils literal notranslate"><span class="pre">size.height</span></code>).</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__getitem__(integer)</span> <span class="pre">-></span> <span class="pre">line</span></code></p> <blockquote> <div>Returns the line at the specified (y) position.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__getitem__(tuple[integer])</span> <span class="pre">-></span> <span class="pre">pixel</span></code></p> <blockquote> <div>The parameter must be a tuple of two integers; they are interpreted respectively as x and y coordinates in the image (0, 0 is the top left corner) and a pixel object is returned.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__getitem__(slice</span> <span class="pre">|</span> <span class="pre">tuple[integer</span> <span class="pre">|</span> <span class="pre">slice])</span> <span class="pre">-></span> <span class="pre">image</span></code></p> <blockquote> <div>The parameter must be a slice or a tuple that contains two slices or an integer and a slice; the selected area of the image is copied and a new image is returned; <code class="docutils literal notranslate"><span class="pre">image[x:y:z]</span></code> is equivalent to <code class="docutils literal notranslate"><span class="pre">image[:,</span> <span class="pre">x:y:z]</span></code>.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__setitem__(tuple[integer],</span> <span class="pre">integer</span> <span class="pre">|</span> <span class="pre">iterable[integer])</span> <span class="pre">-></span> <span class="pre">None</span></code></p> <blockquote> <div>Modifies the pixel at specified position; <code class="docutils literal notranslate"><span class="pre">image[x,</span> <span class="pre">y]</span> <span class="pre">=</span> <span class="pre">integer</span></code> is a shortcut for <code class="docutils literal notranslate"><span class="pre">image[x,</span> <span class="pre">y]</span> <span class="pre">=</span> <span class="pre">(integer,)</span></code> for images with a single component.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__setitem__(slice</span> <span class="pre">|</span> <span class="pre">tuple[integer</span> <span class="pre">|</span> <span class="pre">slice],</span> <span class="pre">image)</span> <span class="pre">-></span> <span class="pre">None</span></code></p> <blockquote> <div>Selects an area in the same way as the corresponding form of the <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> method and assigns to it a copy of the pixels from the image in the second argument, that must have exactly the same mode as this image and the same size as the specified area; the alpha component, if present, is simply copied and doesn’t affect the other components of the image (i.e. no alpha compositing is performed).</div></blockquote> <p>The <code class="docutils literal notranslate"><span class="pre">mode</span></code>, <code class="docutils literal notranslate"><span class="pre">size</span></code> and <code class="docutils literal notranslate"><span class="pre">buffer</span></code> (including the address in memory of the <code class="docutils literal notranslate"><span class="pre">buffer</span></code>) never change after an image is created.</p> <p>It is expected that, if <a class="pep reference internal" href="../pep-3118/" title="PEP 3118 – Revising the buffer protocol">PEP 3118</a> is accepted, all the image objects will support the new buffer protocol, however this is beyond the scope of this PEP.</p> </section> <section id="image-and-imagemixin-classes"> <h4><a class="toc-backref" href="#image-and-imagemixin-classes" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">Image</span></code> and <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> Classes</a></h4> <p>The <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> class implements all the methods and attributes described above except <code class="docutils literal notranslate"><span class="pre">mode</span></code>, <code class="docutils literal notranslate"><span class="pre">size</span></code>, <code class="docutils literal notranslate"><span class="pre">buffer</span></code> and <code class="docutils literal notranslate"><span class="pre">info</span></code>. <code class="docutils literal notranslate"><span class="pre">Image</span></code> is a subclass of <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> that adds support for these four attributes and offers the following constructor (please note that the constructor is not part of the image protocol):</p> <p><code class="docutils literal notranslate"><span class="pre">__init__(mode,</span> <span class="pre">size,</span> <span class="pre">color,</span> <span class="pre">source)</span></code></p> <blockquote> <div><code class="docutils literal notranslate"><span class="pre">mode</span></code> must be one of the constants in the <code class="docutils literal notranslate"><span class="pre">MODES</span></code> set, <code class="docutils literal notranslate"><span class="pre">size</span></code> is a sequence of two integers (width and height of the new image); <code class="docutils literal notranslate"><span class="pre">color</span></code> is a sequence of integers, one for each component of the image, used to initialize all the pixels to the same value; <code class="docutils literal notranslate"><span class="pre">source</span></code> can be a sequence of integers of the appropriate size and format that is copied as-is in the buffer of the new image or an existing image; in Python 2.x <code class="docutils literal notranslate"><span class="pre">source</span></code> can also be an instance of <code class="docutils literal notranslate"><span class="pre">str</span></code> and is interpreted as a sequence of bytes. <code class="docutils literal notranslate"><span class="pre">color</span></code> and <code class="docutils literal notranslate"><span class="pre">source</span></code> are mutually exclusive and if they are both omitted the image is initialized to transparent black (all the bytes in the buffer have value 16 in the <code class="docutils literal notranslate"><span class="pre">YV12</span></code> mode, 255 in the <code class="docutils literal notranslate"><span class="pre">CMYK*</span></code> modes and 0 for everything else). If <code class="docutils literal notranslate"><span class="pre">source</span></code> is present and is an image, <code class="docutils literal notranslate"><span class="pre">mode</span></code> and/or <code class="docutils literal notranslate"><span class="pre">size</span></code> can be omitted; if they are specified and are different from the source mode and/or size, the source image is converted.<p>The exact algorithms used for resizing and doing color space conversions may differ between Python versions and implementations, but they always give high quality results (e.g.: a cubic spline interpolation can be used for upsampling and an antialias filter can be used for downsampling images); any combination of mode conversion is supported, but the algorithm used for conversions to and from the <code class="docutils literal notranslate"><span class="pre">CMYK*</span></code> modes is pretty naïve: if you have the exact color profiles of your devices you may want to use a good color management tool such as LittleCMS. The new image has an empty <code class="docutils literal notranslate"><span class="pre">info</span></code> <code class="docutils literal notranslate"><span class="pre">dict</span></code>.</p> </div></blockquote> </section> <section id="line-objects"> <h4><a class="toc-backref" href="#line-objects" role="doc-backlink">Line Objects</a></h4> <p>The line objects (returned, e.g., when iterating over an image) support the following attributes and methods:</p> <p><code class="docutils literal notranslate"><span class="pre">mode</span></code></p> <blockquote> <div>The mode of the image from where this line comes.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__iter__()</span> <span class="pre">-></span> <span class="pre">iterator[pixel]</span></code></p> <blockquote> <div>Returns an iterator that iterates over all the pixels in the line, from left to right. See below for a description of the <a class="reference internal" href="#pixel-objects">pixel objects</a>.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__len__()</span> <span class="pre">-></span> <span class="pre">int</span></code></p> <blockquote> <div>Returns the number of pixels in the line (the image width).</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__getitem__(integer)</span> <span class="pre">-></span> <span class="pre">pixel</span></code></p> <blockquote> <div>Returns the pixel at the specified (x) position.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__getitem__(slice)</span> <span class="pre">-></span> <span class="pre">image</span></code></p> <blockquote> <div>The selected part of the line is copied and a new image is returned; the new image will always have height 1.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__setitem__(integer,</span> <span class="pre">integer</span> <span class="pre">|</span> <span class="pre">iterable[integer])</span> <span class="pre">-></span> <span class="pre">None</span></code></p> <blockquote> <div>Modifies the pixel at the specified position; <code class="docutils literal notranslate"><span class="pre">line[x]</span> <span class="pre">=</span> <span class="pre">integer</span></code> is a shortcut for <code class="docutils literal notranslate"><span class="pre">line[x]</span> <span class="pre">=</span> <span class="pre">(integer,)</span></code> for images with a single component.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">__setitem__(slice,</span> <span class="pre">image)</span> <span class="pre">-></span> <span class="pre">None</span></code></p> <blockquote> <div>Selects a part of the line and assigns to it a copy of the pixels from the image in the second argument, that must have height 1, a width equal to the specified slice and the same mode as this line; the alpha component, if present, is simply copied and doesn’t affect the other components of the image (i.e. no alpha compositing is performed).</div></blockquote> </section> <section id="pixel-objects"> <h4><a class="toc-backref" href="#pixel-objects" role="doc-backlink">Pixel Objects</a></h4> <p>The pixel objects (returned, e.g., when iterating over a line) support the following attributes and methods:</p> <p><code class="docutils literal notranslate"><span class="pre">mode</span></code></p> <blockquote> <div>The mode of the image from where this pixel comes.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">value</span></code></p> <blockquote> <div>A tuple of integers, one for each component. Any iterable of the correct length can be assigned to <code class="docutils literal notranslate"><span class="pre">value</span></code> (it will be automagically converted to a tuple), but you can’t assign to it an integer, even if the mode has only a single component: use, e.g., <code class="docutils literal notranslate"><span class="pre">pixel.l</span> <span class="pre">=</span> <span class="pre">123</span></code> instead.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">r,</span> <span class="pre">g,</span> <span class="pre">b,</span> <span class="pre">a,</span> <span class="pre">l,</span> <span class="pre">c,</span> <span class="pre">m,</span> <span class="pre">y,</span> <span class="pre">k</span></code></p> <blockquote> <div>The integer values of each component; only those applicable for the current mode (in <code class="docutils literal notranslate"><span class="pre">mode.component_names</span></code>) will be available.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">__iter__()</span> <span class="pre">-></span> <span class="pre">iterator[int]</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">__len__()</span> <span class="pre">-></span> <span class="pre">int</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">__getitem__(integer</span> <span class="pre">|</span> <span class="pre">slice)</span> <span class="pre">-></span> <span class="pre">int</span> <span class="pre">|</span> <span class="pre">tuple[int]</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">__setitem__(integer</span> <span class="pre">|</span> <span class="pre">slice,</span> <span class="pre">integer</span> <span class="pre">|</span> <span class="pre">iterable[integer])</span> <span class="pre">-></span> <span class="pre">None</span></code></div> </div> <blockquote> <div>These four methods emulate a fixed length list of integers, one for each pixel component.</div></blockquote> </section> <section id="imagesize-class"> <h4><a class="toc-backref" href="#imagesize-class" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> Class</a></h4> <p><code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> is a named tuple, a class identical to <code class="docutils literal notranslate"><span class="pre">tuple</span></code> except that:</p> <ul class="simple"> <li>its constructor only accepts two integers, width and height; they are converted in the constructor using their <code class="docutils literal notranslate"><span class="pre">__index__()</span></code> methods, so all the <code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> objects are guaranteed to contain only <code class="docutils literal notranslate"><span class="pre">int</span></code> (or possibly <code class="docutils literal notranslate"><span class="pre">long</span></code>, in Python 2.x) instances;</li> <li>it has a <code class="docutils literal notranslate"><span class="pre">width</span></code> and a <code class="docutils literal notranslate"><span class="pre">height</span></code> property that are equivalent to the first and the second number in the tuple, respectively;</li> <li>the string returned by its <code class="docutils literal notranslate"><span class="pre">__repr__</span></code> method is <code class="docutils literal notranslate"><span class="pre">'imageop.ImageSize(width=%d,</span> <span class="pre">height=%d)'</span> <span class="pre">%</span> <span class="pre">(width,</span> <span class="pre">height)</span></code>.</li> </ul> <p><code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> is not usually instantiated by end-users, but can be used when creating a new class that implements the image protocol, since the <code class="docutils literal notranslate"><span class="pre">size</span></code> attribute must be an <code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> instance.</p> </section> </section> <section id="c-api"> <h3><a class="toc-backref" href="#c-api" role="doc-backlink">C API</a></h3> <p>The available image modes are visible at the C level as <code class="docutils literal notranslate"><span class="pre">PyImage_*</span></code> constants of type <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code> (e.g.: <code class="docutils literal notranslate"><span class="pre">PyImage_RGB</span></code> is <code class="docutils literal notranslate"><span class="pre">imageop.RGB</span></code>).</p> <p>The following functions offer a C-friendly interface to mode and image objects (all the functions return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> or -1 on failure):</p> <p><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImageMode_Check(PyObject</span> <span class="pre">*obj)</span></code></p> <blockquote> <div>Returns true if the object <code class="docutils literal notranslate"><span class="pre">obj</span></code> is a valid image mode.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImageMode_GetComponents(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImageMode_GetComponentNames(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImageMode_GetBitsPerComponent(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImageMode_GetBytesPerPixel(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImageMode_GetPlanar(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImageMode_GetSubsampling(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImageMode_GetXDivisor(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImageMode_GetYDivisor(PyObject</span> <span class="pre">*mode)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span> <span class="pre">PyImageMode_GetLength(PyObject</span> <span class="pre">*mode,</span> <span class="pre">Py_ssize_t</span> <span class="pre">width,</span> <span class="pre">Py_ssize_t</span> <span class="pre">height)</span></code></div> </div> <blockquote> <div>These functions are equivalent to their corresponding Python attributes or methods.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImage_Check(PyObject</span> <span class="pre">*obj)</span></code></p> <blockquote> <div>Returns true if the object <code class="docutils literal notranslate"><span class="pre">obj</span></code> is an <code class="docutils literal notranslate"><span class="pre">Image</span></code> object or an instance of a subtype of the <code class="docutils literal notranslate"><span class="pre">Image</span></code> type; see also <code class="docutils literal notranslate"><span class="pre">PyObject_CheckImage</span></code> below.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImage_CheckExact(PyObject</span> <span class="pre">*obj)</span></code></p> <blockquote> <div>Returns true if the object <code class="docutils literal notranslate"><span class="pre">obj</span></code> is an <code class="docutils literal notranslate"><span class="pre">Image</span></code> object, but not an instance of a subtype of the <code class="docutils literal notranslate"><span class="pre">Image</span></code> type.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImage_New(PyObject</span> <span class="pre">*mode,</span> <span class="pre">Py_ssize_t</span> <span class="pre">width,</span> <span class="pre">Py_ssize_t</span> <span class="pre">height)</span></code></div> </div> <blockquote> <div>Returns a new <code class="docutils literal notranslate"><span class="pre">Image</span></code> instance, initialized to transparent black (see <code class="docutils literal notranslate"><span class="pre">Image.__init__</span></code> above for the details).</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImage_FromImage(PyObject</span> <span class="pre">*image,</span> <span class="pre">PyObject</span> <span class="pre">*mode,</span> <span class="pre">Py_ssize_t</span> <span class="pre">width,</span> <span class="pre">Py_ssize_t</span> <span class="pre">height)</span></code></div> </div> <blockquote> <div>Returns a new <code class="docutils literal notranslate"><span class="pre">Image</span></code> instance, initialized with the contents of the <code class="docutils literal notranslate"><span class="pre">image</span></code> object rescaled and converted to the specified <code class="docutils literal notranslate"><span class="pre">mode</span></code>, if necessary.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImage_FromBuffer(PyObject</span> <span class="pre">*buffer,</span> <span class="pre">PyObject</span> <span class="pre">*mode,</span> <span class="pre">Py_ssize_t</span> <span class="pre">width,</span> <span class="pre">Py_ssize_t</span> <span class="pre">height)</span></code></div> </div> <blockquote> <div>Returns a new <code class="docutils literal notranslate"><span class="pre">Image</span></code> instance, initialized with the contents of the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> object.</div></blockquote> <p><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyObject_CheckImage(PyObject</span> <span class="pre">*obj)</span></code></p> <blockquote> <div>Returns true if the object <code class="docutils literal notranslate"><span class="pre">obj</span></code> implements a sufficient subset of the image protocol to be accepted by the functions defined below, even if its class is not a subclass of <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> and/or <code class="docutils literal notranslate"><span class="pre">Image</span></code>. Currently it simply checks for the existence and correctness of the attributes <code class="docutils literal notranslate"><span class="pre">mode</span></code>, <code class="docutils literal notranslate"><span class="pre">size</span></code> and <code class="docutils literal notranslate"><span class="pre">buffer</span></code>.</div></blockquote> <div class="line-block"> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImage_GetMode(PyObject</span> <span class="pre">*image)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span> <span class="pre">PyImage_GetWidth(PyObject</span> <span class="pre">*image)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span> <span class="pre">PyImage_GetHeight(PyObject</span> <span class="pre">*image)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImage_Clip(PyObject</span> <span class="pre">*image)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImage_Split(PyObject</span> <span class="pre">*image)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyImage_GetBuffer(PyObject</span> <span class="pre">*image)</span></code></div> <div class="line"><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyImage_AsBuffer(PyObject</span> <span class="pre">*image,</span> <span class="pre">const</span> <span class="pre">void</span> <span class="pre">**buffer,</span> <span class="pre">Py_ssize_t</span> <span class="pre">*buffer_len)</span></code></div> </div> <blockquote> <div>These functions are equivalent to their corresponding Python attributes or methods; the image memory can be accessed only with the GIL and a reference to the image or its buffer held, and extra care should be taken for modes with more than 8 bits per component: the data is stored in native byte order and it can be <strong>not</strong> aligned on 2 or 4 byte boundaries.</div></blockquote> </section> </section> <section id="examples"> <h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2> <p>A few examples of common operations with the new <code class="docutils literal notranslate"><span class="pre">Image</span></code> class and protocol:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># create a new black RGB image of 6x9 pixels</span> <span class="n">rgb_image</span> <span class="o">=</span> <span class="n">imageop</span><span class="o">.</span><span class="n">Image</span><span class="p">(</span><span class="n">imageop</span><span class="o">.</span><span class="n">RGB</span><span class="p">,</span> <span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">))</span> <span class="c1"># same as above, but initialize the image to bright red</span> <span class="n">rgb_image</span> <span class="o">=</span> <span class="n">imageop</span><span class="o">.</span><span class="n">Image</span><span class="p">(</span><span class="n">imageop</span><span class="o">.</span><span class="n">RGB</span><span class="p">,</span> <span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">),</span> <span class="n">color</span><span class="o">=</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="c1"># convert the image to YCbCr</span> <span class="n">yuv_image</span> <span class="o">=</span> <span class="n">imageop</span><span class="o">.</span><span class="n">Image</span><span class="p">(</span><span class="n">imageop</span><span class="o">.</span><span class="n">JPEG_YV12</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="n">rgb_image</span><span class="p">)</span> <span class="c1"># read the value of a pixel and split it into three ints</span> <span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">rgb_image</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span> <span class="c1"># modify the magenta component of a pixel in a CMYK image</span> <span class="n">cmyk_image</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span><span class="o">.</span><span class="n">m</span> <span class="o">=</span> <span class="mi">13</span> <span class="c1"># modify the Y (luma) component of a pixel in a *YV12 image and</span> <span class="c1"># its corresponding subsampled Cr (red chroma)</span> <span class="n">yuv_image</span><span class="o">.</span><span class="n">y</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="mi">42</span> <span class="n">yuv_image</span><span class="o">.</span><span class="n">cr</span><span class="p">[</span><span class="n">x</span> <span class="o">//</span> <span class="mi">2</span><span class="p">,</span> <span class="n">y</span> <span class="o">//</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">54</span> <span class="c1"># iterate over an image</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">rgb_image</span><span class="p">:</span> <span class="k">for</span> <span class="n">pixel</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span> <span class="c1"># swap red and blue, and set green to 0</span> <span class="n">pixel</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">pixel</span><span class="o">.</span><span class="n">b</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">pixel</span><span class="o">.</span><span class="n">r</span> <span class="c1"># find the maximum value of the red component in the image</span> <span class="n">max_red</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">pixel</span><span class="o">.</span><span class="n">r</span> <span class="k">for</span> <span class="n">pixel</span> <span class="ow">in</span> <span class="n">rgb_image</span><span class="o">.</span><span class="n">pixels</span><span class="p">())</span> <span class="c1"># count the number of colors in the image</span> <span class="n">num_of_colors</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="n">pixel</span><span class="p">)</span> <span class="k">for</span> <span class="n">pixel</span> <span class="ow">in</span> <span class="n">image</span><span class="o">.</span><span class="n">pixels</span><span class="p">()))</span> <span class="c1"># copy a block of 4x2 pixels near the upper right corner of an</span> <span class="c1"># image and paste it into the lower left corner of the same image</span> <span class="n">image</span><span class="p">[:</span><span class="mi">4</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">:]</span> <span class="o">=</span> <span class="n">image</span><span class="p">[</span><span class="o">-</span><span class="mi">6</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">]</span> <span class="c1"># create a copy of the image, except that the new image can have a</span> <span class="c1"># different (usually empty) info dict</span> <span class="n">new_image</span> <span class="o">=</span> <span class="n">image</span><span class="p">[:]</span> <span class="c1"># create a mirrored copy of the image, with the left and right</span> <span class="c1"># sides flipped</span> <span class="n">flipped_image</span> <span class="o">=</span> <span class="n">image</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="p">:]</span> <span class="c1"># downsample an image to half its original size using a fast, low</span> <span class="c1"># quality operation and a slower, high quality one:</span> <span class="n">low_quality_image</span> <span class="o">=</span> <span class="n">image</span><span class="p">[::</span><span class="mi">2</span><span class="p">,</span> <span class="p">::</span><span class="mi">2</span><span class="p">]</span> <span class="n">new_size</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">size</span><span class="o">.</span><span class="n">width</span> <span class="o">//</span> <span class="mi">2</span><span class="p">,</span> <span class="n">image</span><span class="o">.</span><span class="n">size</span><span class="o">.</span><span class="n">height</span> <span class="o">//</span> <span class="mi">2</span> <span class="n">high_quality_image</span> <span class="o">=</span> <span class="n">imageop</span><span class="o">.</span><span class="n">Image</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="n">new_size</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="n">image</span><span class="p">)</span> <span class="c1"># direct buffer access</span> <span class="n">rgb_image</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span> <span class="k">assert</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">rgb_image</span><span class="o">.</span><span class="n">buffer</span><span class="p">[:</span><span class="mi">3</span><span class="p">])</span> <span class="o">==</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> </pre></div> </div> </section> <section id="backwards-compatibility"> <h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2> <p>There are three areas touched by this PEP where backwards compatibility should be considered:</p> <ul class="simple"> <li><strong>Python 2.6</strong>: new classes and objects are added to the <code class="docutils literal notranslate"><span class="pre">imageop</span></code> module without touching the existing module contents; new methods and attributes will be added to <code class="docutils literal notranslate"><span class="pre">Tkinter.PhotoImage</span></code> and its <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> and <code class="docutils literal notranslate"><span class="pre">__setitem__</span></code> methods will be modified to accept integers, tuples and slices (currently they only accept strings). All the changes provide a superset of the existing functionality, so no major compatibility issues are expected.</li> <li><strong>Python 3.0</strong>: the legacy contents of the <code class="docutils literal notranslate"><span class="pre">imageop</span></code> module will be deleted, according to <a class="pep reference internal" href="../pep-3108/" title="PEP 3108 – Standard Library Reorganization">PEP 3108</a>; everything defined in this proposal will work like in Python 2.x with the exception of the usual 2.x/3.0 differences (e.g. support for <code class="docutils literal notranslate"><span class="pre">long</span></code> integers and for interpreting <code class="docutils literal notranslate"><span class="pre">str</span></code> instances as sequences of bytes will be dropped).</li> <li><strong>external libraries</strong>: the names and the semantics of the standard image methods and attributes are carefully chosen to allow some external libraries that manipulate images (including at least PIL, wxPython and pygame) to implement the new protocol in their image classes without breaking compatibility with existing code. The only blatant conflicts between the image protocol and NumPy arrays are the value of the <code class="docutils literal notranslate"><span class="pre">size</span></code> attribute and the coordinates order in the <code class="docutils literal notranslate"><span class="pre">image[x,</span> <span class="pre">y]</span></code> expression.</li> </ul> </section> <section id="reference-implementation"> <h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2> <p>If this PEP is accepted, the author will provide a reference implementation of the new classes in pure Python (that can run in CPython, PyPy, Jython and IronPython) and a second one optimized for speed in Python and C, suitable for inclusion in the CPython standard library. The author will also submit the required Tkinter patches. For all the code will be available a version for Python 2.x and a version for Python 3.0 (it is expected that the two version will be very similar and the Python 3.0 one will probably be generated almost completely automatically).</p> </section> <section id="acknowledgments"> <h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2> <p>The implementation of this PEP, if accepted, is sponsored by Google through the Google Summer of Code program.</p> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0368.rst">https://github.com/python/peps/blob/main/peps/pep-0368.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0368.rst">2023-09-09 17:39:29 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#pep-deferral">PEP Deferral</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#python-api">Python API</a><ul> <li><a class="reference internal" href="#mode-objects">Mode Objects</a></li> <li><a class="reference internal" href="#image-protocol">Image Protocol</a></li> <li><a class="reference internal" href="#image-and-imagemixin-classes"><code class="docutils literal notranslate"><span class="pre">Image</span></code> and <code class="docutils literal notranslate"><span class="pre">ImageMixin</span></code> Classes</a></li> <li><a class="reference internal" href="#line-objects">Line Objects</a></li> <li><a class="reference internal" href="#pixel-objects">Pixel Objects</a></li> <li><a class="reference internal" href="#imagesize-class"><code class="docutils literal notranslate"><span class="pre">ImageSize</span></code> Class</a></li> </ul> </li> <li><a class="reference internal" href="#c-api">C API</a></li> </ul> </li> <li><a class="reference internal" href="#examples">Examples</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0368.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>