Skip to content

Commit cb27474

Browse files
committed
added setup.py/restructured directories to reflect.
1 parent 3d6db8a commit cb27474

File tree

10 files changed

+310
-5
lines changed

10 files changed

+310
-5
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
*swp
22
*pyc
33
test_imgs
4+
build
5+
dist
6+
*egg-info
7+
.pypirc

README.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,26 @@
22

33
Makin some pictures
44

5-
This library requires the Pillow and colorama libraries
5+
Ascii py requires the use of Python 3.3 or greater because of [an addition made to the shutil ibrary](https://docs.python.org/3/library/shutil.html#querying-the-size-of-the-output-terminal).
6+
7+
Install instructions
8+
---
9+
10+
Using pip:
11+
12+
`python3 -m pip install ascii_py`
13+
14+
Manually:
15+
16+
```
17+
git clone https://github.com/profoak/ascii_py
18+
cd ascii_py
19+
python3 setup.py install
20+
```
21+
22+
If you want to use the gui component: `python3 setup_gui.py install`
23+
24+
This library requires the Pillow and colorama libraries. If you use the above install methods, these will automagically be installed.
625

726
`python3 -m pip install -U Pillow colorama`
827

@@ -15,7 +34,7 @@ At the time of this commit PySide can only be installed on Python versions 2.6,
1534
---
1635

1736
```
18-
Usage: main.py [options]
37+
Usage: ascii_py [options]
1938
2039
Options:
2140
@@ -52,7 +71,7 @@ Terminal flag (screenshot):
5271
Other flags usage example:
5372
---
5473

55-
`$ python main.py -s 10 -w "dank memes" -o ayy_lmao_pizza.jpg Media/pizza_in.jpg`
74+
`$ python ascii_py -s 10 -w "dank memes" -o ayy_lmao_pizza.jpg Media/pizza_in.jpg`
5675

5776
![](https://raw.githubusercontent.com/ProfOak/ascii_py/master/Media/pizza_in.jpg)
5877

ascii_py/__init__.py

Whitespace-only changes.
File renamed without changes.

main.py renamed to ascii_py/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python3
2-
from ascii import Ascii
2+
from .ascii import Ascii
33
from optparse import OptionParser
44

55
def main():

ascii_py_gui/__init__.py

Whitespace-only changes.

ascii_py_gui/ascii.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
import colorama
2+
import shutil
3+
import os
4+
from PIL import Image
5+
from PIL import ImageDraw
6+
7+
class Ascii():
8+
def __init__(self, in_file):
9+
""" Python ascii image maker """
10+
11+
self.letter_densities = '" .`-_\':,;^=+/"|)\\<>)iv%xclrs{*}I?!][1taeo7zjLunT#JCwfy325Fp6mqSghVd4EgXPGZbYkOA&8U$@KHDBWNMR0Q'
12+
13+
self.from_pic = Image.open(in_file)
14+
self.to_pic = Image.new("RGB", self.from_pic.size, "black")
15+
self.draw = ImageDraw.Draw(self.to_pic)
16+
17+
self.MAX_W, self.MAX_H = self.from_pic.size
18+
19+
def word_artify(self, words="#", step=3):
20+
""" create ascii image from word string """
21+
22+
words = words.upper()
23+
24+
h = w = i = 0
25+
26+
# skip pixels by `step` amount and place characters around image
27+
while h < self.MAX_H:
28+
while w < self.MAX_W:
29+
# use a string as the art characters
30+
c = words[i]
31+
32+
# loop around
33+
i = (i+1) % len(words)
34+
35+
# get the color from the pixel
36+
p = self.from_pic.getpixel((w, h))
37+
38+
# insert text based on pixel color
39+
self.draw.text((w, h), c, p)
40+
41+
w += step
42+
h += step
43+
w = 0
44+
45+
self.from_pic.close()
46+
47+
48+
def density_artify(self, step=7):
49+
"""
50+
Generates the acsii image where the 'words' are selected based on
51+
the brightness of a pixel.
52+
53+
A brighter pixel will have a character with lower visual density and
54+
a less bright pixel will have a character with high visual density.
55+
"""
56+
57+
if step < 7:
58+
step = 7
59+
60+
h = 0
61+
w = 0
62+
63+
# used for brightness (density) levels
64+
grayscale_img = self.from_pic.convert("L")
65+
66+
while h < self.MAX_H:
67+
while w < self.MAX_W:
68+
# get brightness value
69+
brightness = 255 - grayscale_img.getpixel((w, h))
70+
clr = self.from_pic.getpixel((w, h))
71+
72+
# select required character from the letter_densities list
73+
char_pos = (brightness/255.0) * (len(self.letter_densities) - 1)
74+
c = self.letter_densities[int(round(char_pos, 0))]
75+
self.draw.text((w, h), c, clr)
76+
77+
w += step
78+
h += step
79+
w = 0
80+
81+
self.from_pic.close()
82+
grayscale_img.close()
83+
84+
85+
def terminal_artify(self):
86+
""" covert image to ascii, display in terminal """
87+
88+
# all colors are beautiful
89+
acab = [
90+
[( 0, 0, 0), colorama.Fore.LIGHTBLACK_EX],
91+
[( 0, 0, 255), colorama.Fore.BLUE],
92+
[( 0, 255, 0), colorama.Fore.GREEN],
93+
[(255, 0, 0), colorama.Fore.RED],
94+
[(255, 255, 255), colorama.Fore.WHITE],
95+
[(255, 0, 255), colorama.Fore.MAGENTA],
96+
[( 0, 255, 255), colorama.Fore.CYAN],
97+
[(255, 255, 0), colorama.Fore.YELLOW]
98+
]
99+
100+
# convert to floats, linearize
101+
# in case more colors are added
102+
acab = [ [[(v/255.0)**2.2 for v in x[0]], x[1]] for x in acab ]
103+
104+
# needed for Windows operating systems
105+
colorama.init()
106+
107+
canvas = self.from_pic
108+
current_h, current_w = float(self.MAX_H), float(self.MAX_W)
109+
110+
# resize to fit current dimensions of terminal
111+
# shutil added get_terminal_size starting in python 3.3
112+
t_width, t_height = shutil.get_terminal_size()
113+
114+
if current_h > t_height or current_w > t_width:
115+
# floating point division
116+
scalar = max(current_h/t_height, (current_w*2)/t_width)
117+
current_w = int((current_w*2)/scalar)
118+
current_h = int((current_h)/scalar)
119+
dimensions = current_w, current_h
120+
canvas = self.from_pic.resize(dimensions)
121+
122+
# used for brightness (density) levels
123+
grayscale_img = canvas.convert("L")
124+
125+
image = ""
126+
127+
for h in range(current_h):
128+
for w in range(current_w):
129+
# get brightness value
130+
brightness = grayscale_img.getpixel((w, h))/255.0
131+
pixel = canvas.getpixel((w, h))
132+
# getpixel() may return an int, instead of tuple of ints, if the
133+
# source img is a PNG with a transparency layer.
134+
if isinstance(pixel, int):
135+
pixel = (pixel, pixel, 255)
136+
137+
srgb = [ (v/255.0)**2.2 for v in pixel ]
138+
139+
# select required character from the letter_densities list
140+
char_pos = brightness * (len(self.letter_densities) - 1)
141+
142+
color = self._convert_color(srgb, brightness, acab)
143+
image += color + self.letter_densities[int(round(char_pos, 0))]
144+
image += "\n"
145+
146+
# prints the converted image to terminal
147+
# (remove the last newline)
148+
print(image[:-1] + colorama.Fore.RESET)
149+
150+
self.from_pic.close()
151+
grayscale_img.close()
152+
153+
input("Press enter to continue...")
154+
155+
156+
#######################################
157+
# Helper Methods #
158+
#######################################
159+
160+
def _L2_min(self, v1, v2):
161+
"""
162+
euclidian norm in a 2 dimensional space
163+
used for calculating shortest distance
164+
"""
165+
166+
return (v1[0]-v2[0])**2 + (v1[1]-v2[1])**2 + (v1[2]-v2[2])**2
167+
168+
def _convert_color(self, rgb, brightness, acab):
169+
""" convert color using acab data """
170+
171+
min_distance = 2
172+
index = 0
173+
174+
for i in range(len(acab)):
175+
tmp = [ v*brightness for v in acab[i][0] ]
176+
distance = self._L2_min(tmp, rgb)
177+
178+
if distance < min_distance:
179+
index = i
180+
min_distance = distance
181+
182+
return acab[index][1]
183+
184+
def save(self, out_file="out.jpg"):
185+
""" save image to file """
186+
187+
self.to_pic.save(out_file)
188+
self.to_pic.close()
189+

main-gui.py renamed to ascii_py_gui/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
from PySide.QtCore import *
44
from PySide.QtGui import *
5-
from ascii import Ascii
5+
from .ascii import Ascii
66

77
class Ascii_gui(QWidget):
88
def __init__(self):

setup.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python3
2+
3+
from setuptools import setup, find_packages
4+
5+
setup(
6+
name = 'ascii_py',
7+
version = '1.2',
8+
description = 'Make ascii art',
9+
10+
author = 'ProfOak',
11+
author_email = 'OpenProfOak@gmail.com',
12+
url = 'https://www.github.com/ProfOak/Ascii_py/',
13+
license = 'MIT',
14+
15+
classifiers = [
16+
'Development Status :: 5 - Production/Stable',
17+
18+
'Intended Audience :: End Users/Desktop',
19+
20+
'License :: OSI Approved :: MIT License',
21+
22+
'Operating System :: OS Independent',
23+
'Topic :: Games/Entertainment',
24+
'Topic :: Multimedia :: Graphics',
25+
'Topic :: Multimedia :: Graphics :: Editors',
26+
27+
# This is because shutil.get_terminal_size() was added in 3.3
28+
'Programming Language :: Python :: 3.3',
29+
'Programming Language :: Python :: 3.4',
30+
'Programming Language :: Python :: 3.5',
31+
],
32+
33+
keywords = 'ascii art image fun memes',
34+
35+
install_requires = [
36+
'colorama',
37+
'Pillow',
38+
],
39+
packages = find_packages(exclude=['Media','ascii_py_gui']),
40+
41+
entry_points = {
42+
'console_scripts': [
43+
'ascii_py = ascii_py.main:main'
44+
]
45+
},
46+
)

setup_gui.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
3+
from setuptools import setup, find_packages
4+
5+
setup(
6+
name = 'ascii_py_gui',
7+
version = '1.2',
8+
description = 'Make ascii art',
9+
10+
author = 'ProfOak',
11+
author_email = 'OpenProfOak@gmail.com',
12+
url = 'https://www.github.com/ProfOak/Ascii_py/',
13+
license = 'MIT',
14+
15+
classifiers = [
16+
'Development Status :: 5 - Production/Stable',
17+
18+
'Intended Audience :: End Users/Desktop',
19+
20+
'License :: OSI Approved :: MIT License',
21+
22+
'Operating System :: OS Independent',
23+
'Topic :: Games/Entertainment',
24+
'Topic :: Multimedia :: Graphics',
25+
'Topic :: Multimedia :: Graphics :: Editors',
26+
27+
# This is because shutil.get_terminal_size() was added in 3.3
28+
# the pypi version of PySide is not compatible with Python 3.5
29+
'Programming Language :: Python :: 3.3',
30+
'Programming Language :: Python :: 3.4',
31+
],
32+
33+
keywords = 'ascii art image fun memes',
34+
35+
install_requires = [
36+
'colorama',
37+
'Pillow',
38+
'PySide',
39+
],
40+
packages = find_packages(exclude=['Media','ascii_py']),
41+
42+
entry_points = {
43+
'console_scripts': [
44+
'ascii_py_gui = ascii_py_gui.main:main'
45+
]
46+
},
47+
)

0 commit comments

Comments
 (0)