Как сделать снимок экрана из окна и всех окон поверх него?

Я использую скриншоты как регрессионные тесты для программного обеспечения GUI. Перед развертыванием каждой новой версии ряд автоматических задач запускается против старой и новой версий, скриншоты генерируются после каждой команды в обоих случаях, и результаты сравниваются. Команда импорта ImageMagick работает очень хорошо.

Недавно я добавил меню правой кнопки мыши. К сожалению, import -window 'id' не отображает эти меню.

Какие инструменты командной строки на Ubuntu могут сделать снимок экрана из окна и все окна поверх него?

То есть , какие инструменты могут вместо снимка экрана, соответствующего идентификатору окна, Какие инструменты командной строки на Ubuntu могут сделать снимок экрана из окна и все окна поверх него? ? [ ! d4]

Я не смог получить этот результат простым способом с помощью любого из инструментов, перечисленных в разделе «Что такое команда терминала, чтобы сделать снимок экрана».

1
задан 8 February 2016 в 01:11

2 ответа

Используя shutter и wmctrl, отредактированная версия этого скрипта делает в значительной степени то, что вы описываете: для этого требуется скриншот области, на вашем экране есть определенное окно, независимо от того, (частично) ниже других окон.

область вокруг окна, которая будет включена в скриншот, произвольна;

На практике

У меня есть окно Inkscape на моем экране с id 0x0520000e, частично покрытое несколькими gedit окнами , Я запускаю скрипт с идентификатором окна и marge (в px) вокруг окна в качестве аргументов:
python3 <script> 0x0520000e 10 10 10 10 
(где 10 10 10 10 - это marge в px вокруг окна слева / справа / сверху / снизу Установите на 0, чтобы на изображении не было marge). Результат:

Сценарий

#!/usr/bin/env python3
import subprocess
import time
import sys

"""
On different window managers, the window geometry as output of wmctrl differs slightly.
The "deviation" should compensate these differences. Most likely appropriate (tested) settings:
Unity: 0, Gnome: -36, Xfce (Xubuntu): -26, KDE (Kubuntu): 0
"""
#---
deviation = 0
#---

get = lambda cmd: subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
time.sleep(0.5)
# targeted window
target = sys.argv[1]; arg = sys.argv[2:]
f_data = [l.split() for l in get("wmctrl -lG").splitlines() if target in l][0][2:6]
xt_data = get("xprop -id "+target).split()
xt_i = xt_data.index("_NET_FRAME_EXTENTS(CARDINAL)")
xt = [int(n.replace(",", "")) for n in xt_data[xt_i+2:xt_i+6]]
# set data for screenshot command
x = str(int(f_data[0])-int(arg[0])-xt[0])
y = str(int(f_data[1])-int(arg[2])-xt[2]+deviation)
w = str(int(f_data[2])+int(arg[0])+int(arg[1])+xt[0]+xt[1])
h = str(int(f_data[3])+int(arg[3])+int(arg[2])+xt[2]+xt[3])

command = "shutter -s="+(",").join([x,y,w,h])+" -e"
subprocess.call(["/bin/bash", "-c", command])

Как использовать

I есть окно Inkscape на моем экране с id 0x0520000e, частично покрытое несколькими окнами gedit. Скопируйте сценарий ниже в пустой файл, сохраните его как custom_screenshot.py. Я запускаю сценарий с идентификатором окна и marge (в px) вокруг окна в качестве аргументов:
python3 <script> 0x0520000e 10 10 10 10 
(где 10 10 10 10 - это marge в px вокруг окна слева / справа / верхний / нижний. Установите на 0, чтобы на изображении не было marge). Результат:

Объяснение

Скопируйте сценарий ниже в пустой файл , сохраните его как custom_screenshot.py.

Я запускаю скрипт с идентификатором окна и marge (в px) вокруг окна в качестве аргументов:

Затем снимок экрана берется из найденная область, с произвольной маршей.

Примечание

С идентификатором окна в качестве аргумента скрипт ищет точное положение окна с помощью wmctrl (wmctrl -lG, если быть точным), а вывод из xprop -id <window_id> (например, в строке _NET_FRAME_EXTENTS(CARDINAL) = 0, 0, 28, 0).

outputfile_1.png
outputfile_2.png
outputfile_3.png

Сценарий не перезаписывает существующие скриншоты. Новые скриншоты названы:

EDIT

Поскольку вы упомянули в комментарии, что скорость является проблемой:

и т. Д. ..

Сценарий

#!/usr/bin/env python3
import subprocess
import sys
import os

"""
On different window managers, the window geometry as output of wmctrl differs slightly.
The "deviation" should compensate these differences. Most likely appropriate (tested) settings:
Unity: 0, Gnome: -36, Xfce (Xubuntu): -26, KDE (Kubuntu): 0
"""
#---
deviation = 0
#---

get = lambda cmd: subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
# targeted window
target = sys.argv[1]; arg = sys.argv[2:]
f_data = [l.split() for l in get("wmctrl -lG").splitlines() if target in l][0][2:6]
xt_data = get("xprop -id "+target).split()
xt_i = xt_data.index("_NET_FRAME_EXTENTS(CARDINAL)")
xt = [int(n.replace(",", "")) for n in xt_data[xt_i+2:xt_i+6]]
# set data for screenshot command
x = str(int(f_data[0])-int(arg[0])-xt[0])
y = str(int(f_data[1])-int(arg[2])-xt[2]+deviation)
w = str(int(f_data[2])+int(arg[0])+int(arg[1])+xt[0]+xt[1])
h = str(int(f_data[3])+int(arg[3])+int(arg[2])+xt[2]+xt[3])

# setting default directories / filenames
home = os.environ["HOME"]
temp = home+"/"+".scrot_images"
img_in = temp+"/in.png"
# if you prefer, you can change the two line below:
output_directory = home+"/"+"scrot_images" # output directory
filename = "outputfile"                    # filename
# creating needed directories
for dr in [temp, output_directory]:
    if not os.path.exists(dr):
        os.mkdir(dr)
# creating filename (-number) to prevent overwriting previous shots
n = 1
while True:
    img_out = output_directory+"/"+filename+"_"+str(n)+".png"
    if os.path.exists(img_out):
        n = n+1
    else:
        break
# Take screnshot, crop image
subprocess.call(["scrot", img_in])
subprocess.Popen(["convert", img_in, "-crop", w+"x"+h+"+"+x+"+"+y, "+repage", img_out])

Использовать

На основе этого скрипта , если мы делаем точно такой же трюк, но используйте Scrot вместо Shutter, мы можем пропустить sleep 0.5 и сделать его быстрее :

Я запускаю скрипт с id окна и marge (в px) вокруг окна в качестве аргументов:

изображения будут сохранены в ~/scrot_images

Объяснение

Использовать это точно так же, как и первый скрипт:

Этот скрипт нуждается в scrot, imagemagick и wmctrl

. Хотя первый скрипт использует параметр командной строки для Shutter для съемки определенного раздела рабочего стола, Scrot не поддерживает это. Он занимает всего скриншот всего экрана.

Мы можем объединить, однако, функцию imagemagick, чтобы сделать выборку изображения, с помощью метода найти точные координаты окна, которые мы использовали в первом скрипте, и обрезать изображение соответственно. Поскольку Scrot чрезвычайно легкий и быстрый, даже в сочетании с действием imagemagick, мы имеем довольно быстрый способ сделать снимки экрана в области окна.

изображения будут сохраненный в ~/scrot_images Впоследствии снимок экрана берется из найденной области с произвольной marge.

Последовательная съемка

Still not достаточно!

Не уверен, что это необходимо, но с небольшим количеством перезаписи (см. скрипт ниже) можно было бы сделать серию снимков еще быстрее, сначала снимая целую серию, [d55 ] весь экран (впоследствии) выполняет обрезку. Предполагая, что окно останется в своем положении, это спасло бы сумму considearable времени:

python3 /path/to/custom_screenshot.py 0x0520000e 0 0 0 0 20

Наконец, в качестве примера, чтобы сделать серию снимков экрана, сценарий ниже, как предлагается в EDIT . Сначала он снимает все изображения подряд, а затем обрезает все созданные изображения сразу.

Сценарий

#!/usr/bin/env python3
import subprocess
import sys
import os

"""
On different window managers, the window geometry as output of wmctrl differs slightly.
The "deviation" should compensate these differences. Most likely appropriate (tested) settings:
Unity: 0, Gnome: -36, Xfce (Xubuntu): -26, KDE (Kubuntu): 0
"""
#---
deviation = 0
#---

get = lambda cmd: subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
# targeted window
target = sys.argv[1]; arg = sys.argv[2:]
f_data = [l.split() for l in get("wmctrl -lG").splitlines() if target in l][0][2:6]
xt_data = get("xprop -id "+target).split()
xt_i = xt_data.index("_NET_FRAME_EXTENTS(CARDINAL)")
xt = [int(n.replace(",", "")) for n in xt_data[xt_i+2:xt_i+6]]
# set data for screenshot command
x = str(int(f_data[0])-int(arg[0])-xt[0])
y = str(int(f_data[1])-int(arg[2])-xt[2]+deviation)
w = str(int(f_data[2])+int(arg[0])+int(arg[1])+xt[0]+xt[1])
h = str(int(f_data[3])+int(arg[3])+int(arg[2])+xt[2]+xt[3])
# setting default directories / filenames
home = os.environ["HOME"]
temp = home+"/"+".scrot_images"
# if you prefer, you can change the two line below:
output_directory = home+"/"+"scrot_images" # output directory
filename = "outputfile"                    # filename
# creating needed directories
for dr in [temp, output_directory]:
    if not os.path.exists(dr):
        os.mkdir(dr)
# do the shooting
t = 0; l = []; shots = int(sys.argv[6])
while t < shots:
    img_temp = temp+"/"+str(t)+"in.png"
    l.append(img_temp)
    # reading arguments,arranging commands to perform
    subprocess.call(["scrot", img_temp])
    t += 1
# do the cropping on all images in a row
for img in l:
    n = 1
    while True:
        img_out = output_directory+"/"+filename+"_"+str(n)+".png"
        if os.path.exists(img_out):
            n = n+1
        else:
            break
    subprocess.call(["convert", img , "-crop", w+"x"+h+"+"+x+"+"+y, "+repage", img_out])
6
ответ дан 23 May 2018 в 13:42
  • 1
    Я опасаюсь вызова sleep(0.5); там будет много скриншотов (порядка 300), поэтому ждать 0,5 секунды между ними не очень хорошо. – Clément 7 February 2016 в 19:14
  • 2
    @ Clément см. Обновленный ответ. – Jacob Vlijm 7 February 2016 в 20:41
  • 3
    Извините за путаницу; Я думал, что скриншоты были сделаны после того, как каждая команда в программе будет достаточно :) Спасибо за обновление ответа! – Clément 7 February 2016 в 21:42
  • 4
    Просто чтобы уточнить: это получает границы окна, а затем урожай скриншотов всего экрана, не так ли? – Clément 7 February 2016 в 21:43
  • 5
    @ Clément - второй сценарий. Будет добавлено объяснение после обеда. – Jacob Vlijm 7 February 2016 в 21:53

Прочитайте man import. В моем .bashrc (фактически в файле source d на .bashrc) у меня есть:

alias tshhmmss='date +%y%b%d-%H%M%S'
screenshot ()
{
   import -window root ~/var/screenshot/$(tshhmmss)_screendump.png
}
-2
ответ дан 23 May 2018 в 13:42

Другие вопросы по тегам:

Похожие вопросы: