Skip to content

Commit 03694fd

Browse files
committed
V2.
1 parent c04996d commit 03694fd

36 files changed

+944
-249
lines changed

.github/workflows/testing.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
python-version: ["3.10", "3.11", "3.12"]
14+
python-version: ["3.10", "3.11", "3.12", "3.13"]
1515
poetry-version: [1.2.2]
1616
os: [ubuntu-latest, macos-latest, windows-latest]
1717
runs-on: ${{ matrix.os }}

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "anshitsu"
3-
version = "1.6.0" # using poetry-dynamic-versioning
3+
version = "2.0.0" # using poetry-dynamic-versioning
44
description = "A tiny digital photographic utility."
55
readme = "README.md"
66
authors = ["Iosif Takakura <[email protected]>"]
@@ -14,7 +14,7 @@ enable = true
1414
style = "pep440"
1515

1616
[tool.poetry.dependencies]
17-
python = "<3.13,>=3.10"
17+
python = "<4.0,>=3.10"
1818
numpy = "*"
1919
Pillow = "*"
2020
colorcorrect = "*"

src/anshitsu/cli.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import fire.core
1010
from PIL import Image, UnidentifiedImageError
1111

12-
from anshitsu.processor import Processor
12+
from anshitsu.process.processor import Processor
1313
from anshitsu.__version__ import version as __version__
1414

1515

@@ -19,11 +19,19 @@ def cli(
1919
colorstretch: bool = False,
2020
grayscale: bool = False,
2121
invert: bool = False,
22+
color: Optional[float] = None,
23+
brightness: Optional[float] = None,
24+
sharpness: Optional[float] = None,
25+
contrast: Optional[float] = None,
2226
tosaka: Optional[float] = None,
2327
outputrgb: bool = False,
28+
sepia: bool = False,
29+
cyanotype: bool = False,
2430
noise: Optional[float] = None,
2531
overwrite: bool = False,
2632
version: bool = False,
33+
line_drawing: bool = False,
34+
posterize: Optional[int] = None,
2735
) -> str:
2836
"""
2937
Process Runnner for Command Line Interface
@@ -49,9 +57,16 @@ def cli(
4957
colorstretch (bool, optional): Use colorstretch algorithm. Defaults to False.
5058
grayscale (bool, optional): Convert to grayscale. Defaults to False.
5159
invert (bool, optional): Invert color. Defaults to False.
52-
tosaka (Optional[float], optional): Use Tosaka mode. Defaults to None.
60+
color (Optional[float], optional): Fix color balance. Defaults to None.
61+
brightness (Optional[float], optional): Fix brightness. Defaults to None.
62+
sharpness (Optional[float], optional): Fix sharpness. Defaults to None.
63+
contrast (Optional[float], optional): Fix contrast. Defaults to None.
64+
tosaka (Optional[float], optional): Convert to grayscale with fix contrast. Defaults to None.
5365
outputrgb (bool, optional): Outputs a monochrome image in RGB. Defaults to False.
66+
cyanotype (bool, optional): Convert to RGB like cyanotype. Defaults to False.
67+
sepia (bool, optional): Convert to RGB colored by sepia. Defaults to False.
5468
noise (Optional[float], optional): Add Gaussian noise. Defaults to None.
69+
line_drawing (bool, optional): Convert to like line drawing. Defaults to False.
5570
version (bool, optional): Show version. Defaults to False.
5671
5772
Raises:
@@ -121,10 +136,18 @@ def cli(
121136
colorautoadjust=colorautoadjust,
122137
colorstretch=colorstretch,
123138
grayscale=grayscale,
139+
color=color,
140+
contrast=contrast,
141+
brightness=brightness,
142+
sharpness=sharpness,
124143
invert=invert,
125144
tosaka=tosaka,
126145
outputrgb=outputrgb,
146+
cyanotype=cyanotype,
147+
sepia=sepia,
127148
noise=noise,
149+
line_drawing=line_drawing,
150+
posterize=posterize,
128151
)
129152
saved_image = psr.process()
130153
os.makedirs(os.path.join(return_path, output_dir), exist_ok=True)

src/anshitsu/process/brightness.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from PIL import Image, ImageEnhance
2+
3+
def brightness(image: Image, brightness: float) -> Image:
4+
"""
5+
brightness
6+
7+
Fix brightness.
8+
9+
Parameters:
10+
image: Image
11+
brightness: float
12+
13+
Returns:
14+
Image: processed image.
15+
"""
16+
enhancer = ImageEnhance.Brightness(image)
17+
image = enhancer.enhance(brightness)
18+
return image

src/anshitsu/process/color.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from PIL import Image, ImageEnhance
2+
3+
def color(image: Image, color: float) -> Image:
4+
"""
5+
contrast
6+
7+
Fix color balance.
8+
9+
Parameters:
10+
image: Image
11+
color: float
12+
13+
Returns:
14+
Image: processed image.
15+
"""
16+
enhancer = ImageEnhance.Contrast(image)
17+
image = enhancer.enhance(color)
18+
return image
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from PIL import Image
2+
import colorcorrect.algorithm as cca
3+
from colorcorrect.util import to_pil, from_pil
4+
5+
6+
def color_auto_adjust(image: Image) -> Image:
7+
"""
8+
color_auto_adjust
9+
10+
Use Color Auto Adjust algorithm.
11+
12+
Returns:
13+
Image: processed image.
14+
"""
15+
if image.mode == "L":
16+
return image
17+
return to_pil(cca.automatic_color_equalization(from_pil(image)))
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from collections import namedtuple
2+
from typing import Optional, Tuple
3+
4+
from PIL import Image
5+
import colorcorrect.algorithm as cca
6+
from colorcorrect.util import to_pil, from_pil
7+
8+
9+
def color_stretch(image: Image) -> Image:
10+
"""
11+
color_stretch
12+
13+
Use Color Stretch algorithm.
14+
15+
Parameters:
16+
image: Image
17+
18+
Returns:
19+
Image: processed image.
20+
"""
21+
if image.mode == "L":
22+
return image
23+
return to_pil(cca.stretch(cca.grey_world(from_pil(image))))

src/anshitsu/process/contrast.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from PIL import Image, ImageEnhance
2+
3+
def contrast(image: Image, contrast: float) -> Image:
4+
"""
5+
contrast
6+
7+
Fix contrast.
8+
9+
Using in Tosaka mode.
10+
11+
Tosaka mode is a mode that expresses the preference of
12+
Tosaka-senpai, a character in "Kyūkyoku Chōjin R",
13+
for "photos taken with Tri-X that look like they were
14+
burned onto No. 4 or No. 5 photographic paper".
15+
Only use floating-point numbers when using this mode;
16+
numbers around 2.4 will make it look right.
17+
18+
Parameters:
19+
image: Image
20+
contrast: float
21+
22+
Returns:
23+
Image: processed image.
24+
"""
25+
enhancer = ImageEnhance.Contrast(image)
26+
image = enhancer.enhance(contrast)
27+
return image

src/anshitsu/process/cyanotype.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from PIL import Image, ImageOps
2+
3+
def cyanotype(image: Image) -> Image:
4+
"""
5+
cyanotype
6+
7+
Outputs a monochrome image colored at prussian blue like cyanotype.
8+
9+
Returns:
10+
Image: processed image.
11+
"""
12+
if image.mode == "L":
13+
image = ImageOps.colorize(image, black=(26, 68, 114), white=(255, 255, 255))
14+
return image

src/anshitsu/process/grayscale.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from collections import namedtuple
2+
3+
import numpy as np
4+
from PIL import Image
5+
6+
7+
def grayscale(image: Image) -> Image:
8+
"""
9+
grayscale
10+
11+
Converts to grayscale based on the luminance in the CIE XYZ color space.
12+
13+
Parameters:
14+
image: Image
15+
16+
Returns:
17+
Image: processed image.
18+
"""
19+
if image.mode == "L":
20+
return image
21+
22+
rgb = np.array(image, dtype="float32")
23+
24+
gamma = 2.2
25+
ColorMatrix = namedtuple("ColorMatrix", ("red", "green", "blue"))
26+
27+
# Coefficients for luminance in CIE XYZ color space
28+
cie_xyz = ColorMatrix(0.2126, 0.7152, 0.0722)
29+
30+
# Inverse Gamma Correction
31+
rgb_l = pow(rgb / 255.0, gamma)
32+
33+
# Extract RGB values
34+
r, g, b = rgb_l[:, :, 0], rgb_l[:, :, 1], rgb_l[:, :, 2]
35+
36+
# Convert to grayscale
37+
gray_l = cie_xyz.red * r + cie_xyz.green * g + cie_xyz.blue * b
38+
39+
# gamma correction
40+
gray = pow(gray_l, 1.0 / gamma) * 255
41+
42+
image = Image.fromarray(gray.astype("uint8"))
43+
44+
return image

0 commit comments

Comments
 (0)