J'utilise des captures d'écran comme tests de régression pour le logiciel d'interface graphique. Avant de déployer chaque nouvelle version, une série de tâches automatiques est exécutée sur l'ancienne et la nouvelle version, des captures d'écran sont générées après chaque commande dans les deux cas, et les résultats sont comparés. La commande d'importation d'ImageMagick fonctionne très bien pour cela.
Récemment, j'ai ajouté des menus clic droit. Malheureusement, import -window 'id'
ne capture pas ces menus.
Quels outils de ligne de commande sous Ubuntu peuvent prendre une capture d’écran d’une fenêtre, et de toutes les fenêtres situées au-dessus?
C'est-à-dire quels outils peuvent, au lieu de prendre une capture d'écran d'une fenêtre correspondant à un ID de fenêtre, prendre une capture d'écran de tout l'écran et la tronquer aux limites d'une fenêtre donnée ?
Je n'ai pas pu obtenir ce résultat de manière simple avec aucun des outils énumérés à la page Quelle est la commande du terminal pour prendre une capture d'écran? .
Utilisez import
avec l’option -screen
, comme
import -screen -window 'id' test.png
En utilisant shutter
et wmctrl
, une version modifiée de ce script fait à peu près exactement ce que vous décrivez: il prend une capture d'écran de la zone , un couvre-fenêtre spécifique sur votre écran, peu importe si et comment la fenêtre est (partiellement) en dessous des autres fenêtres.
La marge autour de la fenêtre, à inclure dans la capture d'écran, est arbitraire; mettez-le à zéro si vous voulez.
Inkscape
sur mon écran, avec id 0x0520000e
, partiellement recouverte par quelques fenêtres gedit
.Je lance le script avec l'identifiant de la fenêtre et la marge (dans px
) autour de la fenêtre sous forme d'arguments:
python3 <script> 0x0520000e 10 10 10 10
(où 10 10 10 10
est la marge dans px
autour de la fenêtre gauche/droite/haut/bas. Réglez sur 0
pour ne pas avoir de marge dans l'image)
Le résultat:
#!/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])
Le script utilise Shutter
et wmctrl
:
Sudo apt-get install wmctrl shutter
Copiez le script ci-dessous dans un fichier vide, enregistrez-le sous le nom custom_screenshot.py
.
Exécutez-le à l'aide de la commande:
python3 /path/to/custom_screenshot.py <window_id> <left> <right> <top> <bottom>
où, <left> <right> <top> <bottom>
sont les marges que vous souhaitez conserver dans l'image autour de la fenêtre, comme dans cette réponse.
Exemple de commande:
python3 /path/to/custom_screenshot.py 0x0520000e 20 20 20 20
Dans Shutter
, il est possible de prendre une capture d'écran d'une zone définie du bureau.
Avec l'identifiant de fenêtre comme argument, le script recherche la position exacte de la fenêtre à l'aide de wmctrl
(wmctrl -lG
pour être précis), et la sortie de xprop -id <window_id>
(dans la ligne _NET_FRAME_EXTENTS(CARDINAL) = 0, 0, 28, 0
par exemple).
Ensuite, une capture d'écran est prise à partir de la zone trouvée, avec une marge arbitraire.
Le script ne remplace pas les captures d'écran existantes. Les nouvelles captures d'écran sont nommées:
outputfile_1.png
outputfile_2.png
outputfile_3.png
etc...
Basé sur ce script , si nous faisons exactement la même astuce, mais que nous utilisons Scrot
au lieu de Shutter
, nous pouvons ignorer le sleep 0.5
et le rendre beaucoup plus rapide:
#!/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])
Utilisez-le exactement comme le premier script, uniquement:
Ce script nécessite scrot
, imagemagick
et wmctrl
Sudo apt-get install imagemagick wmctrl scrot
les images seront stockées dans ~/scrot_images
Alors que le premier script utilise l'option de ligne de commande Shutter
pour créer une section définie du bureau, Scrot
ne prend pas cela en charge. Il ne prend qu'une capture d'écran de de tout l'écran .
Nous pouvons toutefois combiner l'option de imagemagick
pour créer une image, avec la méthode permettant de trouver les coordonnées exactes de la fenêtre que nous avons utilisées dans le premier script et de rogner l'image en conséquence.
Étant donné que Scrot
est extrêmement léger et rapide, même en combinaison avec l'action de rognage de imagemagick
, nous disposons d'un moyen assez rapide de créer des captures d'écran de la surface d'une fenêtre.
Pas encore assez rapide?
Je ne sais pas si cela est nécessaire, mais avec un peu de réécriture (voir le script ci-dessous), il serait possible de faire une série de plans encore plus rapidement en tirant d’abord toute la série, , puis (après) faire le recadrage. En supposant que la fenêtre reste dans sa position, cela économiserait une quantité considérable de temps:
Tir uniquement avec Scrot
(pas de recadrage):
real 0m0.263s
user 0m0.205s
sys 0m0.037s
Tir, y compris recadrage:
real 0m0.363s
user 0m0.293s
sys 0m0.040s
Enfin, à titre d'exemple pour faire une série de captures d'écran, le script ci-dessous, comme suggéré dans l'EDIT.
Celui-ci commence à prendre une photo de toutes les images, , puis recadre toutes les images créées en même temps.
Utilisez le script comme le second, mais avec un argument supplémentaire : le nombre de pousses dans une ligne, par exemple:
python3 /path/to/custom_screenshot.py 0x0520000e 0 0 0 0 20
faire 20 captures d'écran de la fenêtre 0x0520000e
à la suite (cela pourrait être des centaines), pas de marge autour de la fenêtre.
#!/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])