使いやすさにこだわった自作Python画像圧縮ツールの紹介

# 1.はじめに-ツール作成の背景
こんにちは！ごく一般の理系大学院生 けんじえんどうです！今回は，趣味で開発した **「画像圧縮ツール」** について紹介します！！

## 1.1.このツールの開発動機
学部時代に，初めて学会の予稿集用の論文をLaTeXを用いて執筆しました．その際に，提出する論文のファイルサイズに制限があるのを初めて知り，むやみやたらに図を記載していた私は，ファイルサイズの制限をゆうに超えました．その時，画像を圧縮するためのWebサイトを使用しましたが，そのWebサイトは，一度に圧縮できる画像ファイル数の制限があったり，ダウンロードをしたりしたため，面倒な作業だと考えました．そこで，私が普段使用している **Python**を用いて，画像圧縮ツールを作成すれば，そのような面倒な作業がなくなるのではないかと思い，今回作成しました．

## 1.2.重要視した点
今回，自作の画像圧縮ツールを作成するにあたって，以下の点を重視しました：
- **GUIとCUIの量から使える柔軟性**
- **HEIC/HEIF形式を含む多様な画像形式のサポート**
- **圧縮レベルを調整できる制御性**
- **大量の画像を効率的に処理できるバッチ機能**

それでは，このツールの開発過程と主な機能を紹介していきます．

# 2.主な機能と使い方
## 2.1.実装した機能
開発したツールには以下の機能があります：
- **複数の圧縮レベル** ：強・普通・弱の3段階から選択可能
- **多様な画像形式対応** ：JPG，PNG，HEIC，HEIF，WEBP，BMP，TIFFなど
- **PNGからJPGへの変換**
- **バッチ処理**：フォルダ内の全画像を一度に処理
- **プレビュー機能**：選択した画像を表示
- **進行状況表示**：処理中の進捗をリアルタイムで表示
![initial_menu.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815462/57d67c26-4f41-4e84-bfa7-5f5413cdc195.jpeg)
*画像圧縮ツールの初期画面*

![select_folder.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815462/d41b56b6-630f-4005-8f5b-a4aa118e8a9f.jpeg)
*圧縮するフォルダを選択したときの画面*

## 2.2.環境構築
### 2.2.1リポジトリのクローン
```
$ git clone https://github.com/yourusername/image-compression.git
$ cd image-compression
```

### 2.2.2.仮想環境の作成（推奨）
```
# Windowsの場合
$ python -m venv venv
$ venv\Scripts\activate

# macOS/Linuxの場合
$ python3 -m venv venv
$ source venv/bin/activate
```

### 2.2.3.依存関係のインストール
```
$ pip install -r requirements.txt
```

## 2.3.使用方法
### 2.3.1.GUIモード
```
$ python compression.py --gui
```
または，
```
$ python compression.py
```

### 2.3.2.CUIモード
```
$ python compression.py --input_folder /path/to/images --output_folder /path/to/output --compression_ratio 60
```

## 3.技術的な実装
### 3.1.使用技術
| 技術/ライブラリ | バージョン | 用途 |
|--------------|---------|------|
| Python | 3.12.9 | 主要開発言語 |
| Pillow (PIL) | 11.1.0 | 画像処理のコア機能 |
| pillow_heif | 0.21.0 | HEIC/HEIF形式のサポート |
| tkinter | 内蔵 | グラフィカルユーザーインターフェース |
| threading | 標準ライブラリ | UIの応答性を維持するマルチスレッド処理 |
| pathlib | 標準ライブラリ | ファイルパス操作 |
| argparse | 標準ライブラリ | コマンドライン引数の処理 |

### 3.2.アーキテクチャ設計
ツールは，以下のモジュールで構成されています：
1. compression.py: メインアプリケーションエントリポイント
2.util/image_compression.py: 画像圧縮のコアロジック
3.util/ui_window.py: GUIインターフェース実装
4.options/compression_option.py: コマンドラインオプション定義
5.util/module_checker.py: 必要モジュールの可用性確認

# 4.主要な実装部分の解説
画像圧縮の核となる部分は，ImageCompressionクラスのcompress_imageメソッドです．特に工夫した点は、画像形式ごとに最適な圧縮パラメータを適用する部分です：
```
def compress_image(self, image_path, output_path=None):
    try:
        # Get file extension (lowercase)
        ext = os.path.splitext(image_path)[1].lower()
        
        # If it's a HEIC/HEIF file, use dedicated conversion
        if ext in ['.heic', '.heif']:
            return self.heic2jpg(image_path, output_path)
        
        # Open the image
        img = Image.open(image_path)
        
        # Handle transparent images (when converting PNG to JPG)
        if img.mode in ['RGBA', 'LA'] and (self.convert_png_to_jpeg or ext != '.png'):
            background = Image.new('RGB', img.size, (255, 255, 255))
            background.paste(img, mask=img.split()[-1])
            img = background
            
        # Format-specific compression processing
        # (omitted)...
        
        print(f"Compression complete: {image_path} -> {output_path}")
        return True
        
    except Exception as e:
        print(f"Compression error {image_path}: {e}")
        return False
```
また，GUIの応答性を維持するために，圧縮処理を別スレッドで実行する実装も重要なポイントです：
```
# Excerpt from ui_window.py
def compress_images(self):
    # Input validation
    if not self.selected_files and not self.selected_folder:
        messagebox.showwarning("Warning", "Please select files or a folder.")
        return
        
    # Create progress window
    progress_window = tk.Toplevel(self.root)
    # (omitted)...
    
    # Run compression process in a separate thread
    threading.Thread(target=compression_thread, daemon=True).start()
```

# 5.開発を通して学んだこと
このツール作成と通して，多くのことを学ぶことができました：
1. **ユーザインタフェースの重要性**：機能だけでなく，使いやすさも重要であることを再認識した．
2. **エラーハンドリングの難しさ**：多様な画像形式に対応する中で，予期せぬエラーが多数発生した．堅牢なエラーハンドリングの重要性を学びました．
3. **モジュール設計の利点**：機能を明確に分離したモジュール設計のおかげで，機能追加が容易であることを再認識しました．
4. **マルチスレッドプログラミングの実践**：GUIのフリーズを防ぐためのスレッド処理を実装することで，並行処理の知識が深まりました．

# 6.今後の計画と改善点
現在のバージョンでも十分実用的だが，さらに以下の機能を追加する予定です：
- リネーム機能：ファイル名を一括で変更する機能
- 圧縮率変更機能：フォルダ内のファイルごとに圧縮率を変更する機能
- クラウドストレージ連携：Google DriveやDropboxとの連携
また，現状の制限として，非常に大きなファイルの処理時にメモリ使用量が多くなる点があります．
今後，大きなファイルも効率的に処理できるように実装を検討しています．

# 7.まとめ
ソースコードは，GitHubで公開していますので，興味のある方はぜひご覧ください：
[GitHub](https://github.com/KIIIIT00/image_compression)
使ってみた感想や改善アイデアなどありましたら、ぜひコメントやGitHubのIssueでフィードバックをお願いします。皆さんの意見を取り入れながら、より良いツールに進化させていきたいと思います．
最後になりましたが，今後のモチベーションのためにも，いいねやフォローをしていただけると幸いです．