トミー No title
No License Python
2022年06月16日
Copy Clone
# -*- coding: utf-8 -*-
"""
  スクリプト名 : tkinterpiccolor.py
  処理内容:tkinterでコンボボックスの設定サンプル
  対応:pydroid3対応 Macは非対応?
  補足:Harigami上での実行は不可
"""
from logging import shutdown
from tkinter import *
import tkinter as tk
import tkinter.ttk as ttk

import datetime
import os, sys, platform
import glob
from PIL import Image, ImageDraw, ImageFont
import PIL.ExifTags as ExifTags
from PIL import Image, ImageTk

# メッセージボックス
from tkinter import messagebox

# 自作ライブラリ
import usefully

# 透かし文字の透明度
_opacity = 70
_colorlist = ["桃", "橙", "紫", "黄緑", "黄", "桜"]
_colorrgblist = [
    [240, 145, 153],
    [238, 120, 0],
    [136, 72, 152],
    [188, 226, 91],
    [255, 217, 0],
    [254, 244, 244],
]
"""
_colorlist  = ['桃','橙','紫','水','黄','桜','茶','鼠','黄緑','金']
_colorrgblist = [[240,145,153],[238,120,0],
                    [136,72,152],[188,226,91],
                    [255,217,0],[0,0,0],
                    [0,0,0],[0,0,0],
                    [0,0,0],[0,0,0]]
"""

"""
関数名 : messageboxshow
引数 : title                   タイトル
        message                 メッセージ
機能:メッセージボックス表示
作成日:2021/09/25
修正日:
"""


def messageboxshow(title, message):
    messagebox.showinfo(title, message)


"""
関数名 : value_reset
機能:色リセット
作成日:2021/10/03
修正日:
"""


def value_reset():

    # 定数
    BLACK_R_NUM = 0
    BLACK_G_NUM = 0
    BLACK_B_NUM = 0
    GLAY_R_NUM = 128
    GLAY_G_NUM = 128
    GLAY_B_NUM = 128
    SKY_R_NUM = 137
    SKY_G_NUM = 189
    SKY_B_NUM = 222
    WHITE_R_NUM = 255
    WHITE_G_NUM = 255
    WHITE_B_NUM = 255

    # 切替コントロール
    controlchoice_num = controlchoice.get()
    # 色
    colorresetchoice_num = colorresetchoice.get()

    if colorresetchoice_num == 10:
        base_r_value = BLACK_R_NUM
        base_g_value = BLACK_G_NUM
        base_b_value = BLACK_B_NUM
    elif colorresetchoice_num == 11:
        base_r_value = GLAY_R_NUM
        base_g_value = GLAY_G_NUM
        base_b_value = GLAY_B_NUM
    elif colorresetchoice_num == 12:
        base_r_value = SKY_R_NUM
        base_g_value = SKY_G_NUM
        base_b_value = SKY_B_NUM
    elif colorresetchoice_num == 13:
        base_r_value = WHITE_R_NUM
        base_g_value = WHITE_G_NUM
        base_b_value = WHITE_B_NUM
    else:
        base_r_value, base_g_value, base_b_value = value_num_set(
            colorresetchoice_num - 14
        )

    if controlchoice_num == 1 or controlchoice_num == 3:
        ft_comboBackR.set(base_r_value)
        ft_comboBackG.set(base_g_value)
        ft_comboBackB.set(base_b_value)
    if controlchoice_num == 2 or controlchoice_num == 3:
        ft_comboFigureR.set(base_r_value)
        ft_comboFigureG.set(base_g_value)
        ft_comboFigureB.set(base_b_value)


"""
関数名 : value_num_set
引数 : num             色配列番号
機能:色を返却
作成日:2021/09/25
修正日:
"""


def value_num_set(num):
    base_r_value = _colorrgblist[num][0]
    base_g_value = _colorrgblist[num][1]
    base_b_value = _colorrgblist[num][2]

    return base_r_value, base_g_value, base_b_value


"""
関数名 : close_window
機能:終了
作成日:2021/09/25
修正日:
"""


def close_window():
    root.destroy()


"""
関数名 : dummy_def
機能:外に出して疑似的に非表示
作成日:2021/10/03
修正日:
"""


def dummy_def():
    # 外に出して疑似的に非表示にする
    rdo4.place(x=-100, y=0)


"""
関数名 : imgfile_make
機能:透かしを入れた画像を作成する
引数 fname :ファイルパス
作成日:2021/10/03
修正日:
"""


def imgfile_make(fname):
    #
    imgpath = os.path.abspath(fname)
    imgheadfilepath, imgext = os.path.splitext(imgpath)

    (
        comboBackR,
        comboBackG,
        comboBackB,
        comboFigureR,
        comboFigureG,
        comboFigureB,
    ) = get_colorvaluetocode()

    comboOpacity = int(ft_combo_opacity.get())

    # 画像を開いてサイズを調べる
    img = Image.open(fname)
    w, h = img.size
    # インスタグラムだと投稿時に画像が入りきらないことがあるため、縦横を3分の2に縮めた画像をメモリに持たせる (*2)
    resized_img = img.resize((int(w / 3 * 2), int(h / 3 * 2)))

    # 下地を白で 新しい画像オブジェクトを作成
    imgnew = Image.new("RGB", (w, h), (comboBackR, comboBackG, comboBackB))

    # 元画像をコピー、但し中央寄せにする
    imgnew.paste(resized_img, (int(w / 6), int(h / 6)))

    # 埋め込む文字の設定
    draw = ImageDraw.Draw(imgnew)

    # OSによって標準ディレクトリを決める
    # (Windowsで起動するか、Androidで起動するか)※現時点でFlask/Djangoでの実行は考慮保留
    if platform.system() == "Windows":
        basedirectory = os.path.dirname(os.path.abspath(sys.argv[0]).replace("\\", "/"))
    else:
        basedirectory = "/storage/emulated/0"

    font = ImageFont.truetype(
        basedirectory + "/fonts/GenJyuuGothic-Monospace-Normal.ttf", 200
    )

    # 撮影時刻を取得する
    imgshottime = get_shot(fname)
    dtpImgshottime = datetime.datetime.strptime(imgshottime, "%Y:%m:%d %H:%M:%S")
    dtfImgshottime = datetime.datetime.strftime(dtpImgshottime, "%Y-%m-%d %H:%M:%S")

    # # 1段目
    textcontents = "あいちのトミー 撮影 on "
    # 埋め込む文字の高さ・幅を取得する
    fontw, fonth = draw.textsize(textcontents, font)
    textleft = int(w / 3 * 2) + int(w / 6) - fontw - 1
    texttop = int(h / 3 * 2) + int(h / 6) - fonth * 2 - 6
    # draw.text((int(textleft),int(texttop)), textcontents ,(comboFigureR,comboFigureG,comboFigureB),font=font)
    # draw.text((int(textleft),int(texttop)), textcontents ,fill=((comboFigureR,comboFigureG,comboFigureB) + (_opacity,)),font=font)
    draw.text(
        (int(textleft), int(texttop)),
        textcontents,
        fill=((comboFigureR, comboFigureG, comboFigureB) + (comboOpacity,)),
        font=font,
    )

    # # 2段目
    textcontents = dtfImgshottime
    # 埋め込む文字の高さ・幅
    fontw, fonth = draw.textsize(textcontents, font)
    textleft = int(w / 3 * 2) + int(w / 6) - fontw - 1
    texttop = int(h / 3 * 2) + int(h / 6) - fonth - 5
    draw.text(
        (int(textleft), int(texttop)),
        textcontents,
        (comboFigureR, comboFigureG, comboFigureB),
        font=font,
    )

    # showはwindows起動の場合のみ
    imgnew.show()

    # 現在時刻(年月日時分秒を区切り記号無しで出力)
    nowtime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")

    # 透かし画像は別ディレクトリに別ファイルに保存
    #    imgnewfilepath = os.path.dirname(imgheadfilepath).replace('\\', '/') + '/out/'
    #    imgnewfilepath += os.path.splitext(os.path.basename(imgheadfilepath))[0] + "_" + nowtime + imgext
    #    print(imgnewfilepath)

    # 透かし画像は上ディレクトリに別ファイルとして保存
    os.chdir(os.path.dirname(imgheadfilepath).replace("\\", "/") + "/")
    os.chdir("../")

    # imgnewfilepath = os.path.dirname(imgheadfilepath).replace('\\', '/') + '/'
    imgnewfilepath = os.getcwd().replace("\\", "/") + "/"
    imgnewfilepath += (
        os.path.splitext(os.path.basename(imgheadfilepath))[0] + "_" + nowtime + imgext
    )
    print(imgnewfilepath)

    # 指定したファイルパスで保存
    imgnew.save(imgnewfilepath, "JPEG", quality=90)


"""
関数名 : button_process
機能:埋め込みボタン処理
作成日:2021/09/25
修正日:
"""


def button_process():
    # パスの設定
    if platform.system() == "Windows":
        basedirectory = os.path.dirname(os.path.abspath(sys.argv[0]).replace("\\", "/"))
        basepicdirectory = basedirectory
    else:
        basedirectory = "/storage/emulated/0"
        basepicdirectory = "/storage/emulated/0/DCIM/Camera/img"

    directorylist_direct = glob.glob(basepicdirectory + "/*.jpg", recursive=False)
    # 非活性化
    ft_make_button["state"] = tk.DISABLED

    i = 0
    for f in directorylist_direct:
        i += 1
        f = f.replace("\\", "/")
        # 透かしを入れた画像を作成のメイン処理を開始する
        imgfile_make(f)

    messageboxshow("完了", str(i) + "件処理しました。")
    # 非活性化
    ft_make_button["state"] = tk.NORMAL

"""
関数名 : button_colorchange
機能:カラーボタン処理
引数:
作成日:2022/06/10
修正日:
"""


def button_colorchange():
    (
        comboBackR,
        comboBackG,
        comboBackB,
        comboFigureR,
        comboFigureG,
        comboFigureB,
    ) = get_colorvaluetocode()

    # 背景色
    bgcolor = "#" + colornumtohex(comboBackR, comboBackG, comboBackB)
    ft_color_button["bg"] = bgcolor

    # 前景色
    fgcolor = "#" + colornumtohex(comboFigureR, comboFigureG, comboFigureB)
    ft_color_button["fg"] = fgcolor

    messageboxshow("完了", "処理しました。")


"""
関数名 : get_colorvaluetocode
機能:コンボボックスの値から色の数値を変数に格納
戻り値:背景色R、背景色G、背景色B、前景色R、前景色G、前景色B
作成日:2022/06/10
修正日:
"""


def get_colorvaluetocode():
    return (
        int(ft_comboBackR.get()),
        int(ft_comboBackG.get()),
        int(ft_comboBackB.get()),
        int(ft_comboFigureR.get()),
        int(ft_comboFigureG.get()),
        int(ft_comboFigureB.get()),
    )


"""
関数名 : from_rgb_to_colorcode
機能:RGB変換
引数 rgb :RGB値
作成日:2021/10/03
修正日:
"""


def from_rgb_to_colorcode(rgb):
    tup = tuple(rgb)
    print(tup)
    return "#%02x%02x%02x" % tup


"""
関数名 : from_rgb_to_colorcode
機能:EXIFから撮影時刻を取得する
引数 fname :ファイルパス
作成日:2021/10/03
修正日:
"""


def get_shot(fname):
    # 画像ファイルを開く
    im = Image.open(fname)
    print(fname)
    # EXIF情報を辞書型で得る
    exif = {ExifTags.TAGS[k]: v for k, v in im._getexif().items() if k in ExifTags.TAGS}
    # 撮影日時を得る
    shot_tags = exif["DateTimeOriginal"]

    return shot_tags


"""
関数名 : numwide
引数 : num                   半角数字
戻り値:全角化した数字
機能:半角数字を全角にする
作成日:2021/09/25
修正日:
"""


def numwide(num):
    if int(num) < 10:
        int_n = ord(str(int(num)))
        return chr((int_n) + 65248)
    else:
        return num


"""
関数名 : comboset
引数 : combo                 コンボボックス
        initialnum            初期値
        minnum                最小値
        maxnum                最大値
機能:コンボボックスの設定
作成日:2021/09/25
修正日:
"""


def comboset(combo, initialnum, minnum, maxnum):
    # combo = ttk.Combobox(root, width = 4, state='readonly',justify='right')
    # 選択肢設定
    combovalue = []

    # コンボボックスのスクロールバーの設定
    style = ttk.Style()
    style.theme_use("clam")
    style.configure(
        "Vertical.TScrollbar",
        gripcount=0,
        background="Blue",
        darkcolor="DarkGreen",
        lightcolor="LightGreen",
        troughcolor="gray",
        bordercolor="aqua",
        arrowcolor="white",
    )

    for num in range(minnum, maxnum + 1):
        combovalue.append(numwide(num))

    combo["values"] = combovalue
    combo.current(initialnum)
    combo.pack()

"""
関数名 : colornumtohex
引数 :intR 赤
       intG 緑
       intB 青
機能:10進数RGBを指定して16進数表記に変える
作成日:2022/01/22
修正日:
"""
def colornumtohex(intR , intG , intB):
    if 0 <= intR <= 255 and 0 <= intG <= 255 and 0 <= intB <= 255:
        return ('{:X}{:X}{:X}').format(intR, intG, intB)
    else:
        return ""

"""
関数名 : __main__
機能:メイン
作成日:2021/09/25
修正日:
"""
if __name__ == "__main__":
    # tkinter初期化
    root = tk.Tk()

    root.title("文字埋め込み")
    # 以下のサイズで設定
    if platform.system() == "Windows":
        root.geometry("1000x600+100+20")
        combowidth = 4
    else:
        # pydroid3での実行はサイズ指定は意味ないのでダミー値
        root.geometry("250x250")
        combowidth = 6
    # フォームサイズを固定する
    root.resizable(width=False, height=False)
    # 背景色の設定
    root.configure(bg="lightgray")
    style = ttk.Style()
    style.configure("BW.TCombobox", foreground="black", background="lightgray")

    ft_comboBackR = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboBackG = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboBackB = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboFigureR = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboFigureG = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboFigureB = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_combo_opacity = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )

    comboset(ft_comboBackR, 255, 0, 255)
    comboset(ft_comboBackG, 255, 0, 255)
    comboset(ft_comboBackB, 255, 0, 255)
    comboset(ft_comboFigureR, 0, 0, 255)
    comboset(ft_comboFigureG, 0, 0, 255)
    comboset(ft_comboFigureB, 0, 0, 255)
    comboset(ft_combo_opacity, 80, 5, 100)

    # ラジオボタンの作成
    # # グループの設定
    controlchoice = tk.IntVar()
    # # 初期チェックをvalueに指定した値のラジオボタンとする
    controlchoice.set(2)

    # # グループの設定
    # # 初期チェックをvalueに指定した値のラジオボタンとする
    colorresetchoice = tk.IntVar()
    colorresetchoice.set(10)
    # 対象
    rdo1 = tk.Radiobutton(value=1, variable=controlchoice, text="枠背景色")
    rdo2 = tk.Radiobutton(value=2, variable=controlchoice, text="文字色")
    rdo3 = tk.Radiobutton(value=3, variable=controlchoice, text="両方")
    # 色
    rdo4 = tk.Radiobutton(
        root,
        value=10,
        variable=colorresetchoice,
        text="黒",
        fg="black",
        bg=from_rgb_to_colorcode((100, 100, 100)),
    )
    rdo5 = tk.Radiobutton(
        root,
        value=11,
        variable=colorresetchoice,
        text="灰",
        fg="black",
        bg=from_rgb_to_colorcode((128, 128, 128)),
    )
    rdo6 = tk.Radiobutton(
        root,
        value=12,
        variable=colorresetchoice,
        text="空",
        fg="black",
        bg=from_rgb_to_colorcode((137, 189, 222)),
    )
    rdo7 = tk.Radiobutton(
        root, value=13, variable=colorresetchoice, text="白", fg="black", bg="white"
    )

    rdolist = []

    for i in range(len(_colorlist)):
        colorvalue = from_rgb_to_colorcode(_colorrgblist[i])
        rdo = tk.Radiobutton(
            root,
            value=14 + i,
            variable=colorresetchoice,
            text=_colorlist[i],
            bg=colorvalue,
        )
        rdolist.append(rdo)

    # ボタンの作成
    ft_make_button = tk.Button(  # 「 埋め込み 」ボタンの作成
        text="埋め込み",
        width=10,
        height=2,
        background="gray",
        command=button_process,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_reset_button = tk.Button(  # 「 色リセット 」ボタンの作成
        text="色リセット",
        width=10,
        height=2,
        background="gray",
        command=value_reset,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_color_button = tk.Button(  # 「 カラー 」ボタンの作成
        text="カラー(背)",
        width=10,
        height=2,
        background="gray",
        command=button_colorchange,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_close_button = tk.Button(  # 「 ウィンドウ終了 」ボタンの作成
        text="ウィンドウ終了",
        width=10,
        height=2,
        background="gray",
        command=close_window,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_dummy_button = tk.Button(  # 「 非表示 」ボタンの作成
        text="非表示",
        width=10,
        height=2,
        background="gray",
        command=dummy_def,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_dummy2_button = tk.Button(  # 「 再表示 」ボタンの作成
        text="再表示",
        width=10,
        height=2,
        background="gray",
        command=lambda: rdo4.place(x=10, y=220),  # ボタンのクリック時に呼ばれる関数を指定
    )
    # command = lambda: controlchoice.set(2) # ボタンのクリック時に呼ばれる関数を指定

    # ラベル
    label_back = tk.Entry(width=10, foreground="blue", background="white")
    label_figure = tk.Entry(width=10, foreground="blue", background="white")
    label_opacity = tk.Entry(width=10, foreground="blue", background="white")
    # 内容置換
    label_back.insert(0, "枠背景色")
    label_figure.insert(0, "文字色")
    label_opacity.insert(0, "透明度")
    # 非活性
    label_back.configure(state="disabled")
    label_figure.configure(state="disabled")
    label_opacity.configure(state="disabled")

    # 位置の設定
    intYPos = 0
    if platform.system() == "Windows":
        intYPos = 30
        label_back.place(x=10, y=intYPos)
        intYPos += 20
        ft_comboBackR.place(x=10, y=intYPos)
        ft_comboBackG.place(x=60, y=intYPos)
        ft_comboBackB.place(x=110, y=intYPos)
        intYPos += 30
        label_figure.place(x=10, y=intYPos)
        intYPos += 20
        ft_comboFigureR.place(x=10, y=intYPos)
        ft_comboFigureG.place(x=60, y=intYPos)
        ft_comboFigureB.place(x=110, y=intYPos)
        intYPos += 30
        label_opacity.place(x=10, y=intYPos)
        intYPos += 20
        ft_combo_opacity.place(x=10, y=intYPos)
        intYPos += 40

         # TODO:追加中


        intYPos += 50
        rdo1.place(x=10, y=intYPos)
        rdo2.place(x=100, y=intYPos)
        rdo3.place(x=180, y=intYPos)
        intYPos += 30
        rdo4.place(x=10, y=intYPos)
        rdo5.place(x=50, y=intYPos)
        rdo6.place(x=90, y=intYPos)
        rdo7.place(x=130, y=intYPos)
        intYPos += 35
        for i, r in enumerate(rdolist):
            intYNextPos = intYPos + (i // 5) * 30
            r.place(x=10 + (i % 5) * 50, y=intYNextPos)
            intYNextPos += 35
        ft_make_button.place(x=10, y=intYNextPos)
        ft_reset_button.place(x=100, y=intYNextPos)
        ft_color_button.place(x=190, y=intYNextPos)
        ft_close_button.place(x=280, y=intYNextPos)

        # 画像ロード(検証中)
        # imgpathlist = [r"t:\Edion.jpg", r"t:\twitter.jpg"]
        # imgs = []  # Imageを保持するリストを追加
        # # imgpathlist = [r"t:\Edion.jpg"]
        # for i, path in enumerate(imgpathlist):
        #     image = Image.open(path)

        #     intYNextPos += 50
        #     # サイズ縮小
        #     w_size = int(image.width / 4)
        #     h_size = int(image.height / 4)

        #     imgs.append(image)
        #     # # キャンバス作成
        #     canvas = tk.Canvas(width=w_size, height=h_size)
        #     # # PhotoImage変換
        #     tk_image = ImageTk.PhotoImage(image=image.resize((w_size, h_size)))
        #     # # 画像描画
        #     canvas.create_image(0, 0, anchor="nw", image=tk_image)

        #     # # キャンバス表示
        #     canvas.place(x=0, y=intYNextPos)

    else:
        intYPos = 10
        label_back.place(x=100, y=intYPos)
        intYPos = 90
        ft_comboBackR.place(x=100, y=intYPos)
        ft_comboBackG.place(x=350, y=intYPos)
        ft_comboBackB.place(x=600, y=intYPos)
        intYPos = 170
        label_figure.place(x=100, y=intYPos)
        intYPos = 250
        ft_comboFigureR.place(x=100, y=intYPos)
        ft_comboFigureG.place(x=350, y=intYPos)
        ft_comboFigureB.place(x=600, y=intYPos)
        intYPos = 340
        label_opacity.place(x=100, y=intYPos)
        intYPos = 410
        ft_combo_opacity.place(x=100, y=intYPos)

        intYPos = 480
        rdo1.place(x=100, y=intYPos)
        rdo2.place(x=400, y=intYPos)
        rdo3.place(x=700, y=intYPos)
        intYPos = 580
        rdo4.place(x=100, y=intYPos)
        rdo5.place(x=300, y=intYPos)
        rdo6.place(x=500, y=intYPos)
        rdo7.place(x=700, y=intYPos)
        intYPos += 70

        for i, r in enumerate(rdolist):
            intYNextPos = intYPos + (i // 5) * 70
            r.place(x=100 + (i % 5) * 200, y=intYNextPos)
            print(intYNextPos)

        intYPos = intYNextPos + 70
        ft_make_button.place(x=100, y=intYPos)
        intYPos += 150
        ft_reset_button.place(x=100, y=intYPos)
        intYPos += 150
        ft_color_button.place(x=100, y=intYPos)
        intYPos += 150
        ft_close_button.place(x=100, y=intYPos)


    # フォーム初期起動
    root.mainloop()


# -*- coding: utf-8 -*-
"""
  スクリプト名 : tkinterpiccolor.py
  処理内容:tkinterでコンボボックスの設定サンプル
  対応:pydroid3対応 Macは非対応?
  補足:Harigami上での実行は不可
"""
from logging import shutdown
from tkinter import *
import tkinter as tk
import tkinter.ttk as ttk

import datetime
import os, sys, platform
import glob
from PIL import Image, ImageDraw, ImageFont
import PIL.ExifTags as ExifTags
from PIL import Image, ImageTk

# メッセージボックス
from tkinter import messagebox

# 自作ライブラリ
import usefully

# 透かし文字の透明度
_opacity = 70
_colorlist = ["桃", "橙", "紫", "黄緑", "黄", "桜"]
_colorrgblist = [
    [240, 145, 153],
    [238, 120, 0],
    [136, 72, 152],
    [188, 226, 91],
    [255, 217, 0],
    [254, 244, 244],
]
"""
_colorlist  = ['桃','橙','紫','水','黄','桜','茶','鼠','黄緑','金']
_colorrgblist = [[240,145,153],[238,120,0],
                    [136,72,152],[188,226,91],
                    [255,217,0],[0,0,0],
                    [0,0,0],[0,0,0],
                    [0,0,0],[0,0,0]]
"""

"""
関数名 : messageboxshow
引数 : title                   タイトル
        message                 メッセージ
機能:メッセージボックス表示
作成日:2021/09/25
修正日:
"""


def messageboxshow(title, message):
    messagebox.showinfo(title, message)


"""
関数名 : value_reset
機能:色リセット
作成日:2021/10/03
修正日:
"""


def value_reset():

    # 定数
    BLACK_R_NUM = 0
    BLACK_G_NUM = 0
    BLACK_B_NUM = 0
    GLAY_R_NUM = 128
    GLAY_G_NUM = 128
    GLAY_B_NUM = 128
    SKY_R_NUM = 137
    SKY_G_NUM = 189
    SKY_B_NUM = 222
    WHITE_R_NUM = 255
    WHITE_G_NUM = 255
    WHITE_B_NUM = 255

    # 切替コントロール
    controlchoice_num = controlchoice.get()
    # 色
    colorresetchoice_num = colorresetchoice.get()

    if colorresetchoice_num == 10:
        base_r_value = BLACK_R_NUM
        base_g_value = BLACK_G_NUM
        base_b_value = BLACK_B_NUM
    elif colorresetchoice_num == 11:
        base_r_value = GLAY_R_NUM
        base_g_value = GLAY_G_NUM
        base_b_value = GLAY_B_NUM
    elif colorresetchoice_num == 12:
        base_r_value = SKY_R_NUM
        base_g_value = SKY_G_NUM
        base_b_value = SKY_B_NUM
    elif colorresetchoice_num == 13:
        base_r_value = WHITE_R_NUM
        base_g_value = WHITE_G_NUM
        base_b_value = WHITE_B_NUM
    else:
        base_r_value, base_g_value, base_b_value = value_num_set(
            colorresetchoice_num - 14
        )

    if controlchoice_num == 1 or controlchoice_num == 3:
        ft_comboBackR.set(base_r_value)
        ft_comboBackG.set(base_g_value)
        ft_comboBackB.set(base_b_value)
    if controlchoice_num == 2 or controlchoice_num == 3:
        ft_comboFigureR.set(base_r_value)
        ft_comboFigureG.set(base_g_value)
        ft_comboFigureB.set(base_b_value)


"""
関数名 : value_num_set
引数 : num             色配列番号
機能:色を返却
作成日:2021/09/25
修正日:
"""


def value_num_set(num):
    base_r_value = _colorrgblist[num][0]
    base_g_value = _colorrgblist[num][1]
    base_b_value = _colorrgblist[num][2]

    return base_r_value, base_g_value, base_b_value


"""
関数名 : close_window
機能:終了
作成日:2021/09/25
修正日:
"""


def close_window():
    root.destroy()


"""
関数名 : dummy_def
機能:外に出して疑似的に非表示
作成日:2021/10/03
修正日:
"""


def dummy_def():
    # 外に出して疑似的に非表示にする
    rdo4.place(x=-100, y=0)


"""
関数名 : imgfile_make
機能:透かしを入れた画像を作成する
引数 fname :ファイルパス
作成日:2021/10/03
修正日:
"""


def imgfile_make(fname):
    #
    imgpath = os.path.abspath(fname)
    imgheadfilepath, imgext = os.path.splitext(imgpath)

    (
        comboBackR,
        comboBackG,
        comboBackB,
        comboFigureR,
        comboFigureG,
        comboFigureB,
    ) = get_colorvaluetocode()

    comboOpacity = int(ft_combo_opacity.get())

    # 画像を開いてサイズを調べる
    img = Image.open(fname)
    w, h = img.size
    # インスタグラムだと投稿時に画像が入りきらないことがあるため、縦横を3分の2に縮めた画像をメモリに持たせる (*2)
    resized_img = img.resize((int(w / 3 * 2), int(h / 3 * 2)))

    # 下地を白で 新しい画像オブジェクトを作成
    imgnew = Image.new("RGB", (w, h), (comboBackR, comboBackG, comboBackB))

    # 元画像をコピー、但し中央寄せにする
    imgnew.paste(resized_img, (int(w / 6), int(h / 6)))

    # 埋め込む文字の設定
    draw = ImageDraw.Draw(imgnew)

    # OSによって標準ディレクトリを決める
    # (Windowsで起動するか、Androidで起動するか)※現時点でFlask/Djangoでの実行は考慮保留
    if platform.system() == "Windows":
        basedirectory = os.path.dirname(os.path.abspath(sys.argv[0]).replace("\\", "/"))
    else:
        basedirectory = "/storage/emulated/0"

    font = ImageFont.truetype(
        basedirectory + "/fonts/GenJyuuGothic-Monospace-Normal.ttf", 200
    )

    # 撮影時刻を取得する
    imgshottime = get_shot(fname)
    dtpImgshottime = datetime.datetime.strptime(imgshottime, "%Y:%m:%d %H:%M:%S")
    dtfImgshottime = datetime.datetime.strftime(dtpImgshottime, "%Y-%m-%d %H:%M:%S")

    # # 1段目
    textcontents = "あいちのトミー 撮影 on "
    # 埋め込む文字の高さ・幅を取得する
    fontw, fonth = draw.textsize(textcontents, font)
    textleft = int(w / 3 * 2) + int(w / 6) - fontw - 1
    texttop = int(h / 3 * 2) + int(h / 6) - fonth * 2 - 6
    # draw.text((int(textleft),int(texttop)), textcontents ,(comboFigureR,comboFigureG,comboFigureB),font=font)
    # draw.text((int(textleft),int(texttop)), textcontents ,fill=((comboFigureR,comboFigureG,comboFigureB) + (_opacity,)),font=font)
    draw.text(
        (int(textleft), int(texttop)),
        textcontents,
        fill=((comboFigureR, comboFigureG, comboFigureB) + (comboOpacity,)),
        font=font,
    )

    # # 2段目
    textcontents = dtfImgshottime
    # 埋め込む文字の高さ・幅
    fontw, fonth = draw.textsize(textcontents, font)
    textleft = int(w / 3 * 2) + int(w / 6) - fontw - 1
    texttop = int(h / 3 * 2) + int(h / 6) - fonth - 5
    draw.text(
        (int(textleft), int(texttop)),
        textcontents,
        (comboFigureR, comboFigureG, comboFigureB),
        font=font,
    )

    # showはwindows起動の場合のみ
    imgnew.show()

    # 現在時刻(年月日時分秒を区切り記号無しで出力)
    nowtime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")

    # 透かし画像は別ディレクトリに別ファイルに保存
    #    imgnewfilepath = os.path.dirname(imgheadfilepath).replace('\\', '/') + '/out/'
    #    imgnewfilepath += os.path.splitext(os.path.basename(imgheadfilepath))[0] + "_" + nowtime + imgext
    #    print(imgnewfilepath)

    # 透かし画像は上ディレクトリに別ファイルとして保存
    os.chdir(os.path.dirname(imgheadfilepath).replace("\\", "/") + "/")
    os.chdir("../")

    # imgnewfilepath = os.path.dirname(imgheadfilepath).replace('\\', '/') + '/'
    imgnewfilepath = os.getcwd().replace("\\", "/") + "/"
    imgnewfilepath += (
        os.path.splitext(os.path.basename(imgheadfilepath))[0] + "_" + nowtime + imgext
    )
    print(imgnewfilepath)

    # 指定したファイルパスで保存
    imgnew.save(imgnewfilepath, "JPEG", quality=90)


"""
関数名 : button_process
機能:埋め込みボタン処理
作成日:2021/09/25
修正日:
"""


def button_process():
    # パスの設定
    if platform.system() == "Windows":
        basedirectory = os.path.dirname(os.path.abspath(sys.argv[0]).replace("\\", "/"))
        basepicdirectory = basedirectory
    else:
        basedirectory = "/storage/emulated/0"
        basepicdirectory = "/storage/emulated/0/DCIM/Camera/img"

    directorylist_direct = glob.glob(basepicdirectory + "/*.jpg", recursive=False)
    # 非活性化
    ft_make_button["state"] = tk.DISABLED

    i = 0
    for f in directorylist_direct:
        i += 1
        f = f.replace("\\", "/")
        # 透かしを入れた画像を作成のメイン処理を開始する
        imgfile_make(f)

    messageboxshow("完了", str(i) + "件処理しました。")
    # 非活性化
    ft_make_button["state"] = tk.NORMAL

"""
関数名 : button_colorchange
機能:カラーボタン処理
引数:
作成日:2022/06/10
修正日:
"""


def button_colorchange():
    (
        comboBackR,
        comboBackG,
        comboBackB,
        comboFigureR,
        comboFigureG,
        comboFigureB,
    ) = get_colorvaluetocode()

    # 背景色
    bgcolor = "#" + colornumtohex(comboBackR, comboBackG, comboBackB)
    ft_color_button["bg"] = bgcolor

    # 前景色
    fgcolor = "#" + colornumtohex(comboFigureR, comboFigureG, comboFigureB)
    ft_color_button["fg"] = fgcolor

    messageboxshow("完了", "処理しました。")


"""
関数名 : get_colorvaluetocode
機能:コンボボックスの値から色の数値を変数に格納
戻り値:背景色R、背景色G、背景色B、前景色R、前景色G、前景色B
作成日:2022/06/10
修正日:
"""


def get_colorvaluetocode():
    return (
        int(ft_comboBackR.get()),
        int(ft_comboBackG.get()),
        int(ft_comboBackB.get()),
        int(ft_comboFigureR.get()),
        int(ft_comboFigureG.get()),
        int(ft_comboFigureB.get()),
    )


"""
関数名 : from_rgb_to_colorcode
機能:RGB変換
引数 rgb :RGB値
作成日:2021/10/03
修正日:
"""


def from_rgb_to_colorcode(rgb):
    tup = tuple(rgb)
    print(tup)
    return "#%02x%02x%02x" % tup


"""
関数名 : from_rgb_to_colorcode
機能:EXIFから撮影時刻を取得する
引数 fname :ファイルパス
作成日:2021/10/03
修正日:
"""


def get_shot(fname):
    # 画像ファイルを開く
    im = Image.open(fname)
    print(fname)
    # EXIF情報を辞書型で得る
    exif = {ExifTags.TAGS[k]: v for k, v in im._getexif().items() if k in ExifTags.TAGS}
    # 撮影日時を得る
    shot_tags = exif["DateTimeOriginal"]

    return shot_tags


"""
関数名 : numwide
引数 : num                   半角数字
戻り値:全角化した数字
機能:半角数字を全角にする
作成日:2021/09/25
修正日:
"""


def numwide(num):
    if int(num) < 10:
        int_n = ord(str(int(num)))
        return chr((int_n) + 65248)
    else:
        return num


"""
関数名 : comboset
引数 : combo                 コンボボックス
        initialnum            初期値
        minnum                最小値
        maxnum                最大値
機能:コンボボックスの設定
作成日:2021/09/25
修正日:
"""


def comboset(combo, initialnum, minnum, maxnum):
    # combo = ttk.Combobox(root, width = 4, state='readonly',justify='right')
    # 選択肢設定
    combovalue = []

    # コンボボックスのスクロールバーの設定
    style = ttk.Style()
    style.theme_use("clam")
    style.configure(
        "Vertical.TScrollbar",
        gripcount=0,
        background="Blue",
        darkcolor="DarkGreen",
        lightcolor="LightGreen",
        troughcolor="gray",
        bordercolor="aqua",
        arrowcolor="white",
    )

    for num in range(minnum, maxnum + 1):
        combovalue.append(numwide(num))

    combo["values"] = combovalue
    combo.current(initialnum)
    combo.pack()

"""
関数名 : colornumtohex
引数 :intR 赤
       intG 緑
       intB 青
機能:10進数RGBを指定して16進数表記に変える
作成日:2022/01/22
修正日:
"""
def colornumtohex(intR , intG , intB):
    if 0 <= intR <= 255 and 0 <= intG <= 255 and 0 <= intB <= 255:
        return ('{:X}{:X}{:X}').format(intR, intG, intB)
    else:
        return ""

"""
関数名 : __main__
機能:メイン
作成日:2021/09/25
修正日:
"""
if __name__ == "__main__":
    # tkinter初期化
    root = tk.Tk()

    root.title("文字埋め込み")
    # 以下のサイズで設定
    if platform.system() == "Windows":
        root.geometry("1000x600+100+20")
        combowidth = 4
    else:
        # pydroid3での実行はサイズ指定は意味ないのでダミー値
        root.geometry("250x250")
        combowidth = 6
    # フォームサイズを固定する
    root.resizable(width=False, height=False)
    # 背景色の設定
    root.configure(bg="lightgray")
    style = ttk.Style()
    style.configure("BW.TCombobox", foreground="black", background="lightgray")

    ft_comboBackR = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboBackG = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboBackB = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboFigureR = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboFigureG = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_comboFigureB = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )
    ft_combo_opacity = ttk.Combobox(
        root, width=combowidth, state="readonly", justify="right"
    )

    comboset(ft_comboBackR, 255, 0, 255)
    comboset(ft_comboBackG, 255, 0, 255)
    comboset(ft_comboBackB, 255, 0, 255)
    comboset(ft_comboFigureR, 0, 0, 255)
    comboset(ft_comboFigureG, 0, 0, 255)
    comboset(ft_comboFigureB, 0, 0, 255)
    comboset(ft_combo_opacity, 80, 5, 100)

    # ラジオボタンの作成
    # # グループの設定
    controlchoice = tk.IntVar()
    # # 初期チェックをvalueに指定した値のラジオボタンとする
    controlchoice.set(2)

    # # グループの設定
    # # 初期チェックをvalueに指定した値のラジオボタンとする
    colorresetchoice = tk.IntVar()
    colorresetchoice.set(10)
    # 対象
    rdo1 = tk.Radiobutton(value=1, variable=controlchoice, text="枠背景色")
    rdo2 = tk.Radiobutton(value=2, variable=controlchoice, text="文字色")
    rdo3 = tk.Radiobutton(value=3, variable=controlchoice, text="両方")
    # 色
    rdo4 = tk.Radiobutton(
        root,
        value=10,
        variable=colorresetchoice,
        text="黒",
        fg="black",
        bg=from_rgb_to_colorcode((100, 100, 100)),
    )
    rdo5 = tk.Radiobutton(
        root,
        value=11,
        variable=colorresetchoice,
        text="灰",
        fg="black",
        bg=from_rgb_to_colorcode((128, 128, 128)),
    )
    rdo6 = tk.Radiobutton(
        root,
        value=12,
        variable=colorresetchoice,
        text="空",
        fg="black",
        bg=from_rgb_to_colorcode((137, 189, 222)),
    )
    rdo7 = tk.Radiobutton(
        root, value=13, variable=colorresetchoice, text="白", fg="black", bg="white"
    )

    rdolist = []

    for i in range(len(_colorlist)):
        colorvalue = from_rgb_to_colorcode(_colorrgblist[i])
        rdo = tk.Radiobutton(
            root,
            value=14 + i,
            variable=colorresetchoice,
            text=_colorlist[i],
            bg=colorvalue,
        )
        rdolist.append(rdo)

    # ボタンの作成
    ft_make_button = tk.Button(  # 「 埋め込み 」ボタンの作成
        text="埋め込み",
        width=10,
        height=2,
        background="gray",
        command=button_process,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_reset_button = tk.Button(  # 「 色リセット 」ボタンの作成
        text="色リセット",
        width=10,
        height=2,
        background="gray",
        command=value_reset,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_color_button = tk.Button(  # 「 カラー 」ボタンの作成
        text="カラー(背)",
        width=10,
        height=2,
        background="gray",
        command=button_colorchange,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_close_button = tk.Button(  # 「 ウィンドウ終了 」ボタンの作成
        text="ウィンドウ終了",
        width=10,
        height=2,
        background="gray",
        command=close_window,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_dummy_button = tk.Button(  # 「 非表示 」ボタンの作成
        text="非表示",
        width=10,
        height=2,
        background="gray",
        command=dummy_def,  # ボタンのクリック時に呼ばれる関数を指定
    )
    ft_dummy2_button = tk.Button(  # 「 再表示 」ボタンの作成
        text="再表示",
        width=10,
        height=2,
        background="gray",
        command=lambda: rdo4.place(x=10, y=220),  # ボタンのクリック時に呼ばれる関数を指定
    )
    # command = lambda: controlchoice.set(2) # ボタンのクリック時に呼ばれる関数を指定

    # ラベル
    label_back = tk.Entry(width=10, foreground="blue", background="white")
    label_figure = tk.Entry(width=10, foreground="blue", background="white")
    label_opacity = tk.Entry(width=10, foreground="blue", background="white")
    # 内容置換
    label_back.insert(0, "枠背景色")
    label_figure.insert(0, "文字色")
    label_opacity.insert(0, "透明度")
    # 非活性
    label_back.configure(state="disabled")
    label_figure.configure(state="disabled")
    label_opacity.configure(state="disabled")

    # 位置の設定
    intYPos = 0
    if platform.system() == "Windows":
        intYPos = 30
        label_back.place(x=10, y=intYPos)
        intYPos += 20
        ft_comboBackR.place(x=10, y=intYPos)
        ft_comboBackG.place(x=60, y=intYPos)
        ft_comboBackB.place(x=110, y=intYPos)
        intYPos += 30
        label_figure.place(x=10, y=intYPos)
        intYPos += 20
        ft_comboFigureR.place(x=10, y=intYPos)
        ft_comboFigureG.place(x=60, y=intYPos)
        ft_comboFigureB.place(x=110, y=intYPos)
        intYPos += 30
        label_opacity.place(x=10, y=intYPos)
        intYPos += 20
        ft_combo_opacity.place(x=10, y=intYPos)
        intYPos += 40

         # TODO:追加中


        intYPos += 50
        rdo1.place(x=10, y=intYPos)
        rdo2.place(x=100, y=intYPos)
        rdo3.place(x=180, y=intYPos)
        intYPos += 30
        rdo4.place(x=10, y=intYPos)
        rdo5.place(x=50, y=intYPos)
        rdo6.place(x=90, y=intYPos)
        rdo7.place(x=130, y=intYPos)
        intYPos += 35
        for i, r in enumerate(rdolist):
            intYNextPos = intYPos + (i // 5) * 30
            r.place(x=10 + (i % 5) * 50, y=intYNextPos)
            intYNextPos += 35
        ft_make_button.place(x=10, y=intYNextPos)
        ft_reset_button.place(x=100, y=intYNextPos)
        ft_color_button.place(x=190, y=intYNextPos)
        ft_close_button.place(x=280, y=intYNextPos)

        # 画像ロード(検証中)
        # imgpathlist = [r"t:\Edion.jpg", r"t:\twitter.jpg"]
        # imgs = []  # Imageを保持するリストを追加
        # # imgpathlist = [r"t:\Edion.jpg"]
        # for i, path in enumerate(imgpathlist):
        #     image = Image.open(path)

        #     intYNextPos += 50
        #     # サイズ縮小
        #     w_size = int(image.width / 4)
        #     h_size = int(image.height / 4)

        #     imgs.append(image)
        #     # # キャンバス作成
        #     canvas = tk.Canvas(width=w_size, height=h_size)
        #     # # PhotoImage変換
        #     tk_image = ImageTk.PhotoImage(image=image.resize((w_size, h_size)))
        #     # # 画像描画
        #     canvas.create_image(0, 0, anchor="nw", image=tk_image)

        #     # # キャンバス表示
        #     canvas.place(x=0, y=intYNextPos)

    else:
        intYPos = 10
        label_back.place(x=100, y=intYPos)
        intYPos = 90
        ft_comboBackR.place(x=100, y=intYPos)
        ft_comboBackG.place(x=350, y=intYPos)
        ft_comboBackB.place(x=600, y=intYPos)
        intYPos = 170
        label_figure.place(x=100, y=intYPos)
        intYPos = 250
        ft_comboFigureR.place(x=100, y=intYPos)
        ft_comboFigureG.place(x=350, y=intYPos)
        ft_comboFigureB.place(x=600, y=intYPos)
        intYPos = 340
        label_opacity.place(x=100, y=intYPos)
        intYPos = 410
        ft_combo_opacity.place(x=100, y=intYPos)

        intYPos = 480
        rdo1.place(x=100, y=intYPos)
        rdo2.place(x=400, y=intYPos)
        rdo3.place(x=700, y=intYPos)
        intYPos = 580
        rdo4.place(x=100, y=intYPos)
        rdo5.place(x=300, y=intYPos)
        rdo6.place(x=500, y=intYPos)
        rdo7.place(x=700, y=intYPos)
        intYPos += 70

        for i, r in enumerate(rdolist):
            intYNextPos = intYPos + (i // 5) * 70
            r.place(x=100 + (i % 5) * 200, y=intYNextPos)
            print(intYNextPos)

        intYPos = intYNextPos + 70
        ft_make_button.place(x=100, y=intYPos)
        intYPos += 150
        ft_reset_button.place(x=100, y=intYPos)
        intYPos += 150
        ft_color_button.place(x=100, y=intYPos)
        intYPos += 150
        ft_close_button.place(x=100, y=intYPos)


    # フォーム初期起動
    root.mainloop()


TKInterで画像に枠で囲んで著作権みたいな文字を入れる

Harigami上での実行は不可
No one still commented. Please first comment.
Output