Yesterday, 02:45 PM
Hi,
The code is very rough. It's output isn't very useful as is, but it runs now. I had some help with Google AI and and ChatGPT.
The code is very rough. It's output isn't very useful as is, but it runs now. I had some help with Google AI and and ChatGPT.
Code:
#!/usr/bin/env python3
import sys
import gi
import datetime
"""
# I use this when debugging. Any 'print()' statements get sent to 'file'.
# Trace errors by recording them to a file.
# If the file doesn't exist, create it.
import time
file = sys.stderr = sys.stdout = open("D:\\error.txt", 'a')
_start = f"\nPhotoBoothPro, {time.ctime()}"
_end = "_" * (80 - len(_start))
print(f"{_start}{_end}")
"""
gi.require_version('Gimp', '3.0')
gi.require_version('Gegl', '0.4')
from gi.repository import Gegl, Gimp, GLib # noqa
STRIP_W, STRIP_H = 600, 1800
MARGIN, FRAME_H = 40, 400
def run_filter(layer, filter_, q, mode, opacity):
"""
layer: Gimp.Layer
Receive filter output.
filter_: Gimp.DrawableFilter
q: iterable
[(property str, property value)]
mode: Gimp.LayerMode
Identify the layer blend mode with an enum (int).
opacity: float
.0 to 100.
"""
config = filter_.get_config()
for q1 in q:
config.set_property(*q1)
filter_.set_blend_mode(mode)
filter_.set_opacity(opacity)
filter_.update()
layer.append_filter(filter_)
return filter_
def make_filter(layer, s):
"""
Create a "Gimp.DrawableFilter" by string.
layer: Gimp.Layer
The filter name, e.g. 'oil-paint'.
"""
print(f"Making filter: {s}")
return Gimp.DrawableFilter.new(layer, f'gegl:{s}', "")
def do_color_balance(
drawable,
transfer_mode,
preserve_lum,
cyan_red,
magenta_green,
yellow_blue
):
"""Adjust color balance of a drawable."""
procedure = Gimp.get_pdb().lookup_procedure('gimp-drawable-color-balance')
config = procedure.create_config()
config.set_property('drawable', drawable)
config.set_property('transfer-mode', transfer_mode)
config.set_property('preserve-lum', preserve_lum)
config.set_property('cyan-red', cyan_red)
config.set_property('magenta-green', magenta_green)
config.set_property('yellow-blue', yellow_blue)
result = procedure.run(config)
success = result.index(0)
return success
def apply_schneider_look(image, drawable):
"""Applies optical and chemical effects."""
# 1. Mirror
drawable.transform_flip_simple(Gimp.OrientationType.HORIZONTAL, True, 0)
# Prepare arguments for Lens Distortion.
filter_ = make_filter(drawable, 'lens-distortion')
# 2. Schneider Optical Effects
# Use the default filter settings, '[]', for Lens Distortion.
run_filter(
drawable,
filter_,
[],
Gimp.LayerMode.NORMAL,
100.
)
filter_ = make_filter(drawable, 'bloom')
# Use the default filter settings, '[]', for Bloom.
run_filter(
drawable,
filter_,
[],
Gimp.LayerMode.NORMAL,
100.
)
# 3. Chemical Color Balance
preserve_lum = True
cyan_red = -0.15
magenta_green = 0.10
yellow_blue = -0.25
do_color_balance(
drawable,
Gimp.TransferMode.SHADOWS,
preserve_lum,
cyan_red, magenta_green, yellow_blue
)
do_color_balance(
drawable,
Gimp.TransferMode.HIGHLIGHTS,
preserve_lum,
cyan_red, magenta_green, yellow_blue
)
do_color_balance(
drawable,
Gimp.TransferMode.MIDTONES,
preserve_lum,
cyan_red, magenta_green, yellow_blue
)
# 4. Silver Halide Grain
filter_ = make_filter(drawable, 'noise-rgb')
run_filter(
drawable,
filter_,
[],
Gimp.LayerMode.NORMAL,
100.
)
def photobooth_main_proc(
procedure,
run_mode,
image,
drawables,
args,
data,
):
Gimp.context_push()
image.undo_group_start()
new_image = Gimp.Image.new(STRIP_W, STRIP_H, Gimp.ImageBaseType.RGB)
Gimp.Display.new(new_image) #
bg_color = Gegl.Color.new('#F9F7F2')
bg_layer = Gimp.Layer.new(
new_image,
'Paper Base',
STRIP_W,
STRIP_H,
Gimp.ImageType.RGBA_IMAGE,
100.,
Gimp.LayerMode.NORMAL,
)
new_image.insert_layer(bg_layer, None, 0)
Gimp.context_set_background(bg_color)
bg_layer.fill(Gimp.FillType.BACKGROUND)
y_offset = MARGIN
for i in range(min(len(drawables), 4)):
source_layer = drawables[i]
new_frame = Gimp.Layer.new_from_drawable(source_layer, new_image)
new_image.insert_layer(new_frame, None, -1)
apply_schneider_look(new_image, new_frame)
target_w = STRIP_W - MARGIN * 2
scale_ratio = target_w / new_frame.get_width()
new_frame.scale(
target_w, int(new_frame.get_height() * scale_ratio), True
)
new_frame.set_offsets(MARGIN, y_offset)
y_offset += FRAME_H + 15
# Mechanical Date Stamp
stamp_color = Gegl.Color.new('#B22222')
date_str = datetime.datetime.now().strftime('PHOTO-ME - %d %b %Y').upper()
Gimp.context_set_foreground(stamp_color)
# This should work but doesn't.
font = Gimp.Font.get_by_name('Sans-serif')
# Text Layer logic for GIMP 3
stamp_layer = Gimp.TextLayer.new(
new_image,
date_str,
font,
18.0,
Gimp.Unit.pixel()
)
new_image.insert_layer(stamp_layer, None, 0)
if stamp_layer:
stamp_layer.transform_rotate_simple(
Gimp.OrientationType.VERTICAL, True, 0, 0
)
# stamp_layer.set_offsets(STRIP_W - 35, STRIP_H - 450) Needs work.
stamp_layer.set_opacity(70.)
Gimp.Display.new(new_image)
image.undo_group_end()
Gimp.context_pop()
Gimp.displays_flush()
return procedure.new_return_values(
Gimp.PDBStatusType.SUCCESS, GLib.Error()
)
class PhotoboothPro(Gimp.PlugIn):
def do_query_procedures(self):
return ['python-fu-photobooth-pro']
def do_create_procedure(self, name):
procedure = Gimp.ImageProcedure.new(
self, name, Gimp.PDBProcType.PLUGIN, photobooth_main_proc, None
)
procedure.set_image_types('RGB*')
procedure.set_documentation(
'Schneider Photobooth Pro',
'Full analog strip recreation',
name
)
procedure.set_menu_label('Schneider Photobooth Pro...')
procedure.add_menu_path('<Image>/Filters/Artistic')
procedure.set_attribution('Gemini', 'Gemini', '2026')
return procedure
Gimp.main(PhotoboothPro.__gtype__, sys.argv)
