Skip to content

Commit

Permalink
Making pixelsort a package (#17)
Browse files Browse the repository at this point in the history
* resolves issue #19 and #18

* rotates mask
* takes away spurious 'f' characters in argparse file

* corrected formating (converted from f-string to other string format)

* Fix syntax warning (#22)

* Modularity changes

* Some small formatting fixes

* Packaged code

* Packaged code

* Some cleanup

* Import tweak

* More updates and fixes

* More fixes

* Updated README.md

* Caught up to master

* Fixed packaging issues, some general cleanup

* Formatting fixes

* Fixed accidental requirements change

* Forgot these files

* Fix cropping bug

* Fixed sorting randomness bug

* Fixed release version
  • Loading branch information
BernardZhao committed Dec 29, 2019
1 parent 1f41ed7 commit 8333e34
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 257 deletions.
39 changes: 23 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,34 @@ Have a look at [this post](http://satyarth.me/articles/pixel-sorting/) or [/r/pi

### Dependencies

Python 3.6 or greater.

Requires Pillow. `pip install Pillow` should work. If not, see [here](https://pillow.readthedocs.org/en/3.0.0/installation.html#linux-installation) for details.

There is also a requirements file which pretty much does the same via `pip install -r requirements.txt`.
Should work in both Python 2 and 3, but Python 3 is recommended.

### Usage

From the command line:

```
git clone https://github.com/satyarth/pixelsort.git
cd pixelsort
python3 pixelsort.py %PathToImage% [options]
pip install pixelsort
python3 -m pixelsort %PathToImage% [options]
```

Tip: To replicate Kim Asendorf's original [processing script](https://github.com/kimasendorf/ASDFPixelSort), first sort vertically and then horizontally in `threshold` (default) mode:

```
python3 pixelsort.py %PathToImage% -a 90
python3 pixelsort.py %PathToSortedImage%
python3 -m pixelsort %PathToImage% -a 90
python3 -m pixelsort %PathToSortedImage%
```

As a package:

```
>>> from pixelsort import pixelsort
>>> from PIL import Image
>>> a = Image.open("examples/image.jpg")
>>> a
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=576x324 at 0x7F8F6A2AC208>
>>> pixelsort(a)
<PIL.Image.Image image mode=RGBA size=576x324 at 0x7F8F66AA57B8>
```

#### Parameters:
Expand All @@ -40,7 +47,7 @@ Threshold (lower) | `-t` | How dark must a pixel be to be considered as a 'bord
Threshold (upper) | `-u` | How bright must a pixel be to be considered as a 'border' for sorting? Takes values from 0-1. 0.8 by default. Used in `threshold` mode.
Char. length | `-c` | Characteristic length for the random width generator. Used in mode `random`.
Angle | `-a` | Angle at which you're pixel sorting in degrees. `0` (horizontal) by default.
External int file | `-f` | Image used to define intervals. Must be black and white.
External interval file | `-f` | Image used to define intervals. Must be black and white.
Sorting function | `-s` | Sorting function to use for sorting the pixels.
Mask | `-m` | Image used for masking parts of the image.
Logging Level | `-l` | Level of logging statements made visible. Choices include `DEBUG`, `INFO`, `WARNING`, `ERROR`, and `CRITICAL`.
Expand Down Expand Up @@ -70,17 +77,17 @@ Sorting function | Description

#### Examples

`python3 pixelsort.py examples/image.jpg -i random -c 20`
`python3 -m pixelsort examples/image.jpg -i random -c 20`

![random](/examples/random.png)

`python3 pixelsort.py examples/image.jpg -i edges -t 250`
`python3 -m pixelsort examples/image.jpg -i edges -t 250`

![edges](/examples/edges.png)

* `file`: Intervals taken from image specified with `-f`. Must be black and white.

`python3 pixelsort.py examples/image.jpg -i file -f examples/intervals.png `
`python3 -m pixelsort examples/image.jpg -i file -f examples/intervals.png `

![file](/examples/intervals.png)

Expand All @@ -90,13 +97,13 @@ Sorting function | Description

* `mask`: Mask taken from image specified with `-m`. Must be black and white.

`python3 pixelsort.py examples/image.jpg -i random -c 20 -m examples/mask.png`
`python3 -m pixelsort examples/image.jpg -i random -c 20 -m examples/mask.png`

![file](/examples/mask.png)

![file](/examples/masked.png)

### todo
### Todo

* Allow defining different intervals for different channels.

Expand Down
104 changes: 0 additions & 104 deletions argparams.py

This file was deleted.

2 changes: 0 additions & 2 deletions constants.py

This file was deleted.

79 changes: 0 additions & 79 deletions pixelsort.py

This file was deleted.

2 changes: 2 additions & 0 deletions pixelsort/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from pixelsort.main import pixelsort
NAME = "pixelsort"
27 changes: 27 additions & 0 deletions pixelsort/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from PIL import Image
import logging
from pixelsort.argparams import parse_args
from pixelsort.main import pixelsort
from pixelsort.util import id_generator

args = parse_args()
image_input_path = args.pop("image_input_path")
image_output_path = args.pop("image_output_path")
interval_file_path = args.pop("interval_file_path")
mask_path = args.pop("mask_path")

if image_output_path is None:
image_output_path = id_generator() + ".png"
logging.warning("No output path provided, using " + image_output_path)

logging.debug("Opening image...")
args["image"] = Image.open(image_input_path)
if mask_path:
logging.debug("Opening mask...")
args["mask_image"] = Image.open(mask_path)
if interval_file_path:
logging.debug("Opening interval file...")
args["interval_file"] = Image.open(interval_file_path)

logging.debug("Saving image...")
pixelsort(**args).save(image_output_path)
55 changes: 55 additions & 0 deletions pixelsort/argparams.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import argparse
import logging
from pixelsort.interval import choices as interval_choices
from pixelsort.sorting import choices as sorting_choices
from pixelsort.constants import DEFAULTS


def parse_args():
parser = argparse.ArgumentParser(description="Pixel mangle an image.")
parser.add_argument("image", help="Input image file path.")
parser.add_argument("-o", "--output",
help="Output image file path, DEFAULTS to the time created.")
parser.add_argument("-i", "--int_function",
choices=interval_choices.keys(),
default=DEFAULTS["interval_function"],
help="Function to determine sorting intervals")
parser.add_argument("-f", "--int_file",
help="Image used for defining intervals.")
parser.add_argument("-t", "--threshold", type=float, default=DEFAULTS["lower_threshold"],
help="Pixels darker than this are not sorted, between 0 and 1")
parser.add_argument("-u", "--upper_threshold", type=float, default=DEFAULTS["upper_threshold"],
help="Pixels brighter than this are not sorted, between 0 and 1")
parser.add_argument("-c", "--clength", type=int, default=DEFAULTS["clength"],
help="Characteristic length of random intervals")
parser.add_argument("-a", "--angle", type=float, default=DEFAULTS["angle"],
help="Rotate the image by an angle (in degrees) before sorting")
parser.add_argument("-r", "--randomness", type=float, default=DEFAULTS["randomness"],
help="What percentage of intervals are NOT sorted")
parser.add_argument("-s", "--sorting_function",
choices=sorting_choices.keys(),
default=DEFAULTS["sorting_function"],
help="Function to sort pixels by.")
parser.add_argument(
"-m", "--mask", help="Image used for masking parts of the image")
parser.add_argument("-l", "--log_level", default="WARNING", help="Print more or less info",
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"])

_args = parser.parse_args()

logging.basicConfig(
format="%(name)s: %(levelname)s - %(message)s", level=logging.getLevelName(_args.log_level))

return {
"image_input_path": _args.image,
"image_output_path": _args.output,
"interval_function": _args.int_function,
"interval_file_path": _args.int_file,
"lower_threshold": _args.threshold,
"upper_threshold": _args.upper_threshold,
"clength": _args.clength,
"angle": _args.angle,
"randomness": _args.randomness,
"sorting_function": _args.sorting_function,
"mask_path": _args.mask
}
11 changes: 11 additions & 0 deletions pixelsort/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
BLACK_PIXEL = (0, 0, 0, 255)
WHITE_PIXEL = (255, 255, 255, 255)
DEFAULTS = {
"interval_function": "threshold",
"lower_threshold": 0.25,
"upper_threshold": 0.8,
"clength": 50,
"angle": 0,
"randomness": 0,
"sorting_function": "lightness",
}

0 comments on commit 8333e34

Please sign in to comment.