Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#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