LoginSignup
0
0

d3dshotを使う

Posted at

序文

スクリーンショットを速く撮るために色々してたときの中で、D3Dshotを使ってみたときの下書き記事をとりあえず形にだけして投稿したもの
要するに、塩漬け記事

正直、推奨しません

スクリーンショットを速く撮りたい

Pythonでは、PILやPyAutoGUIでスクリーンショットが撮れるのですが、少なくとも、Windows環境ではかなり遅いです。

これは、使用しているAPIが古いことに原因があります。

d3dshotを使う

で、Pypiにd3dshotと言うモジュールがあり、これは高速にスクリーンショットを撮れるようです。ですが、このd3dshot、問題がありPypiからインストール出来ません。してしまうとちょっと問題が出ます。

インストールに失敗する原因はPythonのバージョンとPillowのバージョンです。特にPillowは古すぎるバージョンが指定されているため、pipが古いバージョンをインストールしようとしますが、バイナリがPypiに既に無いため、ソースコードからコンパイルしろと言うエラーが出ます。
この時、既にPillowがインストールされている場合、実体は削除されてしまうのですが、pip上ではインストールされていると言う状態で終了します。
修正するには、pip uninstall pillow をした後に、pip install pillowをして、pillowを再インストールしてください

なので、手動でインストールしましょう。
PyPiからd3dshotをDLしましょう
任意の場所に展開した上で、pyproject.tomlを修正します

version = "0.1.5"
# ↓
version = "0.1.6"
    "Programming Language :: Python",
    "Programming Language :: Python :: 3.8",
# ↓
    "Programming Language :: Python",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
[tool.poetry.dependencies]
python = ">=3.6"

comtypes = "~1.1.7"
pillow = "~7.1.2"

[tool.poetry.dev-dependencies]
ipython = "~7.14"
notebook = "~6.0"
# ↓
[tool.poetry.dependencies]
python = ">=3.6"

comtypes = ">=1.1.7"
pillow = ">=7.1.2"

[tool.poetry.dev-dependencies]
ipython = ">=7.14"
notebook = ">=6.0"

全体だと下のようになります

pyproject.toml
[tool.poetry]
name = "D3DShot"
version = "0.1.6"
description = "A fork of the original D3DShot package: Extremely Fast and Robust Screen Capture on Windows with the Desktop Duplication API"
readme = "README.md"
authors = ["Nicholas Brochu <nicholas@serpent.ai>"]
license = "MIT"
repository = "https://github.com/fauskanger/D3DShot"
keywords = ["Screen Capture", "Screenshot", "Computer Vision", "Windows"]
classifiers = [
    "Development Status :: 5 - Production/Stable",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Natural Language :: English",
    "Operating System :: Microsoft :: Windows",
    "Operating System :: Microsoft :: Windows :: Windows 8.1",
    "Operating System :: Microsoft :: Windows :: Windows 10",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Topic :: Multimedia :: Graphics",
    "Topic :: Multimedia :: Graphics :: Capture",
    "Topic :: Multimedia :: Graphics :: Capture :: Screen Capture"
]
packages = [
    {include = "d3dshot"},
]
include = []

[tool.poetry.dependencies]
python = ">=3.6"

comtypes = ">=1.1.7"
pillow = ">=7.1.2"

[tool.poetry.dev-dependencies]
ipython = ">=7.14"
notebook = ">=6.0"

[tool.black]
line-length = 99

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

このファイルを保存して、
pip install d3dshot/
のようにしてインストールします

以下サンプルプログラム(pygame使用)

d3dshot_ex.py
import ctypes
import sys
import d3dshot
import copy
import pygame

frame_buffer_size = 60
fillcolor = pygame.Color(0,0,0)
window_size = (800,480)

user32 = ctypes.windll.user32
screen_size = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)
s = d3dshot.create(capture_output="numpy", frame_buffer_size=frame_buffer_size)

def main():
    global window_size

    pygame.display.init()

    sf = pygame.display.set_mode(window_size, flags=pygame.RESIZABLE, depth=0)

    def draw():
        ds = pygame.display.get_surface()

        sc = copy.deepcopy(s.screenshot())
        sf.blit(pygame.transform.scale(pygame.surfarray.make_surface(
            sc.transpose(1, 0, 2)), window_size), (0, 0))
        return

    def get_scale(screensize,windowsize):
        return min(windowsize[0]/screensize[0], windowsize[1]/screensize[1])

    def quit():
        pygame.quit()
        sys.exit()

    while True:  # メインループ
        for event in pygame.event.get():
            if event.type == pygame.QUIT:  # 外部からの終了要求に対する終了処理
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:  # ESCキーを押したときの終了処理
                    quit()
            if event.type == pygame.VIDEORESIZE:
                ds = pygame.display.get_surface()
                scale = get_scale(screen_size, (ds.get_width(),ds.get_height()))
                window_size = (screen_size[0]*scale, screen_size[1]*scale)
        sf.fill(fillcolor)
        draw()

        pygame.display.flip()  # 画面表示

if __name__ == '__main__':
    main()

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