Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compose #161

Merged
merged 9 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 2023

4.4.0 Added compose two pictures, removed histogram from code

4.3.3 Italian translation, __main__.py instead fotokilof.py

4.3.2 more ttkbootstrap: dark and light mode, licence window
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ GUI for the most used (by me) ImageMagick functionality for processing pictures.
- color auto-level or equalize,
- vignette
- adding logo image on picture,
- compose two image in one picture
- file formats: JPG, PNG, TIFF, SVG
- format conversion into JPG, PNG, TIFF.

Expand Down Expand Up @@ -61,7 +62,11 @@ GUI for the most used (by me) ImageMagick functionality for processing pictures.
- corners can be filled by selected color,
- offset in both direction
- logo position by gravity, size and offset,
- histograms of original and result pictures (temporary disabled),
- compose:
- add picture on right side
- add picture on bottom
- autoresize picture
- fill color if no autoresize
- fast file navigation: First, Prev, Next, Last or keys: Home, PgUp, PgDn, End,
- command editor: possible to use ImageMagick commands for convert: eg. *-gaussian-blur 10x10* or *-monochrome*, etc.
- dark and light mode
Expand Down
713 changes: 487 additions & 226 deletions fotokilof/__main__.py

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions fotokilof/convert_wand.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
- contrast - modify contrast
- crop - crop picture
- vignete - add vignete into picture
- compose - join two pictures
"""

import os
Expand Down Expand Up @@ -346,4 +347,111 @@ def vignette(clone, dx, dy, radius, sigma):
y=common.empty(dy))
log.write_log(" Conversion: vigette")


def compose(clone, compose_file, right, autoresize, color, gravity):
""" join two pictures
clone - clone of image for processing
compose_file - file to join
right - join on right or bottom side
autoresize - autoresize picture or not
color - color to fill gap if no autoresize
gravity - position if no autoresize
"""
if len(compose_file):
with Image(filename=compose_file) as compose_image:
if right:
stacked=False
# for canvas
canvas_width = clone.width + compose_image.width
if clone.height >= compose_image.height:
canvas_height = clone.height
else:
canvas_height = compose_image.height
# for autoresize
resize_width = compose_image.width * clone.height / compose_image.height
resize_height = clone.height
# for no autoresize
position_x1 = 0
position_x2 = clone.width
if clone.height >= compose_image.height:
# orig > compose
position_y1 = 0
if gravity == "N":
position_y2 = 0
elif gravity == "S":
position_y2 = canvas_height - compose_image.height
else:
position_y2 = canvas_height / 2 - compose_image.height / 2
else:
# orig < compose
position_y2 = 0
if gravity == "N":
position_y1 = 0
elif gravity == "S":
position_y1 = canvas_height - clone.height
else:
position_y1 = canvas_height / 2 - clone.height / 2
else:
stacked=True
# for canvas
if clone.width >= compose_image.width:
canvas_width = clone.width
else:
canvas_width = compose_image.width
canvas_height = clone.height + compose_image.height
# for autoresize
resize_width = clone.width
resize_height = compose_image.height * clone.width / compose_image.width
# for no autoresize
position_y1 = 0
position_y2 = clone.height
if clone.width >= compose_image.width:
# orig > compose
position_x1 = 0
if gravity == "W":
position_x2 = 0
elif gravity == "E":
position_x2 = canvas_width - compose_image.width
else:
position_x2 = canvas_width / 2 - compose_image.width / 2
else:
# orig < compose
position_x2 = 0
if gravity == "W":
position_x1 = 0
elif gravity == "E":
position_x1 = canvas_width - clone.width
else:
position_x1 = canvas_width / 2 - clone.width / 2

if autoresize:
# autoresize, no problem
resize_value = str(resize_width) + 'x' + str(resize_height)
compose_image.transform(crop='', resize=resize_value)
clone.sequence.append(compose_image)
clone.concat(stacked=stacked)
else:
# no autoresize
with Image(width=canvas_width, height=canvas_height, background=color) as canvas:
with Drawing() as draw:
# original picture
draw.composite(operator='over',
left=position_x1,
top=position_y1,
width=clone.width,
height=clone.height,
image=clone)
draw(canvas)
# picture to join
draw.composite(operator='over',
left=position_x2,
top=position_y2,
width=compose_image.width,
height=compose_image.height,
image=compose_image)
draw(canvas)
clone.image_set(canvas)

log.write_log(" Conversion: compose")

# EOF
100 changes: 77 additions & 23 deletions fotokilof/ini_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
- normalize
- contrast
- logo
- custom
- compose
"""

import configparser
Expand All @@ -48,59 +48,59 @@
def main(file_ini, preview_size_list):
""" General settings """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
config.read(file_ini, encoding="utf8")

# read values from a section
try:
file_in = config.get('Konfiguracja', 'path')
file_in = config.get('Main', 'path')
except:
file_in = ""
dict_return['file_in_path'] = file_in

try:
dir_work = config.get('Konfiguracja', 'work_dir')
dir_work = config.get('Main', 'work_dir')
except:
dir_work = "FotoKilof"
dict_return['work_dir'] = dir_work

try:
file_dir_select = config.getint('Konfiguracja', 'file_dir')
file_dir_select = config.getint('Main', 'file_dir')
except:
file_dir_select = "0"
dict_return['file_dir_selector'] = entries.parse_list(file_dir_select, (0, 1), 0)

try:
exif = config.getint('Konfiguracja', 'exif')
exif = config.getint('Main', 'exif')
except:
exif = "0"
dict_return['img_exif_on'] = entries.parse_list(exif, (0, 1), 0)

try:
histograms = config.getint('Konfiguracja', 'histograms')
custom = config.getint('Main', 'custom')
except:
histograms = "0"
dict_return['img_histograms_on'] = entries.parse_list(histograms, (0, 1), 0)
custom = 0
dict_return['img_custom_on'] = entries.parse_list(custom, (0, 1), 0)

try:
preview_orig = config.getint('Konfiguracja', 'preview_orig')
preview_orig = config.getint('Main', 'preview_orig')
except:
preview_orig = 400
dict_return['preview_orig'] = entries.parse_list(preview_orig,
preview_size_list, 400)

try:
preview_new = config.getint('Konfiguracja', 'preview_new')
preview_new = config.getint('Main', 'preview_new')
except:
preview_new = 400
dict_return['preview_new'] = entries.parse_list(preview_new,
preview_size_list, 400)

try:
log_level = config.get('Konfiguracja', 'log_level')
log_level = config.get('Main', 'log_level')
except:
log_level = "E"
dict_return['log_level'] = entries.parse_list(log_level,
Expand All @@ -113,7 +113,7 @@ def main(file_ini, preview_size_list):
def resize(file_ini):
""" Resize/scalling """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -155,7 +155,7 @@ def resize(file_ini):
def text(file_ini, fonts_dict):
""" Text configuration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -252,7 +252,7 @@ def text(file_ini, fonts_dict):
def rotate(file_ini):
""" Rotate configuration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -288,7 +288,7 @@ def rotate(file_ini):
def crop(file_ini):
""" Crop configuration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -391,7 +391,7 @@ def crop(file_ini):
def border(file_ini):
""" Border congiguration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -427,7 +427,7 @@ def border(file_ini):
def vignette(file_ini):
""" Vignette congiguration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -475,7 +475,7 @@ def vignette(file_ini):
def colors(file_ini):
""" Color configuration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -505,7 +505,7 @@ def colors(file_ini):
def normalize(file_ini, channels):
""" Normalize """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -535,7 +535,7 @@ def normalize(file_ini, channels):
def contrast(file_ini, contrast_selection_valid_list):
""" Contrast configuration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -579,7 +579,7 @@ def contrast(file_ini, contrast_selection_valid_list):
def logo(file_ini):
""" Logo cofiguration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand Down Expand Up @@ -634,7 +634,7 @@ def logo(file_ini):
def mirror(file_ini):
""" Rotate configuration """

# słownik wyjściowy
# output dictionary
dict_return = {}

config = configparser.ConfigParser()
Expand All @@ -660,4 +660,58 @@ def mirror(file_ini):

return dict_return


def compose(file_ini, preview_size_list):
""" Compose congiguration """

# output dictionary
dict_return = {}

config = configparser.ConfigParser()
config.read(file_ini, encoding="utf8")

try:
on = config.getint('Compose', 'on')
except:
on = "0"
dict_return['compose_on'] = entries.parse_list(on, (0, 1), 0)

try:
file = config.get('Compose', 'filename')
except:
file = ""
dict_return['compose_filename'] = file

try:
right = config.getint('Compose', 'right')
except:
right = 0
dict_return['compose_right'] = entries.parse_list(right, (0, 1), 0)

try:
autoresize = config.getint('Compose', 'autoresize')
except:
autoresize = 1
dict_return['compose_autoresize'] = entries.parse_list(autoresize, (0, 1), 1)

try:
color = config.get('Compose', 'color')
except:
color = "#FFFFFF"
dict_return['compose_color'] = entries.parse_color(color, '#FFFFFF')

try:
gravity = config.get('Compose', 'gravity')
except:
gravity = "C"
dict_return['compose_gravity'] = entries.parse_list(gravity,
("N", "W", "C", "E", "S"), "C")

try:
preview = config.getint('Compose', 'preview')
except:
preview = 400
dict_return['preview'] = entries.parse_list(preview,
preview_size_list, 400)
return dict_return
# EOF
Loading