File: pripngtopam

package info (click to toggle)
pypng 0.0.19%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 568 kB
  • sloc: python: 4,371; sh: 126; makefile: 5
file content (119 lines) | stat: -rwxr-xr-x 2,862 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python

from __future__ import print_function

import argparse
import struct
import sys

import png

def write_pnm(file, rows, meta):
    """Write a Netpbm PNM/PAM file.
    """

    meta = dict(meta)
    meta['maxval'] = 2**meta['bitdepth'] - 1
    meta['width'], meta['height'] = meta['size']

    # Number of planes determines both image formats:
    # 1 : L to PGM
    # 2 : LA to PAM
    # 3 : RGB to PPM
    # 4 : RGBA to PAM
    planes = meta['planes']

    # Assume inputs are from a PNG file.
    assert planes in (1, 2, 3, 4)
    if planes in (1, 3):
        if 1 == planes:
            # PGM
            # Even if maxval is 1 we use PGM instead of PBM,
            # to avoid conerting data.
            magic = 'P5'
        else:
            # PPM
            magic = 'P6'
        header = "{magic} {width:d} {height:d} {maxval:d}\n".format(
            magic=magic, **meta)
    if planes in (2, 4):
        # PAM
        # See http://netpbm.sourceforge.net/doc/pam.html
        if 2 == planes:
            tupltype = 'GRAYSCALE_ALPHA'
        else:
            tupltype = 'RGB_ALPHA'
        header = ('P7\nWIDTH {width:d}\nHEIGHT {height:d}\n'
                  'DEPTH {planes:d}\nMAXVAL {maxval:d}\n'
                  'TUPLTYPE {tupltype}\nENDHDR\n'.format(
                  tupltype=tupltype, **meta))
    file.write(header.encode('ascii'))
    # Values per row
    vpr = planes * meta['width']
    # format for struct.pack
    fmt = '>%d' % vpr
    if meta['maxval'] > 0xFF:
        fmt = fmt + 'H'
    else:
        fmt = fmt + 'B'
    for row in rows:
        file.write(struct.pack(fmt, *row))
    file.flush()


def cli_open(path):
    if path == "-":
        return binary_stdin()
    return open(path, 'rb')


def binary_stdin():
    """
    A sys.stdin that returns bytes.
    """

    try:
        return sys.stdin.buffer
    except AttributeError:
        # Probably Python 2, where bytes are strings.
        pass
    return sys.stdin


def binary_stdout():
    """
    A sys.stdout that accepts bytes.
    """

    # First there is a Python3 issue.
    try:
        stdout = sys.stdout.buffer
    except AttributeError:
        # Probably Python 2, where bytes are strings.
        stdout = sys.stdout

    # On Windows the C runtime file orientation needs changing.
    if sys.platform == "win32":
        import msvcrt
        import os
        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

    return stdout


def main(argv=None):
    parser = argparse.ArgumentParser(description='Convert PNG to PAM')
    parser.add_argument('png', nargs='?', default='-')

    args = parser.parse_args()

    inp = cli_open(args.png)

    # Encode PNG to PPM
    image = png.Reader(file=inp)
    _, _, rows, info = image.asDirect()
    write_pnm(binary_stdout(), rows, info)


if __name__ == '__main__':
    sys.exit(main())