Created
May 29, 2024 08:52
-
-
Save bootleq/88341006e04c6dd939aa37400a770f5b to your computer and use it in GitHub Desktop.
GIMP 2.10.x Python-fu script for removing letterbox black edges
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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