#1 Le 05/03/2010, à 02:24
- pops
script de recadrage d'images avec prévisualisation en python
bonjours a tous
voila, comme j'en avais marre de devoir utiliser windows et photoshop pour recadrer mes plans d'anims, j'ai fais un ptit script pour cela, l'intérêt par rapport à phatch ou dbp c'est qu'on peut voir un apercu du recadrage.
c'est à utiliser sur des images qui ont toutes la même taille (j'ai pas testé autrement mais il peut y avoir des bug)
je l'utilise en script thunar avec cette commande: python /chemin/vers/le/script/script.py %F (ça dois pas être bien différent pour nautilus)
et qu'il n'apparaisse que sur les dossier.
il faut avoir python et pygtk d'installé (mais ça dois surement être déjà fais)
mais aussi pil; le paquet "python-imaging" des dépots
donc voila, si ça peut servir a quelqu'un ou encore si vous avez des conseils (c'est mon premier truc qui ne sort pas d'un tuto en python)
j'essaierai de rajouter quelques petites choses ultérieurement comme la rotation ou la possibilité de bloquer le ratio de l'image.
# -*- coding: Latin-1 -*-
#!/usr/bin/python
import os, sys
from PIL import Image
import pygtk
pygtk.require("2.0")
import gtk
import StringIO
# passe d'une image pil à une image gtk (merci à manatlan)
def image2pixbuf(im):
file1 = StringIO.StringIO()
im.save(file1, "ppm")
contents = file1.getvalue()
file1.close()
loader = gtk.gdk.PixbufLoader("pnm")
loader.write(contents, len(contents))
pixbuf = loader.get_pixbuf()
loader.close()
return pixbuf
# découpe l'image et renvoie une image gtk pour l'apercu
def crop_im(im, rect, zoom):
tuple_rect = (rect[0],rect[1],rect[2],rect[3])
cropim = im.crop(tuple_rect)
if zoom == "100%":
w = cropim.size[0]
h = cropim.size[1]
elif zoom == "75%":
w = int(cropim.size[0]*0.75)
h = int(cropim.size[1]*0.75)
elif zoom == "50%":
w = int(cropim.size[0]*0.5)
h = int(cropim.size[1]*0.5)
elif zoom == "25%":
w = int(cropim.size[0]*0.25)
h = int(cropim.size[1]*0.25)
elif zoom == "10%":
w = int(cropim.size[0]*0.1)
h = int(cropim.size[1]*0.1)
cropzim = cropim.resize((w, h))
pixbuf = image2pixbuf(cropzim)
return pixbuf
# création de l'interface avec les valeurs de base
def fenetregtk():
global im
global rect
global width
global height
global activ_file
global zoom
activ_file = CHEMIN+"/"+images[0]
im = Image.open(activ_file)
info = str (images[0] + " " + im.format + " " + str(im.size) + " " + im.mode)
width = im.size[0]
height = im.size[1]
rect = [0, 0, width, height]
ratio = "ratio: " + str(float(width)/float(height))
# construction de l'interface
mainWindow = gtk.Window()
mainWindow.set_title("image")
mainWindow.connect("destroy", on_mainWindow_destroy)
label_info = gtk.Label(info)
label_crop = gtk.Label(str(width) + " / " + str(height))
label_ratio = gtk.Label(ratio)
label_save = gtk.Label("")
ratio_169 = gtk.Label("16/9: 1.7777...")
ratio_43 = gtk.Label("4/3: 1.3333...")
# choix de l'image
sel_image = gtk.combo_box_new_text()
for i in images:
sel_image.append_text(i)
sel_image.set_active(0)
sel_image.connect('changed', change_image, label_info)
# boutons de recadrage
gauche_ajustement = gtk.Adjustment(0, 0, width, 1)
haut_ajustement = gtk.Adjustment(0, 0, height, 1)
droite_ajustement = gtk.Adjustment(width, 0, width, 1)
bas_ajustement = gtk.Adjustment(height, 0, height, 1)
gauche = gtk.SpinButton(gauche_ajustement)
haut = gtk.SpinButton(haut_ajustement)
droite = gtk.SpinButton(droite_ajustement)
bas = gtk.SpinButton(bas_ajustement)
gauche.connect("value-changed", maj, label_crop, label_ratio, "gauche")
haut.connect("value-changed", maj, label_crop, label_ratio, "haut")
droite.connect("value-changed", maj, label_crop, label_ratio, "droite")
bas.connect("value-changed", maj, label_crop, label_ratio, "bas")
save_button = gtk.Button("save")
save_button.connect("clicked", on_save_button_clicked, label_save)
label_gauche = gtk.Label("gauche")
label_haut = gtk.Label("haut")
label_droite = gtk.Label("droite")
label_bas = gtk.Label("bas")
vBox = gtk.VBox()
vBox.pack_start(sel_image)
vBox.pack_start(label_info)
vBox.pack_start(label_gauche)
vBox.pack_start(gauche)
vBox.pack_start(label_haut)
vBox.pack_start(haut)
vBox.pack_start(label_droite)
vBox.pack_start(droite)
vBox.pack_start(label_bas)
vBox.pack_start(bas)
vBox.pack_start(label_crop)
vBox.pack_start(label_ratio)
vBox.pack_start(ratio_169)
vBox.pack_start(ratio_43)
vBox.pack_start(save_button)
vBox.pack_start(label_save)
mainWindow.add(vBox)
mainWindow.show_all()
# seconde fenetre d'apercu
prevWindow = gtk.Window()
prevWindow.set_title("apercu")
prevWindow.connect("destroy", on_prevWindow_destroy)
zoom_image = gtk.combo_box_new_text()
zoom_image.append_text("100%")
zoom_image.append_text("75%")
zoom_image.append_text("50%")
zoom_image.append_text("25%")
zoom_image.append_text("10%")
zoom_image.connect('changed', choix_zoom)
if width > 2000 or height > 2000:
zoom_image.set_active(4)
zoom = "10%"
elif width > 1000 or height > 1000:
zoom_image.set_active(2)
zoom = "50%"
else:
zoom_image.set_active(0)
zoom = "100%"
pixbuf = crop_im(im, rect, zoom)
global previmage
previmage = gtk.Image()
previmage.set_from_pixbuf(pixbuf)
vvBox = gtk.VBox()
vvBox.pack_start(zoom_image)
vvBox.pack_start(previmage)
prevWindow.add(vvBox)
prevWindow.show_all()
def on_mainWindow_destroy(widget):
gtk.main_quit()
def on_prevWindow_destroy(widget):
pass
def choix_zoom(zoom_image):
global zoom
zoom = zoom_image.get_active_text()
pixbuf = crop_im(im, rect, zoom)
previmage.set_from_pixbuf(pixbuf)
# change l'image utilisé pour la prévisualisation
def change_image(sel_image, label_info):
global im
global activ_file
choix = sel_image.get_active_text()
activ_file = CHEMIN+"/"+choix
im = Image.open(activ_file)
info = str (choix + " " + im.format + " " + str(im.size) + " " + im.mode)
label_info.set_text(info)
pixbuf = crop_im(im, rect, zoom)
previmage.set_from_pixbuf(pixbuf)
# met a jour le cadre et la prévisualisation
def maj(entree, sortieCrop, sortieRatio, widget):
global rect
if widget == "gauche":
rect[0] = int(entree.get_text())
elif widget == "haut":
rect[1] = int(entree.get_text())
elif widget == "droite":
rect[2] = int(entree.get_text())
elif widget == "bas":
rect[3] = int(entree.get_text())
ratioheight = rect[3] - rect[1]
ratiowidth = rect[2] - rect[0]
ratio = float(ratiowidth)/float(ratioheight)
sortieCrop.set_text(str(ratiowidth) + " / " + str(ratioheight))
sortieRatio.set_text(" ratio: "+str(ratio))
pixbuf = crop_im(im, rect, zoom)
previmage.set_from_pixbuf(pixbuf)
# aplique les modification a toutes les images
def on_save_button_clicked(widget, label_save):
tuple_rect = (rect[0],rect[1],rect[2],rect[3])
os.mkdir(repertoire_sortie)
n = 0
nt = len (images)
for i in images:
n = n+1
im = Image.open(CHEMIN+"/"+i)
cropim = im.crop(tuple_rect)
cropim.save(repertoire_sortie+"/"+i)
label_save.set_text(str(n) + " / " + str(nt) + " images recadrées")
if __name__ == "__main__":
# verifie que c'est bien un dossier
CHEMIN = sys.argv[1]
#CHEMIN = "/media/doc/prog/python/image/thunar/images"
if os.path.isdir(CHEMIN):
fichiers = []
fichiers = os.listdir(CHEMIN)
# prépare le répertoire ou seront enregistrées les images
repertoire_sortie = CHEMIN + "crop"
if os.path.isdir(repertoire_sortie):
i=1
while os.path.isdir(repertoire_sortie):
i = i+1
repertoire_sortie = repertoire_sortie+str(i)
# ne prend que les fichiers images
images = []
for i in fichiers:
ext = os.path.splitext(i) [ 1 ]
if ext == ".png" or ext == ".PNG" or ext == ".jpg" or ext == ".JPG" or ext == ".jpeg" or ext == ".JPEG":
images.append(i)
images.sort()
# lance la fenetre pour choisir le cadre
fenetregtk()
gtk.main()
Hors ligne
#2 Le 06/03/2010, à 17:49
- pops
Re : script de recadrage d'images avec prévisualisation en python
hop, je continu à améliorer mon ptit script, j'ai rajouté la rotation et quelques petites options.
je voulais aussi rajouter un redimensionnement mais j'ai un petit problème pour conserver le ratio de l'image:
en fait j'ai deux spinbutton pour la hauteur et la largeur.
a chaque fois que l'on change la valeur de l'un, il va changer la valeur de l'autre pour conserver le ratio de l'image.
le probleme et que le calcul est aproximatif (au pixel pres) et que du coup le second va alors changer la valeur du premier puis le premier va changer la valeur du second jusqu'à ce qu'ils se mettent d'accord entre eux.
voila les widget:
label_redimentionner = gtk.Label("redimentionner")
label_height = gtk.Label("hauteur")
label_width = gtk.Label("largeur")
resize_height_ajustement = gtk.Adjustment(height, 0, height, 1)
resize_width_ajustement = gtk.Adjustment(width, 0, width, 1)
resize_height = gtk.SpinButton(resize_height_ajustement)
resize_width = gtk.SpinButton(resize_width_ajustement)
resize_height.connect("value_changed", redimensionner, "height", resize_width)
resize_width.connect("value_changed", redimensionner, "width", resize_height)
et la fonction:
def redimensionner(entree, widget, secwidget):
global height_redim
global width_redim
if widget == "height":
height_redim = entree.get_value()
width_redim = height_redim * ratio
secwidget.set_value(int(width_redim))
print "tagada"
elif widget == "width":
width_redim = entree.get_value()
height_redim = width_redim / ratio
secwidget.set_value(int(height_redim))
print "tsoin tsoin"
voila, ca fais une heure que je bouffe de la doc de gtk sans rien trouver si ce n'est un obscur set_update_policy qui ne fonctionne pas, donc j'aurais besoin d'un petit coup de main.
Hors ligne