An open source image processing library that supports blend modes, curve adjustment, and other adjustments that graphic designers or photographers frequently use
Project description
Layer.is
A library that supports all blend modes in Photoshop, brightness, contrast, hue, saturation, lightness adjustments, and curve adjustments on separate RGB channels.
This project was a part of the 2019 Open Source Software Competition.
Why use Layer.is?
- Supports all frequently used blend modes in Photoshop
- Chain operations for concise, readable image pipelines
- Straightforward API to manipulate images
- Load a sequence of operations from JSON
- Apply curve adjustments selectively to individual RGB channels
Requirements
Python 3.10 or higher.
Installation
From PyPI
pip install layeris
From source
git clone https://github.com/subwaymatch/layer-is-python.git
cd layer-is-python
pip install .
To install with development dependencies (includes pytest):
pip install -e ".[dev]"
# or, using hatch:
hatch env create
Quick Start
Load an image
from layeris import LayerImage
# From a local file
image = LayerImage.from_file('/path/to/image.jpg')
# From a URL
image = LayerImage.from_url('https://example.com/photo.jpg')
# From a NumPy array (float64, values in [0, 1], shape HxWx3 or HxWx4)
import numpy as np
data = np.random.random((100, 100, 3))
image = LayerImage.from_array(data)
Save an image
# Default quality is 95 for JPEG
image.save('output.jpg')
# Specify JPEG quality (0–100)
image.save('output.jpg', quality=85)
# Save as PNG (lossless)
image.save('output.png')
Basic adjustments
# Grayscale
image.grayscale()
# Brightness (factor > 0 brightens, factor < 0 darkens)
image.brightness(0.2)
# Contrast (factor > 1 increases, 0 < factor < 1 decreases)
image.contrast(1.5)
# Hue (value in [0, 1])
image.hue(0.3)
# Saturation (factor > 0 increases, factor < 0 decreases; -1 fully desaturates)
image.saturation(-0.5)
# Lightness (factor > 0 lightens toward white, factor < 0 darkens toward black)
image.lightness(0.4)
# Curve adjustment (apply an S-curve to the RGB channels)
image.curve('rgb', [0, 0.1, 0.4, 0.65, 0.9, 1])
# Curve on a single channel
image.curve('r', [0, 0.2, 0.8, 1])
Resize
image.resize(width=800, height=600)
Blend modes
All blend mode methods accept a hex colour string or a NumPy array, plus an optional opacity parameter (0.0–1.0).
Darken group
image.darken('#3fe28f')
image.multiply('#3fe28f', opacity=0.8)
image.color_burn('#7fe3f8')
image.linear_burn('#e1a8ff')
Lighten group
image.lighten('#ff3ce1')
image.screen('#e633ba')
image.color_dodge('#490cc7')
image.linear_dodge('#490cc7')
Contrast group
image.overlay('#ffb956')
image.soft_light('#ff3cbc')
image.hard_light('#df5dff')
image.vivid_light('#ac5b7f')
image.linear_light('#9fa500')
image.pin_light('#005546')
Method chaining
All operations return self, so calls can be chained:
result = (
LayerImage.from_file('photo.jpg')
.grayscale()
.brightness(0.1)
.multiply('#3fe28f', opacity=0.7)
.curve('rgb', [0, 0.2, 0.8, 1])
.save('output.jpg')
)
Clone
# Create an independent copy before branching
copy = image.clone()
copy.darken('#000000') # original is unaffected
Get image data as a NumPy array
arr = image.get_image_as_array()
# arr.shape → (height, width, 3) for RGB
# → (height, width, 4) for RGBA
# arr.dtype → float64
# values in [0.0, 1.0]
Apply operations from a dictionary or JSON file
Operations can be described as a Python dict (or a JSON file) and applied in sequence:
ops = {
"operations": [
{"type": "grayscale"},
{"type": "brightness", "factor": 0.15},
{"type": "multiply", "hex": "#3fe28f", "opacity": 0.6},
{"type": "curve", "channels": "rgb", "curve_points": [0, 0.1, 0.9, 1]},
{"type": "resize", "width": 800, "height": 600},
]
}
image.apply_from_dict(ops)
# Or load directly from a JSON file
image.apply_from_json('pipeline.json')
Supported operation types: grayscale, resize, brightness, contrast, hue,
saturation, lightness, curve, darken, multiply, color_burn,
linear_burn, lighten, screen, color_dodge, linear_dodge, overlay,
soft_light, hard_light, vivid_light, linear_light, pin_light.
Running tests
Install development dependencies and run the test suite with pytest:
# Using pip (editable install)
pip install -e .
pip install pytest pytest-cov
pytest
# Using hatch (recommended)
hatch run test
# With coverage report
hatch run test-cov
Run a specific test file or test:
pytest tests/test_layer_image.py
pytest tests/test_utils.py
pytest tests/test_layer_image.py::TestBlendModes::test_multiply_by_white_no_change -v
Blend mode reference
| Group | Method | Formula (A = base, B = blend) |
|---|---|---|
| Darken | darken |
min(A, B) |
| Darken | multiply |
A × B |
| Darken | color_burn |
1 − (1 − A) / B |
| Darken | linear_burn |
A + B − 1 |
| Lighten | lighten |
max(A, B) |
| Lighten | screen |
1 − (1 − A)(1 − B) |
| Lighten | color_dodge |
A / (1 − B) |
| Lighten | linear_dodge |
A + B |
| Contrast | overlay |
2AB if A ≤ 0.5 else 1 − 2(1−A)(1−B) |
| Contrast | soft_light |
Pegtop formula |
| Contrast | hard_light |
2AB if B ≤ 0.5 else 1 − 2(1−A)(1−B) |
| Contrast | vivid_light |
Color burn / dodge based on B |
| Contrast | linear_light |
A + 2B − 1 |
| Contrast | pin_light |
Conditional replace |
All results are clamped to [0, 1].
Roadmap
- Imitate Photoshop's auto brightness & auto contrast features
- Add filter presets
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file layeris-0.3.1.tar.gz.
File metadata
- Download URL: layeris-0.3.1.tar.gz
- Upload date:
- Size: 15.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.27.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79a458db60891b2e7166ccbf15b9f159ee5d109309947b5e8bd18bc132f7520d
|
|
| MD5 |
fab1210aed2d5f9f5c0d84f88d4880b0
|
|
| BLAKE2b-256 |
d84f1fe5a376c65ec46cbda131023511b344a5ac17f69be3425e773e0f5bb38c
|
File details
Details for the file layeris-0.3.1-py3-none-any.whl.
File metadata
- Download URL: layeris-0.3.1-py3-none-any.whl
- Upload date:
- Size: 3.0 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.27.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c19ba2dbb0511c691dfe7e52300e2ab6a6b1bd6c2e2f05b3d3515ac3daf083e1
|
|
| MD5 |
105ae30a9b0b46794bd088376cf8d204
|
|
| BLAKE2b-256 |
1712ca2f6a2c502f850271a6925e5eef5f666361ee52b78eee05326662f4fcc3
|