Gitで整理!画像を200KB圧縮+コピーライト追加【第3回:ファイル名から日付情報取得】

当ページのリンクには広告が含まれています。

これまでの記事では、Pythonで作成した画像加工スクリプトをGitで管理するために、第1回:リポジトリの構成、第2回:圧縮モジュールについて紹介しました。

今回はその続編として、ファイル名から日付情報取得の処理にフォーカスします。
本モジュールでは、ファイル名に `”YYYY年MM月DD日”` 形式の撮影日が含まれていることを前提とし、含まれない場合は実行時の日付を返す仕様としています。

このように処理を1つのモジュールとして分離しておくことで、以下のメリットがあります。

  • 再利用性の向上:日付抽出処理を他の画像加工スクリプトや別プロジェクトでも使い回せる  
  • 保守性の向上:日付抽出ロジックを修正する場合も、このモジュールだけを変更すれば全体に反映される  
  • テスト容易性:単機能モジュールのため、単体テストがしやすく、不具合の原因切り分けも容易

今回も、Gitでのコード管理を前提に、モジュールごと・関数単位で整理し、将来的な拡張や修正に強い構成にしています。

目次

1.|プログラム全体説明:画像を200KB圧縮+コピーライト追加

当連載で最終的に作成するプログラムについて説明します。
当記事の内容は、STEP2における①〜③の箇所に使用するモジュールとなります。

プログラムの目的

前提条件

  • 入力ファイル名は、基本的に “YYYY年MM月DD日_任意の文字列.拡張子” の形式で撮影日が含まれていることを想定しています。
  • 日付が含まれない場合は、現在日付(実行日)を “YYYY年MM月DD日” 形式で返します。

JPEG画像を以下の処理で一括加工し、ブログ用に最適化された画像を作成する:
• 横幅を1200pxにリサイズ
• 目標サイズ(200KB)以下に圧縮
• ファイル名から日付を取得し、コピーライト付きテキストを画像に追加

プログラムの動作(処理の流れ)

STEP
指定フォルダ内の .jpeg 画像をすべて取得
STEP
各画像について以下を実行
  • ファイル名を取得して、保存用の出力パスを作成
  • 横幅を1200pxにリサイズし、一時保存
  • 200KB以下になるように品質を調整して圧縮保存
  • 「日付+©ふくゆー」のテキストを画像右下に追加(黒背景+白文字)
STEP
加工済み画像を「compress_元のファイル名.jpg」の形式でoutput_imagesフォルダに保存

main.py

当プログラムのmain.py全文です。:

import os
from utils.compress import compress_and_resize_jpeg, compress_image_to_target_size
from utils.add_text import add_text_with_background
from utils.date_utils import extract_photo_date_from_filename
from config.config import quality, width, target_size_kb, image_file_dir, save_dir, font_path  # ← 設定をインポート

# 出力ディレクトリがなければ作成
os.makedirs(save_dir, exist_ok=True)

# 入力フォルダ内のJPEG画像を順に処理
for filename in os.listdir(image_file_dir):
    if filename.lower().endswith((".jpg", ".jpeg")):
        input_path = os.path.join(image_file_dir, filename)
        print(f"処理対象: {filename}")

        base_name = os.path.splitext(filename)[0]
        output_filename = f"compress_{base_name}.jpg"
        output_path = os.path.join(save_dir, output_filename)

        # Step 1: リサイズ+Exif除去処理(品質95で一時保存)
        temp_path = output_path + ".temp.jpg"
        print("▶ Step 1: リサイズ+Exif除去")
        compress_and_resize_jpeg(input_path, temp_path, quality=95, width=width)

        if os.path.exists(temp_path):
            size_kb = os.path.getsize(temp_path) / 1024
            print(f"初期サイズ: {size_kb:.2f} KB")

        # Step 2: 目標サイズ以下に再圧縮
        print("▶ Step 2: サイズ調整(目標: {} KB)".format(target_size_kb))
        compress_image_to_target_size(temp_path, output_path, target_size_kb=target_size_kb)

        # Step 3: 画像に日付+著作権テキストを追加
        if os.path.exists(output_path):
            photo_date = extract_photo_date_from_filename(filename)
            text = f"{photo_date} ©ふくゆー"
            print("▶ Step 3: テキスト追加")
            add_text_with_background(output_path, output_path, text, font_path)

            final_size_kb = os.path.getsize(output_path) / 1024
            print(f"最終サイズ: {final_size_kb:.2f} KB")
            print("-" * 40)

        # Step 4: 一時ファイルを削除
        if os.path.exists(temp_path):
            os.remove(temp_path)

print("✅ 全処理完了")

当記事では、main.pyにおけるSTEP3内の関数:extract_photo_date_from_filename(filename)について解説しています。

2.|date_utils.pyについて解説

ここからは、本プログラム内で撮影日を取得する役割を担う **`date_utils.py`** について、構成や処理の流れを詳しく見ていきます。

2-1.|date_utils.pyの構成

このプログラムは、「ファイル名から撮影日(YYYY年MM月DD日)を取り出す」ことに特化した単機能モジュールです。
本体関数+動作確認用の if-main で構成されています。

関数名役割
extract_photo_date_from_filename(filename)ファイル名から YYYY年MM月DD日 形式を正規表現で抽出します。条件に一致する文字列が含まれない場合は、現在日付を返すようにしています。
if __name__ == "__main__":動作確認

2-2.|使用するライブラリ

今回のスクリプトでは、以下の 2つのPython標準ライブラリ を使用しています。どちらも Python に標準で付属しているため、追加インストールは不要です。

re(正規表現)

当プログラムにおける用途

ファイル名から “YYYY年MM月DD日” 形式の日付部分を抽出するために使用
パターンは \d{4}年\d{2}月\d{2}日 を採用し、最初にマッチした箇所だけを取得
詳細は、2-4.|関数説明にて解説しています。

インストール要否

標準ライブラリのため、インストール不要

主な用途(本スクリプト内)
用途関数・メソッド
日付文字列の抽出re.search(pattern, string)

datetime

当プログラムにおける用途


ファイル名に日付が含まれていない場合、現在日付を “YYYY年MM月DD日” 形式で生成するために使用

インストール要否

標準ライブラリのため、インストール不要

主な用途(本スクリプト内)
用途関数・メソッド
現在日付の取得datetime.now( )
日付のフォーマット.strftime(“%Y年%m月%d日”)

ポイントとして、このスクリプトは Pillow(PIL)や OS 系ライブラリを使用せず、ファイル名文字列の解析と日付生成に必要な最小限の標準ライブラリのみで構成されています。
そのため、環境依存が少なく、他モジュールからの呼び出しや単体テストもしやすいように作りました。

2-3.|date_utils.pyのコード全文

それでは、今回解説の対象となる date_utils.py のコード全文を掲載します。
まずは全体の構造を確認し、その後で各関数の役割や動作を順を追って説明していきます。

"""ファイル名から撮影日を抽出するためのユーティリティ。"""

import re
from datetime import datetime

def extract_photo_date_from_filename(filename: str) -> str:
    """
    ファイル名から撮影日を抽出する関数

    【目的】
    ファイル名に「YYYY年MM月DD日」の形式で日付が含まれている場合はそれを撮影日(photo_date)として返す。
    含まれていない場合は、実行日時(今日の日付)をデフォルトとして返す。

    【使用例】
    ファイル名例:
        - "2025年05月18日_風景.jpeg" → "2025年05月18日" を返す
        - "sunset.jpeg" → 実行日の "2025年06月05日"(例)を返す

    【パラメータ】
    filename (str): 処理対象のファイル名(拡張子含むことも可)

    【戻り値】
    str: 撮影日("YYYY年MM月DD日" 形式)

    【注意点】
    - 正規表現で日本語日付にマッチする形式のみ対応
    - 先頭で見つかった日付部分1箇所だけを対象とする
    """

    # 正規表現で「YYYY年MM月DD日」の形式を検索
    match = re.search(r"\d{4}年\d{2}月\d{2}日", filename)

    if match:
        # 該当する日付文字列が見つかった場合は、それを返す
        return match.group()
    else:
        # 見つからなかった場合は、現在の日付を"YYYY年MM月DD日"形式で返す
        return datetime.now().strftime("%Y年%m月%d日")

if __name__ == "__main__":
    from pathlib import Path

    # テスト用のファイル名例
    sample_filenames = [
        "2025年05月18日_風景.jpeg",
        "holiday_2024年12月25日.png",
        "no_date_image.jpg",
    ]

    print("[INFO] extract_photo_date_from_filename() テスト")
    for fname in sample_filenames:
        date_str = extract_photo_date_from_filename(fname)
        print(f"{fname} → {date_str}")

    # 実フォルダ内の画像ファイルでも試す(相対パス指定)
    project_root = Path(__file__).resolve().parent.parent
    input_dir = project_root / "input_images"

    if input_dir.exists():
        print(f"\n[INFO] Checking files in: {input_dir}")
        for img_file in input_dir.iterdir():
            if img_file.suffix.lower() in [".jpg", ".jpeg", ".png"]:
                date_str = extract_photo_date_from_filename(img_file.name)
                print(f"{img_file.name} → {date_str}")
    else:
        print(f"[WARN] {input_dir} が見つかりませんでした。")

実行すると次のように表示されます。

# ※ 実行結果中のパスは、環境依存情報(ユーザー名やPCのフォルダ構成)を含むため一部を「~」で省略しています。
# 2025年8月11日実行した場合の結果を表示しています。

[INFO] extract_photo_date_from_filename() テスト
2025年05月18日_風景.jpeg → 2025年05月18日
holiday_2024年12月25日.png → 2024年12月25日
no_date_image.jpg → 2025年08月11日

[INFO] Checking files in: ~/image-compressor-with-text/input_images
comp_input_sample_comp_2025年04月20日.jpg → 2025年04月20日

2-4.|関数説明

それでは、date_utils.py に含まれる唯一の関数extract_photo_date_from_filename(filename) について説明していきます。

目的

この関数は、画像ファイル名に含まれる撮影日(”YYYY年MM月DD日” 形式)を抽出するためのものです。
ファイル名に日付が含まれていない場合は、関数実行時の現在日付を返します。
ブログやWebサイトの画像加工時に、日付入りのコピーライト表記を自動生成する用途で使用します。

引数
  • filename
    処理対象のファイル名(拡張子を含んでも可)。
    例: “2025年05月18日_風景.jpeg”
動作概要:
  • 正規表現(\d{4}年\d{2}月\d{2}日)を使って、ファイル名から日付部分を検索します。
    この正規表現は、ファイル名の中から「西暦年4桁+月2桁+日2桁」の日本語日付表記を探すためのものです。
    該当箇所のコードを次に示します。
    #日付抽出
    match = re.search(r"\d{4}年\d{2}月\d{2}日", filename)

re.search(r"\d{4}年\d{2}月\d{2}日", filename)
この正規表現パターンは、「YYYY年MM月DD日」形式の日本語日付を探すためのものです。

  • \d{4} → 数字(0〜9)4桁(例: 2025
  • → 「年」という文字そのもの
  • \d{2} → 数字2桁(例: 0512
  • → 「月」という文字そのもの
  • \d{2} → 数字2桁(例: 1825
  • → 「日」という文字そのもの

つまり、2025年05月18日 のように、4桁の西暦年+2桁の月+2桁の日 で構成される部分だけを抽出します。

この正規表現では、

  • 月や日が1桁の場合(例: 2025年5月8日)はマッチしない
  • 必ず 0 を含む2桁表記である必要がある

という仕様になっています。

  • 最初にマッチした日付文字列を返します。
  • 日付が見つからない場合は、現在日付を “YYYY年MM月DD日” 形式で返します。

まとめ

今回は、ファイル名から撮影日を取得するだけの単機能モジュールについて解説しました。
このような前処理用のモジュールを分離しておくことで、他の画像加工処理からも簡単に再利用でき、保守性も向上します。

また、正規表現を活用することで日付部分の抽出がシンプルかつ確実に行える点もポイントです。
本記事の例では \d{4}年\d{2}月\d{2}日 というパターンを用いて、日本語形式の日付を直接ファイル名から取得できるようにしています。

前提条件として、ファイル名にはこの形式(例: 2025年08月11日_○○.jpg)の日付が含まれていることを想定しています。
もし日付が含まれない場合は、実行日を "YYYY年MM月DD日" 形式で返すような処理としました。

今回紹介したモジュールは、日付取得というシンプルな処理を独立させることで、画像加工スクリプトの中でも柔軟に組み込める形になっています。正規表現を使えば短いコードで確実に日付抽出が可能です。コピーライト表記の自動化やファイル管理など、ぜひ応用してみてください。

このモジュールは、シリーズ全体の画像加工処理における日付取得パートを担います。次のステップでは、コピーライト追加処理について解説します。

目次