Skip to content

Instantly share code, notes, and snippets.

@bootleq
Created May 29, 2024 08:52
Show Gist options
  • Save bootleq/88341006e04c6dd939aa37400a770f5b to your computer and use it in GitHub Desktop.
Save bootleq/88341006e04c6dd939aa37400a770f5b to your computer and use it in GitHub Desktop.
GIMP 2.10.x Python-fu script for removing letterbox black edges
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from gimpfu import *
color_threshold = 5 # 像素顏色判定為黑色的閾值 (0-255)
min_continuous_pixels = 20 # 連續黑色像素,超過此閾值才判定為黑邊
max_detect_ratio = 50 # 搜尋黑邊過程中,抵達圖片的一定比例就放棄搜尋
def split_into_anchors(length, n):
# 將 length 均勻分割,取得 n 個分割點
# 例:將 100 以 n = 3 分割會得到 [25, 50, 75]
step = length // (n + 1)
parts = [i * step for i in range(n + 1)]
return parts[1:]
def detect_with_anchors(drawable, direction):
# 偵測黑邊,以多個節點座標為參考,在其一座標偵測到黑邊後,
# 會檢查其他節點的這個位置也是黑色才確認結果
anchors = split_into_anchors(drawable.width, 3)
if direction > 0:
start_index = 0
end_index = max(0, drawable.height * max_detect_ratio / 100 - 1)
step = 1
else:
start_index = drawable.height - 1
end_index = max(0, drawable.height * (100 - max_detect_ratio) / 100 - 1)
step = -1
while len(anchors) > 0:
a = anchors.pop()
edge = find_black_edge(drawable, a, start_index, end_index, step)
# 只多檢查 1 個節點,簡單處理
if edge > 0 and len(anchors) > 0 and drawable.get_pixel(anchors[0], edge)[0] < color_threshold:
return edge
return start_index
def find_black_edge(drawable, anchor, start_index, end_index, step):
edge = start_index
consecutive_black_pixels = 0
for y in range(start_index, end_index, step):
color = drawable.get_pixel(anchor, y)[0]
if color <= color_threshold:
consecutive_black_pixels += 1
if consecutive_black_pixels > min_continuous_pixels:
edge = y
else:
if edge != start_index:
return edge
else:
consecutive_black_pixels = 0
return edge
def process_image(image, drawable, p_min_continuous_pixels, p_max_detect_ratio):
global min_continuous_pixels
global max_detect_ratio
min_continuous_pixels = max(1, p_min_continuous_pixels)
max_detect_ratio = min(100, max(1, p_max_detect_ratio))
up_edge = detect_with_anchors(drawable, 1)
down_edge = detect_with_anchors(drawable, -1)
new_height = down_edge - up_edge
if new_height > 0:
# 裁剪圖片
pdb.gimp_image_crop(image, drawable.width, new_height, 0, up_edge)
pdb.gimp_displays_flush()
else:
gimp.message('找不到黑邊,停止操作')
script_params = [
(PF_INT16, "p_min_continuous_pixels", "黑邊的最小厚度(像素)", 30),
(PF_INT8, "p_max_detect_ratio", "搜尋不到黑邊時的停損比例(例:50 只會搜尋到圖片高的一半)", 50),
]
register(
"python_fu_crop_letterbox_edges",
"將圖片裁剪到其內容的範圍(移除上下端的黑邊區域)",
"將圖片裁剪到其內容的範圍(移除上下端的黑邊區域)",
"Chiao Chuang",
"Chiao Chuang",
"2024",
"<Image>/Filters/Languages/Python-Fu/剪裁外框黑邊",
"*",
script_params,
[],
process_image)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment