0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

キャプボからキャプチャしたゲーム画像を自動で縮小・変換する

Last updated at Posted at 2019-05-17

さっさと本題に入りたい方は目次からどうぞ。

ゲーム画面の静止画をシェアしたいことってありますよね。
今時であればキャプチャー機能が付いているゲームハードは珍しくなく、手軽にSNSへシェアすることもできます。
しかし私は画面全体をキャプチャに含めなくてもいいなというときは、トリミングしてからシェアをしたいと思っていました。
例えば下記投稿はユーザーが書いたイラスト部分が主題であり、ユーザーの装備は画像に含める必要がありません。

そんな中、ニンテンドーSwitch本体のアップデートでズーム機能が追加されました。
これで必要な部分だけ実質トリミングできる!と思った私でしたが、ズーム機能だけではその願いをかなえることはできませんでした。

しかしそれでもトリミング画像をシェアしたい私は、ゲーム画面でズームしたままにしておいてキャプチャーボードを起動し、パソコン側でキャプチャーボードに映ったズーム済みの画像をキャプチャーしてSNS投稿用に変換してからシェアするという非常に回りくどい方法を取っていたのです。
キャプチャーするときにフォーマットを選べれば良いのですが、bmp形式での保存しか対応していないのが特にツラいところです(Twitterはbmp画像をアップロードできないっぽい?)。

いい加減面倒な方法だよなと感じたため、キャプボを起動して静止画キャプチャーする手間は減らせないものの、キャプチャー後の手間を減らすために今回のプログラムを作りました。

本題

次のようなプログラムにしました。

  1. キャプチャーボードからのファイルの保存先フォルダは固定されている。
  2. 保存先フォルダのファイルを監視し、bmpファイルが作成されたタイミングがわかるようにする。
  3. 作成されたbmpファイルを縮小し、jpg形式で新規保存する。

フォルダを監視する

watchdogというモジュールを利用します。
下記記事の記述が分かりやすかったため、参考にさせて頂きました。

ファイル監視にwatchdogがかなり便利な件 - Qiita

今回はファイルが作成されたタイミングだけ知ることができればよいので、on_createdのイベントだけ実装します。

ここで一つハマったポイントがありました。
私が利用しているキャプチャーボードAVT-C875および、その専用ソフトRECentralからのキャプチャーでファイルが作成されたとき、普通にイベントをハンドルしてしまうとPermissionErrorが発生したのです。

デバッグでステップ実行すると同エラーは発生しません。
結果的に、イベントを検知したときにtime.sleep(1)を入れることで安定して動作するようになりました。
キャプチャーソフトの動作は、ファイルを作成した瞬間にはまだ画像が「完成」しておらず、コントロールを掴んだままになっているのではないかと思っています。
その、まだ未完成の画像ファイルを読もうとしてしまったからエラーになったのではないかという推測ですね。

画像を変換する

PILの機能を使って読み込み・リサイズ・保存まで実行します。
画像のキャンバスサイズは整数でなければいけないはずなのでround関数で丸めました。単に縮小できればよかったので、誤差などは無視しています。

ところで、Image.save()関数ではフォーマットを指定できる引数が用意されているはずなんですが、format='JPEG'と指定しても拡張子なしで保存されてしまいました。どうやったらformat引数にちゃんと保存形式を渡すことができるのでしょうか?ご存知の方がいらっしゃったら教えてください。

Image.save(fp, format=None, **params)

結局、ファイル名 + '.jpg'というパスを保存先として渡すことでjpg保存させることにしました。

おわり

フォルダ監視って面倒なんじゃないかな~と思っていたんですが、簡単に実装できるモジュールがあって助かりました。
以下、今回作ったプログラムです。

ConvertToJpg - GitHub

# -*- coding: utf-8 -*-

import time
import os
from PIL import Image
import numpy as np

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

BASEDIR = os.path.abspath("E:\VideoGames\【キャプチャ映像】")

def get_ext(filename):
    return os.path.splitext(filename)[-1].lower()

class ChangeHandler(FileSystemEventHandler):

    def on_created(self, event):
        time.sleep(1)
        if event.is_directory:
            return
        if get_ext(event.src_path) == '.bmp':
            img_path = event.src_path
            bmp_img = Image.open(img_path)
            resized = bmp_img.resize(
                (round(bmp_img.width / 2), round(bmp_img.height / 2)),
                Image.NEAREST)
            filename = os.path.splitext(event.src_path)[0]
            resized.save(filename + '.jpg')

if __name__ in '__main__':
    while 1:
        event_handler = ChangeHandler()
        observer = Observer()
        observer.schedule(event_handler,BASEDIR,recursive=True)
        observer.start()
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            observer.stop()
        observer.join()
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?