Skip to content

Commit

Permalink
added setup.py/restructured directories to reflect.
Browse files Browse the repository at this point in the history
  • Loading branch information
ProfOak committed May 31, 2016
1 parent 3d6db8a commit cb27474
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -1,3 +1,7 @@
*swp
*pyc
test_imgs
build
dist
*egg-info
.pypirc
25 changes: 22 additions & 3 deletions README.md
Expand Up @@ -2,7 +2,26 @@

Makin some pictures

This library requires the Pillow and colorama libraries
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).

Install instructions
---

Using pip:

`python3 -m pip install ascii_py`

Manually:

```
git clone https://github.com/profoak/ascii_py
cd ascii_py
python3 setup.py install
```

If you want to use the gui component: `python3 setup_gui.py install`

This library requires the Pillow and colorama libraries. If you use the above install methods, these will automagically be installed.

`python3 -m pip install -U Pillow colorama`

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

```
Usage: main.py [options]
Usage: ascii_py [options]
Options:
Expand Down Expand Up @@ -52,7 +71,7 @@ Terminal flag (screenshot):
Other flags usage example:
---

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

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

Expand Down
Empty file added ascii_py/__init__.py
Empty file.
File renamed without changes.
2 changes: 1 addition & 1 deletion main.py → ascii_py/main.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
from ascii import Ascii
from .ascii import Ascii
from optparse import OptionParser

def main():
Expand Down
Empty file added ascii_py_gui/__init__.py
Empty file.
189 changes: 189 additions & 0 deletions ascii_py_gui/ascii.py
@@ -0,0 +1,189 @@
import colorama
import shutil
import os
from PIL import Image
from PIL import ImageDraw

class Ascii():
def __init__(self, in_file):
""" Python ascii image maker """

self.letter_densities = '" .`-_\':,;^=+/"|)\\<>)iv%xclrs{*}I?!][1taeo7zjLunT#JCwfy325Fp6mqSghVd4EgXPGZbYkOA&8U$@KHDBWNMR0Q'

self.from_pic = Image.open(in_file)
self.to_pic = Image.new("RGB", self.from_pic.size, "black")
self.draw = ImageDraw.Draw(self.to_pic)

self.MAX_W, self.MAX_H = self.from_pic.size

def word_artify(self, words="#", step=3):
""" create ascii image from word string """

words = words.upper()

h = w = i = 0

# skip pixels by `step` amount and place characters around image
while h < self.MAX_H:
while w < self.MAX_W:
# use a string as the art characters
c = words[i]

# loop around
i = (i+1) % len(words)

# get the color from the pixel
p = self.from_pic.getpixel((w, h))

# insert text based on pixel color
self.draw.text((w, h), c, p)

w += step
h += step
w = 0

self.from_pic.close()


def density_artify(self, step=7):
"""
Generates the acsii image where the 'words' are selected based on
the brightness of a pixel.
A brighter pixel will have a character with lower visual density and
a less bright pixel will have a character with high visual density.
"""

if step < 7:
step = 7

h = 0
w = 0

# used for brightness (density) levels
grayscale_img = self.from_pic.convert("L")

while h < self.MAX_H:
while w < self.MAX_W:
# get brightness value
brightness = 255 - grayscale_img.getpixel((w, h))
clr = self.from_pic.getpixel((w, h))

# select required character from the letter_densities list
char_pos = (brightness/255.0) * (len(self.letter_densities) - 1)
c = self.letter_densities[int(round(char_pos, 0))]
self.draw.text((w, h), c, clr)

w += step
h += step
w = 0

self.from_pic.close()
grayscale_img.close()


def terminal_artify(self):
""" covert image to ascii, display in terminal """

# all colors are beautiful
acab = [
[( 0, 0, 0), colorama.Fore.LIGHTBLACK_EX],
[( 0, 0, 255), colorama.Fore.BLUE],
[( 0, 255, 0), colorama.Fore.GREEN],
[(255, 0, 0), colorama.Fore.RED],
[(255, 255, 255), colorama.Fore.WHITE],
[(255, 0, 255), colorama.Fore.MAGENTA],
[( 0, 255, 255), colorama.Fore.CYAN],
[(255, 255, 0), colorama.Fore.YELLOW]
]

# convert to floats, linearize
# in case more colors are added
acab = [ [[(v/255.0)**2.2 for v in x[0]], x[1]] for x in acab ]

# needed for Windows operating systems
colorama.init()

canvas = self.from_pic
current_h, current_w = float(self.MAX_H), float(self.MAX_W)

# resize to fit current dimensions of terminal
# shutil added get_terminal_size starting in python 3.3
t_width, t_height = shutil.get_terminal_size()

if current_h > t_height or current_w > t_width:
# floating point division
scalar = max(current_h/t_height, (current_w*2)/t_width)
current_w = int((current_w*2)/scalar)
current_h = int((current_h)/scalar)
dimensions = current_w, current_h
canvas = self.from_pic.resize(dimensions)

# used for brightness (density) levels
grayscale_img = canvas.convert("L")

image = ""

for h in range(current_h):
for w in range(current_w):
# get brightness value
brightness = grayscale_img.getpixel((w, h))/255.0
pixel = canvas.getpixel((w, h))
# getpixel() may return an int, instead of tuple of ints, if the
# source img is a PNG with a transparency layer.
if isinstance(pixel, int):
pixel = (pixel, pixel, 255)

srgb = [ (v/255.0)**2.2 for v in pixel ]

# select required character from the letter_densities list
char_pos = brightness * (len(self.letter_densities) - 1)

color = self._convert_color(srgb, brightness, acab)
image += color + self.letter_densities[int(round(char_pos, 0))]
image += "\n"

# prints the converted image to terminal
# (remove the last newline)
print(image[:-1] + colorama.Fore.RESET)

self.from_pic.close()
grayscale_img.close()

input("Press enter to continue...")


#######################################
# Helper Methods #
#######################################

def _L2_min(self, v1, v2):
"""
euclidian norm in a 2 dimensional space
used for calculating shortest distance
"""

return (v1[0]-v2[0])**2 + (v1[1]-v2[1])**2 + (v1[2]-v2[2])**2

def _convert_color(self, rgb, brightness, acab):
""" convert color using acab data """

min_distance = 2
index = 0

for i in range(len(acab)):
tmp = [ v*brightness for v in acab[i][0] ]
distance = self._L2_min(tmp, rgb)

if distance < min_distance:
index = i
min_distance = distance

return acab[index][1]

def save(self, out_file="out.jpg"):
""" save image to file """

self.to_pic.save(out_file)
self.to_pic.close()

2 changes: 1 addition & 1 deletion main-gui.py → ascii_py_gui/main.py
Expand Up @@ -2,7 +2,7 @@
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from ascii import Ascii
from .ascii import Ascii

class Ascii_gui(QWidget):
def __init__(self):
Expand Down
46 changes: 46 additions & 0 deletions setup.py
@@ -0,0 +1,46 @@
#!/usr/bin/env python3

from setuptools import setup, find_packages

setup(
name = 'ascii_py',
version = '1.2',
description = 'Make ascii art',

author = 'ProfOak',
author_email = 'OpenProfOak@gmail.com',
url = 'https://www.github.com/ProfOak/Ascii_py/',
license = 'MIT',

classifiers = [
'Development Status :: 5 - Production/Stable',

'Intended Audience :: End Users/Desktop',

'License :: OSI Approved :: MIT License',

'Operating System :: OS Independent',
'Topic :: Games/Entertainment',
'Topic :: Multimedia :: Graphics',
'Topic :: Multimedia :: Graphics :: Editors',

# This is because shutil.get_terminal_size() was added in 3.3
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],

keywords = 'ascii art image fun memes',

install_requires = [
'colorama',
'Pillow',
],
packages = find_packages(exclude=['Media','ascii_py_gui']),

entry_points = {
'console_scripts': [
'ascii_py = ascii_py.main:main'
]
},
)
47 changes: 47 additions & 0 deletions setup_gui.py
@@ -0,0 +1,47 @@
#!/usr/bin/env python3

from setuptools import setup, find_packages

setup(
name = 'ascii_py_gui',
version = '1.2',
description = 'Make ascii art',

author = 'ProfOak',
author_email = 'OpenProfOak@gmail.com',
url = 'https://www.github.com/ProfOak/Ascii_py/',
license = 'MIT',

classifiers = [
'Development Status :: 5 - Production/Stable',

'Intended Audience :: End Users/Desktop',

'License :: OSI Approved :: MIT License',

'Operating System :: OS Independent',
'Topic :: Games/Entertainment',
'Topic :: Multimedia :: Graphics',
'Topic :: Multimedia :: Graphics :: Editors',

# This is because shutil.get_terminal_size() was added in 3.3
# the pypi version of PySide is not compatible with Python 3.5
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
],

keywords = 'ascii art image fun memes',

install_requires = [
'colorama',
'Pillow',
'PySide',
],
packages = find_packages(exclude=['Media','ascii_py']),

entry_points = {
'console_scripts': [
'ascii_py_gui = ascii_py_gui.main:main'
]
},
)

0 comments on commit cb27474

Please sign in to comment.