11#!/usr/bin/env python3
22
3- """PPM and PGM image files reading, displaying and writing for Python >= 3.11.
4- -------------------------------------------------------------------------------
3+ """
4+ =====
5+ PyPNM
6+ =====
7+ --------------------------------------------------------------------------
8+ PPM and PGM image files reading, displaying and writing for Python >=3.11.
9+ --------------------------------------------------------------------------
10+
11+ NOTE: This is main `PyPNM for Python >= 3.11`_ build; it actually works with
12+ any Python supporting f-strings, but Tkinter included with CPython < 3.11
13+ could not handle 16 bpc images. If you need more compatibility with
14+ old Python and Tkinter versions, please consider using `PyPNM for Python >= 3.4`_.
515
616Overview
7- ---------
17+ --------
18+
19+ PyPNM module comprise a set of functions for dealing with `PPM`_ and `PGM`_ image files.
20+ Functions included are listed below
21+
22+ :pnm2list: reading binary or ASCII RGB PPM or L PGM file and returning image data
23+ as nested list of int.
24+ :list2bin: getting image data as nested list of int and creating binary PPM (P6) or PGM (P5)
25+ data structure in memory. Suitable for generating data to display with Tkinter
26+ ``PhotoImage (data=...)`` class.
27+ :list2pnmbin: getting image data as nested list of int and writing binary PPM (P6) or PGM (P5)
28+ image file.
29+ Note that bytes generations procedure is different from that used in ``list2bin``.
30+ :list2pnmascii: getting image data as nested list of int and writing ASCII PPM (P3) or PGM (P2) files.
31+ :list2pnm: getting image data as nested list of int and writing either binary or ASCII PNM file depending on ``bin`` argument value.
32+ :create_image: creating empty nested 3D list for image representation.
833
9- PyPNM module is a pack of functions for dealing with PPM and PGM image files.
10- Functions included are:
34+ Usage
35+ -----
1136
12- - `pnm2list`: reading binary or ASCII RGB PPM or L PGM file and returning image data
13- as nested list of int.
14- - `list2bin`: getting image data as nested list of int and creating binary PPM (P6) or PGM (P5)
15- data structure in memory. Suitable for generating data to display with Tkinter `PhotoImage (data=...)` class.
16- - `list2pnmbin`: getting image data as nested list of int and writing binary PPM (P6) or PGM (P5) image file.
17- Note that bytes generations procedure is different from that used in `list2bin`.
18- - `list2pnmascii`: getting image data as nested list of int and writing ASCII PPM (P3) or PGM (P2) files.
19- - `list2pnm`: getting image data as nested list of int and writing either binary or ASCII PNM
20- depending on `bin` argument value.
21- - `create_image`: creating empty nested 3D list for image representation.
37+ After ``from pypnm import pnmlpnm``, use something like
2238
23- Installation
24- -------------
39+ ::
2540
26- Via PyPI:
41+ X, Y, Z, maxcolors, list_3d = pnmlpnm.pnm2list(in_filename)
2742
28- `python -m pip install --upgrade PyPNM`
43+ for reading data from PPM/PGM, where:
2944
30- then in your program import section:
45+ :X, Y, Z: image dimensions (int);
46+ :maxcolors: maximum value of color per channel for current image (int);
47+ :list_3d: image pixel data as list(list(list(int)));
3148
32- `from pypnm import pnmlpnm`
49+ and
3350
34- If you acquired module in some other, non-PyPI way, you may simply put module into your main program folder.
51+ ::
3552
36- Usage
37- ------
53+ pnm_bytes = pnmlpnm.list2bin(list_3d, maxcolors)
3854
39- After ` from pypnm import pnmlpnm`, use something like:
55+ for writing data from ``list_3d`` nested list to ``pnm_bytes`` bytes object in memory,
4056
41- `X, Y, Z, maxcolors, list_3d = pnmlpnm.pnm2list(in_filename)`
57+ or
4258
43- for reading data from PPM/PGM, where :
59+ : :
4460
45- - `X`, `Y`, `Z`: image dimensions (int);
46- - `maxcolors`: maximum of color per channel for current image (int);
47- - `list_3d`: image pixel data as list(list(list(int)));
61+ pnmlpnm.list2pnm(out_filename, list_3d, maxcolors, bin)
4862
49- and:
63+ for writing data from ``list_3d`` nested list to PPM/PGM file ``out_filename``,
64+ where ``bin`` is a bool switch defining where resulting file will be binary or ASCII.
5065
51- `pnm_bytes = pnmlpnm.list2bin(list_3d, maxcolors)`
66+ Copyright and redistribution
67+ ----------------------------
5268
53- for writing data from `list_3d` nested list to `pnm_bytes` bytes object in memory,
69+ Written by Ilya Razmanov (https://dnyarri.github.io) to facilitate developing
70+ image editing programs in Python by simplifying work with PPM/PGM files
71+ and displaying arbitrary image-like data with Tkinter ``PhotoImage`` class.
5472
55- or:
73+ May be freely used, redistributed and modified.
5674
57- `pnmlpnm.list2pnm(out_filename, list_3d, maxcolors, bin)`
75+ In case of introducing useful modifications, please report to the developer.
5876
59- for writing data from `list_3d` nested list to PPM/PGM file `out_filename`,
60- where `bin` is a bool switch defining where resulting file will be binary or ASCII.
77+ References
78+ ----------
6179
62- Copyright and redistribution
63- -----------------------------
80+ 1. `Netpbm specifications`_
81+ 2. `PyPNM for Python >= 3.11`_ at GitHub
82+ 3. `PyPNM for Python >= 3.4`_ at GitHub
83+ 4. `PyPNM at PyPI`_
84+ 5. `PyPNM Documentation`_
6485
65- Written by `Ilya Razmanov<https://dnyarri.github.io/>`_ aka Ilyich the Toad
66- to facilitate working with PPM/PGM files and displaying arbitrary image-like data
67- with Tkinter `PhotoImage` class.
86+ .. _Netpbm specifications: https://netpbm.sourceforge.net/doc/
6887
69- May be freely used, redistributed and modified.
88+ .. _PPM: https://netpbm.sourceforge.net/doc/ppm.html
7089
71- In case of introducing useful modifications, report upstairs at once.
90+ .. _PGM: https://netpbm.sourceforge.net/doc/pgm.html
7291
73- References
74- -----------
92+ .. _PyPNM for Python >= 3.11: https://github.com/Dnyarri/PyPNM/
93+
94+ .. _PyPNM for Python >= 3.4: https://github.com/Dnyarri/PyPNM/tree/py34
95+
96+ .. _PyPNM at PyPI: https://pypi.org/project/PyPNM/
7597
76- 1. Netpbm specifications: https://netpbm.sourceforge.net/doc/
77- 2. PyPNM for Python >= 3.11 at GitHub: https://github.com/Dnyarri/PyPNM/
78- 3. PyPNM for Python >= 3.4 at GitHub: https://github.com/Dnyarri/PyPNM/tree/py34
79- 4. PyPNM at PyPI: https://pypi.org/project/PyPNM/
80- 5. PyPNM Documentation: https://dnyarri.github.io/pypnm/pypnm.pdf
98+ .. _PyPNM Documentation: https://dnyarri.github.io/pypnm/pypnm.pdf
8199
82100"""
83101
84102__author__ = 'Ilya Razmanov'
85103__copyright__ = '(c) 2024-2025 Ilya Razmanov'
86104__credits__ = 'Ilya Razmanov'
87105__license__ = 'unlicense'
88- __version__ = '2.21.3.12 '
106+ __version__ = '2.23.13.13 '
89107__maintainer__ = 'Ilya Razmanov'
90108__email__ = 'ilyarazmanov@gmail.com'
91109__status__ = 'Production'
104122def pnm2list (in_filename : str ) -> tuple [int , int , int , int , list [list [list [int ]]]]:
105123 """Read PGM or PPM file to nested image data list.
106124
107- Usage:
125+ Usage
108126
109- `X, Y, Z, maxcolors, list_3d = pnmlpnm.pnm2list(in_filename)`
127+ ::
128+
129+ X, Y, Z, maxcolors, list_3d = pnmlpnm.pnm2list(in_filename)
110130
111131 for reading data from PPM/PGM, where:
112132
113- - `X`, `Y`, `Z`: image dimensions (int);
114- - `maxcolors`: maximum of color per channel for current image (int),
115- 255 for 8 bit and 65535 for 16 bit input. Note that 1 bit images get promoted to 8 bit L upon import.
116- - `list_3d`: image pixel data as list(list(list(int)));
117- - `in_filename`: PPM/PGM file name (str).
133+ :X, Y, Z: image dimensions (int);
134+ :maxcolors: maximum of color per channel for current image (int),
135+ 255 for 8 bit and 65535 for 16 bit input.
136+ Note that 1 bit images get promoted to 8 bit L upon import.
137+ :list_3d: image pixel data as list(list(list(int)));
138+ :in_filename: PPM/PGM file name (str).
118139
119140 """
120141
@@ -347,18 +368,22 @@ def _p1(in_filename: str) -> tuple[int, int, int, int, list[list[list[int]]]]:
347368def list2bin (list_3d : list [list [list [int ]]], maxcolors : int , show_chessboard : bool = False ) -> bytes :
348369 """Convert nested image data list to PGM P5 or PPM P6 bytes in memory.
349370
350- Usage:
371+ Usage
372+
373+ ::
351374
352- ` image_bytes = pnmlpnm.list2bin(list_3d, maxcolors, show_chessboard)`
375+ image_bytes = pnmlpnm.list2bin(list_3d, maxcolors, show_chessboard)
353376
354377 where:
355378
356- - `list_3d`: Y * X * Z list (image) of lists (rows) of lists (pixels) of ints (channel values);
357- - `maxcolors`: maximum of color per channel for current image (int);
358- - `show_chessboard`: optional bool, set `True` to show LA and RGBA images against chessboard pattern;
359- `False` or missing show existing L or RGB data for transparent areas as fully opaque.
360- Default is `False` for backward compatibility.
361- - `image_bytes`: PNM-structured binary data.
379+ :list_3d: Y * X * Z list (image) of lists (rows) of lists (pixels) of ints (channel values);
380+ :maxcolors: maximum of color per channel for current image (int);
381+ :show_chessboard: optional bool, set ``True`` to show LA and RGBA images against chessboard pattern;
382+ ``False`` or missing show existing L or RGB data for transparent areas as fully opaque.
383+ Default is ``False`` for backward compatibility.
384+ :image_bytes: PNM-structured binary data.
385+
386+ **Warning**: Feeds PNM bytes to Tkinter "as is", which makes old Tkinter versions crash.
362387
363388 """
364389
@@ -367,7 +392,7 @@ def _chess(x: int, y: int) -> int:
367392
368393 Photoshop chess pattern preset parameters:
369394 - Small: 4 px; Medium: 8 px, Large: 16 px
370- - Light: (0.8, 1.0); Medium: (0.4, 0.6); Dark: (0.2, 0.4) of maxcolors
395+ - Light: (0.8, 1.0); Medium: (0.4, 0.6); Dark: (0.2, 0.4) of `` maxcolors``
371396
372397 """
373398 return int (maxcolors * 0.8 ) if ((y // 8 ) % 2 ) == ((x // 8 ) % 2 ) else maxcolors
@@ -408,17 +433,19 @@ def _chess(x: int, y: int) -> int:
408433 ╚═════════════╝ """
409434
410435def list2pnmbin (out_filename : str , list_3d : list [list [list [int ]]], maxcolors : int ) -> None :
411- """Write binary PNM `out_filename` file; writing performed per row to reduce RAM usage.
436+ """Write binary PNM ``out_filename`` file; writing performed per row to reduce RAM usage.
437+
438+ Usage
412439
413- Usage :
440+ : :
414441
415- ` pnmlpnm.list2pnmbin(out_filename, list_3d, maxcolors)`
442+ pnmlpnm.list2pnmbin(out_filename, list_3d, maxcolors)
416443
417444 where:
418445
419- - ` list_3d`: X * Y * Z list (image) of lists (rows) of lists (pixels) of ints (channels);
420- - ` maxcolors`: maximum of color per channel for current image (int);
421- - ` out_filename`: PNM file name.
446+ : list_3d: X * Y * Z list (image) of lists (rows) of lists (pixels) of ints (channels);
447+ : maxcolors: maximum of color per channel for current image (int);
448+ : out_filename: PNM file name.
422449
423450 """
424451
@@ -450,17 +477,19 @@ def list2pnmbin(out_filename: str, list_3d: list[list[list[int]]], maxcolors: in
450477 ╚═══════════════╝ """
451478
452479def list2pnmascii (out_filename : str , list_3d : list [list [list [int ]]], maxcolors : int ) -> None :
453- """Write ASCII PNM `out_filename` file; writing performed per sample to reduce RAM usage.
480+ """Write ASCII PNM `` out_filename` ` file; writing performed per sample to reduce RAM usage.
454481
455- Usage:
482+ Usage
456483
457- `pnmlpnm.list2pnmascii(out_filename, list_3d, maxcolors)`
484+ ::
485+
486+ pnmlpnm.list2pnmascii(out_filename, list_3d, maxcolors)
458487
459488 where:
460489
461- - ` list_3d`: Y * X * Z list (image) of lists (rows) of lists (pixels) of ints (channels);
462- - ` maxcolors`: maximum of color per channel for current image (int);
463- - ` out_filename`: PNM file name.
490+ : list_3d: Y * X * Z list (image) of lists (rows) of lists (pixels) of ints (channels);
491+ : maxcolors: maximum of color per channel for current image (int);
492+ : out_filename: PNM file name.
464493
465494 """
466495
@@ -496,18 +525,20 @@ def list2pnmascii(out_filename: str, list_3d: list[list[list[int]]], maxcolors:
496525 ╚══════════╝ """
497526
498527def list2pnm (out_filename : str , list_3d : list [list [list [int ]]], maxcolors : int , bin : bool = True ) -> None :
499- """Write PNM `out_filename` file using either `list2pnmbin` or `list2pnmascii` depending on `bin` switch.
528+ """Write PNM ``out_filename`` file using either ``list2pnmbin`` or ``list2pnmascii`` depending on ``bin`` switch.
529+
530+ Usage
500531
501- Usage :
532+ : :
502533
503- ` pnmlpnm.list2pnm(out_filename, list_3d, maxcolors, bin)`
534+ pnmlpnm.list2pnm(out_filename, list_3d, maxcolors, bin)
504535
505536 where:
506537
507- - ` list_3d`: X * Y * Z list (image) of lists (rows) of lists (pixels) of ints (channels);
508- - ` maxcolors`: maximum of color per channel for current image (int);
509- - ` bin`: whether output file is binary (bool);
510- - ` out_filename`: PNM file name.
538+ : list_3d: X * Y * Z list (image) of lists (rows) of lists (pixels) of ints (channels);
539+ : maxcolors: maximum of color per channel for current image (int);
540+ : bin: whether output file is binary (bool);
541+ : out_filename: PNM file name.
511542
512543 """
513544
0 commit comments