Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/setanarut/halftonism
Artistic halftone generation library
https://github.com/setanarut/halftonism
animated-gif art artistic artistic-coding color-cycle color-cycling computer-graphics digital-elevation-model fractal gif-animation gif-creator halftone halftoning loop optical-illusion procedural-art
Last synced: 15 days ago
JSON representation
Artistic halftone generation library
- Host: GitHub
- URL: https://github.com/setanarut/halftonism
- Owner: setanarut
- License: gpl-3.0
- Created: 2019-11-14T17:38:24.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2024-02-08T00:43:23.000Z (9 months ago)
- Last Synced: 2024-02-08T01:34:42.092Z (9 months ago)
- Topics: animated-gif, art, artistic, artistic-coding, color-cycle, color-cycling, computer-graphics, digital-elevation-model, fractal, gif-animation, gif-creator, halftone, halftoning, loop, optical-illusion, procedural-art
- Language: Python
- Homepage:
- Size: 8.96 MB
- Stars: 14
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Halftonism
Artistic halftone generation library
![example_6_tri_fs2_m70](./assets/eyeswide.gif)
## Installation
```shell
pip install git+https://github.com/setanarut/halftonism
```## Tutorial
```python
from halftonism import Projectp = Project("example.ora", repeat=16, waveform="triangle")
p.save_GIF("example.gif", scale=0.25, miliseconds=70, colors=30, resample=3)
```![Krita ORA Screenshot](./example/example.gif)
### Preparing the ORA file
![Krita ORA Screenshot](./assets/krita_ORA_SS.jpg)
You can open the example.ora file in [example](./example/) folder with the [Krita](https://docs.krita.org/en/general_concepts/file_formats/file_ora.html). ([Openraster](https://www.openraster.org/) format). In the example you can see the color layers obtained using [fastLayerDecomposition](https://github.com/CraGL/fastLayerDecomposition) repository. After installing the halftonism package, the `folder2ora` command line tool is installed. Using this, you can convert the folder full of PNG layers obtained with [fastLayerDecomposition](https://github.com/CraGL/fastLayerDecomposition) into an ORA file. Saves it with the name `output.ora`.
```bash
$ folder2ora ~/Downloads/layers_folder# saved -> ~/Downloads/layers_folder/output.ora
```Alternatively you can decompose and save image as an ORA file with the [decompose](https://github.com/setanarut/decompose) package. [decompose](https://github.com/setanarut/decompose) package separates very quickly using pytorch but the colors are inaccurate a little bit depending on the palette.
```bash
$ decomp ~/Desktop/img.png
# Decomposer mask generation...
# Decomposer processing alpha layers...
# Decomposer Done!
# ORA saved: img.ora
# 7
# Palette saved: img_palette.png
```Also you can paint it by hand without layer decompositing. Play around with layer orders and alpha levels for a more color balanced halftone outputs.
#### ORA Layer Structure
Before processing the ORA file with Python, you have to follow the template below.
1. Each color layer should contain only a single color.
2. The bottom background layer (base color) must be solid color.
3. There should be a grayscale fractal heightmap at the top layer for halftone patterns. Top layer can be a computer generated heightmaps or [real DEM images](https://tangrams.github.io/heightmapper/) or any suitable grayscale gradient.
#### Some procedural techniques.
- Procedural terrains based on simplified landscape evolution model (LEM) [github.com/TadaTeruki/fastlem-random-terrain](https://github.com/TadaTeruki/fastlem-random-terrain)
- Diffusion-limited aggregation
- Mandelbrot Fractals
- Hydraulic erosion simulation across a heightfield (Noise)##### Fastlem terrain fractal example
![fastlem](./assets/fastlem.gif)
##### Mandelbrot fractal example
![mandel](./assets/mandel.gif)
### ORA processing with halftonism package
Halftone animation is created with 256 pixels linear grayscale gradient [cycling](https://en.wikipedia.org/wiki/Color_cycling), also known as palette shifting or palette animation. The halftone pattern and color layer are mixed with the [*Hard Mix*]([https://](http://www.simplefilter.de/en/basics/mixmods.html)) blending mode (mix *halftone gradient pattern* and *color layer* by 50%. If the alpha value is greater than 128, set the color to 255, otherwise set the color to 0).
#### `Project()` parameters
##### waveform
Waveform of gradient. `Project()` has parameters `waveform="sawtooth"`, `waveform="triangle"` and `waveform="sine"`. The effects are shown below, respectively.
![downsample](./assets/waveforms.png)
##### repeat
This number determines how many times gradient will be divided. The formula` (256 / repeat) / frame_skipping` gives the number of animation frames. (frame_skipping is 1 by default, meaning it is disabled). For example, `repeat=8` will give 32 frames. (**256/8/1 = 32 frames**).
Let's save all sawtooth gradient repetitions from 1 to 16 as image. It will help to understand. Height increased from 256x1 to 256x32 and image rotated 90 degree for visibility.
```python
from PIL import Image
import numpy as np
from halftonism.utils import gradient_vstack, gradientstack = gradient_vstack(gradient(1, "sawtooth"), 32)
for repeat in range(2, 17):
stack = np.vstack((stack, gradient_vstack(gradient(repeat, "sawtooth"), 32)))
im = Image.fromarray(stack)
im.rotate(90, expand=True).save("gradient_repeats.png")```
![Gradient repeats 1-16 ](./assets/gradient_repeats.png)
##### frame_skipping
You can skip frames to reduce GIF/APNG file size. This also reduces the frame jump effect in repeat numbers where the number 256 is not divisible, such as 3,7,10.
#### Antialiasing
For antialiasing, you can downscale image with [bicubic sampling](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#PIL.Image.Resampling.BICUBIC). For example, you can start with 2000x2000 and downscale to 500x500 for final output (500 / 2000 = 0.25 scale). The `save_GIF()` `save_APNG()` and `save_frame()` methods have `scale` and [resample](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#PIL.Image.Resampling.BICUBIC) arguments.
Resampling example with `NEAREST` on the left and `BICUBIC` on the right. (scale 0.25)
![downsample](./assets/downsample.png)
```python
p.save_GIF("output.gif", scale=0.25, resample=Image.BICUBIC)
p.save_frame(0, "01_frame.png", scale=0.25., resample=3)
```