Made a proper python package out of this.

This commit is contained in:
jaseg 2013-07-29 18:51:18 +02:00
parent 62e62f1eac
commit a79ab96953
11 changed files with 176 additions and 173 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
build
dist
pixelterm.egg-info
__pycache__

55
gifterm Executable file
View file

@ -0,0 +1,55 @@
#!/usr/bin/env python
import os, sys, argparse, os.path, json, time, signal, atexit, pixelterm
#NOTE: This script uses pygments for RGB->X256 conversion since pygments is
#readily available. If you do not like pygments (e.g. because it is large),
#you could patch in something like https://github.com/magarcia/python-x256
#(but don't forget to send me a pull request ;)
from pygments.formatters import terminal256
from PIL import Image, GifImagePlugin, ImageSequence
clear_screen = '\033[H\033[2J'
cursor_invisible = '\033[?25l'
cursor_visible = '\033[?25h'
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Render pixel images on 256-color ANSI terminals')
parser.add_argument('image', type=str)
parser.add_argument('-s', '--size', type=str, help='Terminal size, [W]x[H]')
args = parser.parse_args()
tw, th = os.get_terminal_size()
th = th*2
if args.size:
tw, th = map(int, args.size.split('x'))
img = Image.open(args.image)
palette = img.getpalette()
last_frame = Image.new("RGBA", img.size)
frames = []
for frame in ImageSequence.Iterator(img):
#This works around a known bug in Pillow
#See also: http://stackoverflow.com/questions/4904940/python-converting-gif-frames-to-png
frame.putpalette(palette)
c = frame.convert("RGBA")
if img.info['background'] != img.info['transparency']:
last_frame.paste(c, c)
else:
last_frame = c
im = last_frame.copy()
im.thumbnail((tw, th), Image.NEAREST)
frames.append(pixelterm.termify_pixels(im))
print(cursor_invisible)
atexit.register(lambda:print(cursor_visible))
signal.signal(signal.SIGTERM, lambda signum, stack_frame: exit(1))
while True:
for frame in frames:
print(clear_screen, pixelterm.reset_sequence)
print(frame)
time.sleep(img.info['duration']/1000.0)

View file

@ -1,123 +0,0 @@
#!/usr/bin/env python
import os, sys, argparse, os.path, json, time, signal, atexit
#NOTE: This script uses pygments for RGB->X256 conversion since pygments is
#readily available. If you do not like pygments (e.g. because it is large),
#you could patch in something like https://github.com/magarcia/python-x256
#(but don't forget to send me a pull request ;)
from pygments.formatters import terminal256
from PIL import Image, GifImagePlugin, ImageSequence
clear_screen = '\033[H\033[2J'
cursor_invisible = '\033[?25l'
cursor_visible = '\033[?25h'
formatter = terminal256.Terminal256Formatter()
reset_sequence = terminal256.EscapeSequence(fg=formatter._closest_color(0,0,0), bg=formatter._closest_color(0,0,0)).reset_string()
def termify_pixels(img):
sx, sy = img.size
out = ''
fg,bg = None,None
fgd,bgd = {},{}
def bgescape(color):
nonlocal bg, bgd
if bg == color:
return ''
bg=color
if color == (0,0,0,0):
return '\033[49m'
if color in bgd:
return bgd[color]
r,g,b,_ = color
bgd[color] = '\033[48;5;'+str(formatter._closest_color(r,g,b))+'m'
return bgd[color]
def fgescape(color):
nonlocal fg, fgd
if fg == color:
return ''
fg=color
r,g,b,_ = color
fgd[color] = '\033[38;5;'+str(formatter._closest_color(r,g,b))+'m'
return fgd[color]
def balloon(x,y):
if x+1 == img.size[0] or img.im.getpixel((x+1, y)) != (0,255,0,127):
w = 1
while x-w >= 0 and img.im.getpixel((x-w, y)) == (0,255,0,127):
w += 1
return '$balloon{}$'.format(w)
return ''
for y in range(0, sy, 2):
for x in range(sx):
coltop = img.im.getpixel((x, y))
colbot = img.im.getpixel((x, y+1)) if y+1 < img.size[1] else (0,0,0,0)
if coltop[3] == 127: #Control colors
out += reset_sequence
out += {(255, 0, 0, 127): lambda x,y:'$\\$',
(0, 0, 255, 127): lambda x,y:'$/$',
(0, 255, 0, 127): balloon
}.get(coltop, lambda x,y:' ')(x,y)
continue
if coltop[3] != 255:
coltop = (0,0,0,0)
if colbot[3] != 255:
colbot = (0,0,0,0)
#Da magicks: ▀█▄
c,cf = '',''
te,be = fgescape,bgescape
if coltop == (0,0,0,0) or ((coltop == bg or colbot == fg) and not colbot == (0,0,0,0)):
c,cf,te,be = '',' ',be,te
if colbot == coltop:
c,te,be = cf,te,te
out += te(coltop) + be(colbot) + c
out = (out.rstrip() if bg == (0,0,0,0) else out) + '\n'
return out[:-1] + reset_sequence + '\n'
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Render pixel images on 256-color ANSI terminals')
parser.add_argument('image', type=str)
parser.add_argument('-s', '--size', type=str, help='Terminal size, [W]x[H]')
args = parser.parse_args()
tw, th = os.get_terminal_size()
th = th*2
if args.size:
tw, th = map(int, args.size.split('x'))
img = Image.open(args.image)
palette = img.getpalette()
last_frame = Image.new("RGBA", img.size)
frames = []
for frame in ImageSequence.Iterator(img):
#This works around a known bug in Pillow
#See also: http://stackoverflow.com/questions/4904940/python-converting-gif-frames-to-png
frame.putpalette(palette)
c = frame.convert("RGBA")
if img.info['background'] != img.info['transparency']:
last_frame.paste(c, c)
else:
last_frame = c
im = last_frame.copy()
im.thumbnail((tw, th), Image.NEAREST)
frames.append(termify_pixels(im))
print(cursor_invisible)
atexit.register(lambda:print(cursor_visible))
signal.signal(signal.SIGTERM, lambda signum, stack_frame: exit(1))
while True:
for frame in frames:
print(clear_screen, reset_sequence)
print(frame)
time.sleep(img.info['duration']/1000.0)

28
pixelterm Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env python
import os, sys, argparse, os.path, json, pixelterm
from PIL import Image, PngImagePlugin
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Render pixel images on 256-color ANSI terminals')
parser.add_argument('image', type=str, nargs='*')
parser.add_argument('-d', '--output-dir', type=str, help='Output directory (if not given, output to stdout)')
args = parser.parse_args()
for f in args.image:
img = Image.open(f).convert("RGBA")
if args.output_dir:
print(f)
foo, _, _ = f.rpartition('.png')
output = os.path.join(args.output_dir, os.path.basename(foo)+'.pony')
metadata = json.loads(img.info.get('pixelterm-metadata'))
comment = metadata['_comment']
del metadata['_comment']
metadataarea = '$$$\n' +\
'\n'.join([ '\n'.join([ k.upper() + ': ' + v for v in metadata[k] ]) for k in sorted(metadata.keys()) ]) +\
'\n' + comment +\
'\n$$$\n'
with open(output, 'w') as of:
of.write(metadataarea)
of.write(pixelterm.termify_pixels(img))
else:
print(pixelterm.termify_pixels(img))

View file

@ -1,12 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
import os, sys, argparse, os.path, json
#NOTE: This script uses pygments for RGB->X256 conversion since pygments is #NOTE: This script uses pygments for RGB->X256 conversion since pygments is
#readily available. If you do not like pygments (e.g. because it is large), #readily available. If you do not like pygments (e.g. because it is large),
#you could patch in something like https://github.com/magarcia/python-x256 #you could patch in something like https://github.com/magarcia/python-x256
#(but don't forget to send me a pull request ;) #(but don't forget to send me a pull request ;)
from pygments.formatters import terminal256 from pygments.formatters import terminal256
from PIL import Image, PngImagePlugin
formatter = terminal256.Terminal256Formatter() formatter = terminal256.Terminal256Formatter()
reset_sequence = terminal256.EscapeSequence(fg=formatter._closest_color(0,0,0), bg=formatter._closest_color(0,0,0)).reset_string() reset_sequence = terminal256.EscapeSequence(fg=formatter._closest_color(0,0,0), bg=formatter._closest_color(0,0,0)).reset_string()
@ -76,26 +74,3 @@ def termify_pixels(img):
out = (out.rstrip() if bg == (0,0,0,0) else out) + '\n' out = (out.rstrip() if bg == (0,0,0,0) else out) + '\n'
return out[:-1] + reset_sequence + '\n' return out[:-1] + reset_sequence + '\n'
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Render pixel images on 256-color ANSI terminals')
parser.add_argument('image', type=str, nargs='*')
parser.add_argument('-d', '--output-dir', type=str, help='Output directory (if not given, output to stdout)')
args = parser.parse_args()
for f in args.image:
img = Image.open(f).convert("RGBA")
if args.output_dir:
print(f)
foo, _, _ = f.rpartition('.png')
output = os.path.join(args.output_dir, os.path.basename(foo)+'.pony')
metadata = json.loads(img.info.get('pixelterm-metadata'))
comment = metadata['_comment']
del metadata['_comment']
metadataarea = '$$$\n' +\
'\n'.join([ '\n'.join([ k.upper() + ': ' + v for v in metadata[k] ]) for k in sorted(metadata.keys()) ]) +\
'\n' + comment +\
'\n$$$\n'
with open(output, 'w') as of:
of.write(metadataarea)
of.write(termify_pixels(img))
else:
print(termify_pixels(img))

View file

50
setup.py Executable file
View file

@ -0,0 +1,50 @@
#!/usr/bin/env python3
from setuptools import setup
import os, os.path
import sys
ver = "1.0"
def read(filename):
return open(os.path.join(os.path.dirname(__file__), filename)).read()
if sys.version_info < (3,0):
print('Oops, only python >= 3.0 supported!')
sys.exit()
setup(name = 'pixelterm',
version = ver,
description = 'Render pixely images on your terminal. Now also with animated GIF support.',
license = 'BSD',
author = 'jaseg',
author_email = 'pixelterm@jaseg.net',
url = 'https://github.com/jaseg/pixelterm',
py_modules = ['pixelterm', 'unpixelterm'],
scripts = ['pixelterm',
'unpixelterm',
'colorcube',
'gifterm',
'resolvecolor',
'pngmeta'],
zip_safe = True,
classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Information Technology',
'Intended Audience :: Intended Audience :: End Users/Desktop',
'License :: Freely Distributable',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 3',
'Topic :: Internet',
'Topic :: Graphics',
'Topic :: System :: Networking'
'Topic :: Text Processing :: Filters',
'Topic :: Utilities',
],
long_description = read('README.md'),
dependency_links = [],
)

38
unpixelterm Executable file
View file

@ -0,0 +1,38 @@
#!/usr/bin/env python
import os, sys, argparse, os.path, json, unpixelterm
#NOTE: This script uses pygments for X256->RGB conversion since pygments is
#readily available. If you do not like pygments (e.g. because it is large),
#you could patch in something like https://github.com/magarcia/python-x256
#(but don't forget to send me a pull request ;)
from pygments.formatters import terminal256
from PIL import Image, PngImagePlugin
try:
import re2 as re
except:
import re
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Convert images rendered by pixelterm-like utilities back to PNG')
parser.add_argument('-v', '--verbose', action='store_true')
output_group = parser.add_mutually_exclusive_group()
output_group.add_argument('-o', '--output', type=str, help='Output file name, defaults to ${input%.pony}.png')
output_group.add_argument('-d', '--output-dir', type=str, help='Place output files here')
parser.add_argument('input', type=argparse.FileType('r'), nargs='+')
args = parser.parse_args()
if len(args.input) > 1 and args.output:
parser.print_help()
print('You probably do not want to overwrite the given output file {} times.'.format(len(args.input)))
sys.exit(1)
for f in args.input:
if len(args.input) > 1:
print(f.name)
img, metadata = unpixelterm.unpixelterm(f.read())
pnginfo = PngImagePlugin.PngInfo()
pnginfo.add_text('pixelterm-metadata', json.dumps(metadata))
foo, _, _ = f.name.rpartition('.pony')
output = args.output or foo+'.png'
if args.output_dir:
output = os.path.join(args.output_dir, os.path.basename(output))
img.save(output, 'PNG', pnginfo=pnginfo)

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
import os, sys, argparse, os.path, json import os, sys, os.path
from collections import defaultdict from collections import defaultdict
#NOTE: This script uses pygments for X256->RGB conversion since pygments is #NOTE: This script uses pygments for X256->RGB conversion since pygments is
#readily available. If you do not like pygments (e.g. because it is large), #readily available. If you do not like pygments (e.g. because it is large),
@ -99,27 +99,3 @@ def unpixelterm(text):
x, y = 0, y+2 x, y = 0, y+2
return img, metadata return img, metadata
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Convert images rendered by pixelterm-like utilities back to PNG')
parser.add_argument('-v', '--verbose', action='store_true')
output_group = parser.add_mutually_exclusive_group()
output_group.add_argument('-o', '--output', type=str, help='Output file name, defaults to ${input%.pony}.png')
output_group.add_argument('-d', '--output-dir', type=str, help='Place output files here')
parser.add_argument('input', type=argparse.FileType('r'), nargs='+')
args = parser.parse_args()
if len(args.input) > 1 and args.output:
parser.print_help()
print('You probably do not want to overwrite the given output file {} times.'.format(len(args.input)))
sys.exit(1)
for f in args.input:
if len(args.input) > 1:
print(f.name)
img, metadata = unpixelterm(f.read())
pnginfo = PngImagePlugin.PngInfo()
pnginfo.add_text('pixelterm-metadata', json.dumps(metadata))
foo, _, _ = f.name.rpartition('.pony')
output = args.output or foo+'.png'
if args.output_dir:
output = os.path.join(args.output_dir, os.path.basename(output))
img.save(output, 'PNG', pnginfo=pnginfo)