(Moved to https://git.sr.ht/~noelle/glitch_me) Python module to add some distortion/glitch effects to images.
Repo has been moved to
glitch_me
Python module to add some distortion/glitch effects to images.
Inspired by the work of DataErase.
Examples using the included transforms
(Click images for larger view)
| Original | Glitched | GIF'd | |----------|----------|-------| |
|
|
| |
|
|
| |
|
|
|
Dependencies
Note: This module may work with older versions of these, but compatibility is only guaranteed on these versions or newer.Install
Download
git clone https://github.com/noelleleigh/glitch_me.git
Recommended Install Method
Add theglitch_me to your Python scripts available on your path and automatically install dependencies by running:
pip install -e ./glitch_me
No Install Method
If you don't wantglitch_me added to your scripts, you can run it from within its folder with:
python -m glitch_me
Usage
Command Line Interface (CLI) Arguments
usage: glitchme [-h] [-q] [--linecount LINE_COUNT] [-f FRAMES] [-d DURATION]
[-b]
{still,gif} input output_dir
Add some glitch/distortion effects to images.
positional arguments: {still,gif} Make a still glitched image, or a progressive glitch animation. input Input image path glob pattern output_dir Path to output directory (files will be saved with "_glitch" suffix)
optional arguments: -h, --help show this help message and exit -q, --quiet Include to not print the paths to the output image(s). --linecount LINECOUNT The vertical resolution you want the glitches to operate at -f FRAMES, --frames FRAMES The number of frames you want in your GIF (default: 20) -d DURATION, --duration DURATION The delay between frames in ms (default: 100) -b, --bounce Include if you want the gif to play backward to the beginning before looping. Doubles frame count.
Examples
Add glitch effects to a single image and save it to its existing directory:glitch_me still /pictures/image.png /pictures
Add glitch effects to multiple images and save them to a different directory:
glitch_me still /pictures/*.png /pictures/glitched
Add glitch effects to a single image, pixelated to a vertical resolution of 200px:
glitchme still --linecount 200 /pictures/image.png /pictures
Create a glitch GIF from a single image, pixelated to a vertical resolution of 200px, with 10 frames, 50ms frame delay:
glitchme gif --linecount 200 -f 10 -d 50 /pictures/image.png /pictures
Deeper Customization
The CLI was written as a thin shell and doesn't expose the many ways this library can modify an image. For fine-grained control over the actual transformations applied by the CLI, you must edit the filesample_transform.py.
In sample_transform.py, you'll find two important objects:
STATICTRANSFORM: A list of tuples, each containing a function reference and the arguments to pass into that function. This list of functions tellsglitchmehow to transform your image.GIFTRANSFORM: A function that takes a value calledprogressthat tells the function how far along it is in the animation. The function returns a list in the same format asSTATICTRANSFORMthat is used to transform a specific animation frame.
still or gif options in the CLI, respectively.
The functions referenced in both objects all have one thing in common: They take in a Pillow.Image object (and extra arguments) and return a Pillow.Image object (presumably modified from the input). If you look at the functions that are there already, you'll see that most of them come from the effects.py file, where a lot of useful glitching functions are defined. You can use any function in there with the pattern functionname(im: ImageType, ...) -> ImageType to add a transformation.
Add a New Transformation Tutorial
Say you were looking througheffects.py and decided you wanted to add the effect shiftcorruption to the GIF transformations.
- First, check the function's docstring (the part under the
def ...line surrounded by"""triple quotes""") to learn what it does and how to use it. shift_corruptiontakes three arguments:
im: a Pillow Image (This one is handled by default in the function that uses STATICTRANSFORM and GIFTRANSFORM)
2. offset_mag: The furthest you want a pixel row to be shifted (in pixels)
3. coverage: What percentage of rows will be shifted
- Now that we know what the function needs, we need to decide what values to give it. The
GIFTRANSFORMfunction has a useful variable in it calledloopprogress, which will let us make an effect that goes from clean, to glitchy, and back to clean over the course of the GIF animation. We'll do some math so that whenloopprogressis 0.0, there's no glitching. When it's 1.0, there's maximum glitching. So if you want your maximumoffesetmagto be 10 pixels, then we would putint(10 * loop_progress)into that argument (theint()is to convert the floating point value to an integer, which is what that argument expects). The same principle applies forcoverage. - So the code we'll be adding will look like:
(effects.shift_corruption, {
'offsetmag': int(10 loopprogress), 'coverage': 0.5 loop_progress
})
(I've indented the arguments so the line isn't impractically long.)
- Now we have to decide where in the multi-step transformation to add this line. Let's add it after the
sinwavedistortion(don't forget to add a comma to the end!), so the final list will look like:
return [
(effects.convert, {'mode': 'RGB'}),
(effects.pixel_sort, {
'mask_function':
lambda val, factor=loopprogress, limit=lumlimit:
255 if val < limit * factor else 0,
'reverse': True
}),
(effects.sinwavedistortion, {
'mag': 5, 'freq': 1, 'phase': -2piprogress
}),
(effects.shift_corruption, {
'offsetmag': int(10 loopprogress), 'coverage': 0.5 loop_progress
}),
(effects.addnoisebands, {
'count': int(10 * loop_progress), 'thickness': 10
}),
(effects.lowresblocks, {
'rows': 10, 'cols': 10, 'cells': int(10 * progress), 'factor': 4
}),
(ImageOps.posterize, {'bits': int(5 * (1 - loop_progress) + 3)}),
(effects.splitcolorchannels, {'offset': int(5 * loop_progress)}),
(effects.convert, {'mode': 'P', 'palette': Image.ADAPTIVE}),
]
- Save your modified
sample_transform.pytry creating a GIF and admire your distorted, glitchy results!