Logo Mon Club Elec

PyQt Lab’ : Ouvrir/Enregistrer une image (QPixmap et QImage) depuis/dans un fichier

PyQt Lab est un outil puissant qui permet aux développeurs d’utiliser le framework Qt pour créer des applications graphiques. Il offre une variété de fonctionnalités, notamment la possibilité d’ouvrir et d’enregistrer des images (QPixmap et QImage) depuis et dans un fichier. Dans cet article, nous allons examiner en détail comment utiliser PyQt Lab pour ouvrir et enregistrer des images à partir et vers un fichier.

PyQt Lab’ : Ouvrir/Enregistrer une image (QPixmap et QImage) depuis/dans un fichier

Par X. HINAULT – Juin 2013

PyQt Lab’ : Ouvrir/Enregistrer une image (QPixmap et QImage) depuis/dans un fichier PyQt Lab’ : Ouvrir/Enregistrer une image (QPixmap et QImage) depuis/dans un fichier

Ce que l’on va faire ici

  • Dans ce code PyQt, je montre comment enregistrer / ouvrir un fichier image à l’aide d’une interface PyQt. Ce code ouvre la voie à l’enregistrement d’images obtenues par calcul, traitement, capture, etc.. au sein d’une interface PyQt.
  • Cette interface permet :
    • de créer un fichier image (bouton <NOUVEAU>)
    • d’enregistrer un fichier image (bouton <ENREGISTRER>)
    • d’ouvrir un fichier image existant (bouton <OUVRIR>) et de le redimensionner pour affichage dans un QLabel
  • Ce code crée un dessin par défaut et ne permet pas d’interagir avec l’image, mais ceci sera fait dans un code à venir.

Pré-requis

  • python 2.7
  • pyqt4.x

Le fichier d’interface *.py

  • Fichier obtenu automatiquement avec l’utilitaire pyuic4 à partir du fichier *.ui créé avec QtDesigner :
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file
#
# Created: Sat Jun 15 09:50:11 2013
#      by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8(« Form »))
        Form.resize(334, 323)
        self.labelImage = QtGui.QLabel(Form)
        self.labelImage.setGeometry(QtCore.QRect(5, 15, 320, 240))
        self.labelImage.setStyleSheet(_fromUtf8(« background-color: rgb(180, 180, 180); »))
        self.labelImage.setText(_fromUtf8(«  »))
        self.labelImage.setObjectName(_fromUtf8(« labelImage »))
        self.pushButtonNouveauImage = QtGui.QPushButton(Form)
        self.pushButtonNouveauImage.setGeometry(QtCore.QRect(5, 290, 86, 27))
        self.pushButtonNouveauImage.setObjectName(_fromUtf8(« pushButtonNouveauImage »))
        self.pushButtonEnregistrerImage = QtGui.QPushButton(Form)
        self.pushButtonEnregistrerImage.setGeometry(QtCore.QRect(185, 290, 86, 27))
        self.pushButtonEnregistrerImage.setObjectName(_fromUtf8(« pushButtonEnregistrerImage »))
        self.lineEditCheminImage = QtGui.QLineEdit(Form)
        self.lineEditCheminImage.setGeometry(QtCore.QRect(5, 262, 321, 26))
        self.lineEditCheminImage.setObjectName(_fromUtf8(« lineEditCheminImage »))
        self.pushButtonOuvrirImage = QtGui.QPushButton(Form)
        self.pushButtonOuvrirImage.setGeometry(QtCore.QRect(95, 290, 85, 27))
        self.pushButtonOuvrirImage.setObjectName(_fromUtf8(« pushButtonOuvrirImage »))

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate(« Form », « PyQt : dessin : enregistrer fichier », None, QtGui.QApplication.UnicodeUTF8))
        self.pushButtonNouveauImage.setText(QtGui.QApplication.translate(« Form », « Nouveau », None, QtGui.QApplication.UnicodeUTF8))
        self.pushButtonEnregistrerImage.setText(QtGui.QApplication.translate(« Form », « Enregistrer », None, QtGui.QApplication.UnicodeUTF8))
        self.pushButtonOuvrirImage.setText(QtGui.QApplication.translate(« Form », « Ouvrir », None, QtGui.QApplication.UnicodeUTF8))

if __name__ == « __main__ »:
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

 

Le fichier d’application *Main.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

# par X. HINAULT – Mai 2013 – Tous droits réservés
# GPLv3 – www.mon-club-elec.fr

# modules a importer
from PyQt4.QtGui import *
from PyQt4.QtCore import *  # inclut QTimer..
import os,sys

from  tuto_pyqt_dessin_qpixmap_save_file import * # fichier obtenu à partir QtDesigner et pyuic4

# +/- variables et objets globaux

class myApp(QWidget, Ui_Form): # la classe reçoit le Qwidget principal ET la classe définie dans test.py obtenu avec pyuic4
        def __init__(self, parent=None):
                QWidget.__init__(self) # initialise le Qwidget principal
                self.setupUi(parent) # Obligatoire

                # — Variables de classe

                # — Paramétrage des widgets de l’interface GUI si nécessaire —

                # — Connexions entre signaux des widgets et fonctions
                # connecte chaque signal utilisé des objets à l’appel de la fonction voulue

                self.connect(self.pushButtonOuvrirImage, SIGNAL(« clicked() »), self.pushButtonOuvrirImageClicked)  # connecte le signal Clicked de l’objet à l’appel de la fonction voulue
                self.connect(self.pushButtonEnregistrerImage, SIGNAL(« clicked() »), self.pushButtonEnregistrerImageClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
                self.connect(self.pushButtonNouveauImage, SIGNAL(« clicked() »), self.pushButtonNouveauImageClicked) # connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue

                # — Code actif initial  —

                # Dessin avec QPixmap (affichage) et QImage (I/O, accès pixels)

                # création d’un QImage permettant l’accès aux pixels
                self.image=QImage(self.labelImage.size(),QImage.Format_RGB32) # crée image RGB 32 bits même taille que label

                #– initialisation du QImage
                self.image.fill(QColor(255,255,255)) # fond blanc

                # coordonnées centre du QPixmap (même taille que label)
                xo=self.image.width()/2
                yo=self.image.height()/2

                #trace le point
                #self.image.setPixel(xo,yo,qRgb(0,0,0)) # modifie la couleur du pixel x,y – noter qRgb renvoie valeur RGB 0xFFRRGGBB

                #— dessin initial sur QImage —
                self.painterImage=QPainter(self.image) # associe QPainter (classe de dessin) au Qimage

                # tracé de formes
                self.painterImage.setPen(QPen(QColor(0,0,255),2)) # fixe la couleur du crayon et la largeur pour le dessin – forme compactée           
                self.painterImage.drawRect(10,10,50,50) # dessin rectangle : drawRect (self, int x, int y, int w, int h)
                #self.painterImage.drawPoint(xo,yo) # trace un point drawPoint (self, int x, int y)
                #self.painterImage.fillRect(150,150,30,30,QColor(255,255,0)) # fillRect (self, int x, int y, int w, int h, QColor b)
                self.painterImage.drawEllipse(xo,yo,50,50) # dessin cercle – x-y = coin sup gauche rect encadrant : drawEllipse (self, int x, int y, int w, int h)
                #self.painterImage.drawEllipse(QPointF(xo,yo),50,50) # dessin cercle avec x,y centre et rayon : drawEllipse (self, QPointF center, float rx, float ry)
                self.painterImage.drawLine(0,0,xo*2,yo) # trace une ligne : drawLine (self, int x1, int y1, int x2, int y2)
                #self.painterImage.drawText(QPointF(xo/2, yo/2), « Hello ») # drawText (self, QPointF p, QString s)

                # il existe d’autres possibilités de dessin (polygone, chemin, etc..) voir : http://pyqt.sourceforge.net/Docs/PyQt4/qpainter.html

                self.painterImage.end() # ferme le painter – n’est plus accessible après

                # — fin dessin sur QImage

                #– Initialisation du QPixmap
                self.pixmap=QPixmap.fromImage(self.image) # initialise  le QPixmap…

                self.updatePixmap()

        # — les fonctions appelées, utilisées par les signaux des widgets —

        def pushButtonOuvrirImageClicked(self):
                print(« Bouton <Sélectionner Fichier> appuyé »)

                # ouvre fichier en tenant compte du chemin déjà saisi dans le champ
                if self.lineEditCheminImage.text()==«  »:
                        self.filenameImage=QFileDialog.getOpenFileName(self, ‘Ouvrir fichier’, os.getenv(‘HOME’)) # ouvre l’interface fichier – home par défaut
                        #self.filename=QFileDialog.getOpenFileName(self, ‘Ouvrir fichier’, QDir.currentPath()) # ouvre l’interface fichier – chemin courant par défaut
                else:
                        info=QFileInfo(self.lineEditCheminImage.text()) # définit un objet pour manipuler info sur fichier à partir chaine champ
                        print info.absoluteFilePath() # debug  
                        self.filenameImage=QFileDialog.getOpenFileName(self, ‘Ouvrir fichier’, info.absoluteFilePath()) # ouvre l’interface fichier – à partir chemin

                #self.filename=QFileDialog.getOpenFileName(self, ‘Ouvrir fichier’, os.getenv(‘HOME’)) # ouvre l’interface fichier – home par défaut
                #self.filename=QFileDialog.getOpenFileName(self, ‘Ouvrir fichier’, QDir.currentPath()) # ouvre l’interface fichier – chemin courant par défaut
                # getOpenFileName ouvre le fichier sans l’effacer

                print(self.filenameImage) # affiche le chemin obtenu dans la console
                self.lineEditCheminImage.setText(self.filenameImage) # affiche le chemin obtenu dans le champ texte

                self.image.load(self.filenameImage)
                self.image=self.image.scaled(self.labelImage.size()) # redimensionne l’image
                self.updatePixmap() # met à jour le pixmap et qlabel

        def pushButtonNouveauImageClicked(self):
                print(« Bouton NOUVEAU appuyé »)

                # ouvre fichier en tenant compte du chemin déjà saisi dans le champ
                if self.lineEditCheminImage.text()==«  »:
                        #self.filename=QFileDialog.getSaveFileName(self, ‘Ouvrir fichier’, os.getenv(‘HOME’)) # ouvre l’interface fichier – home par défaut
                        self.filenameImage=QFileDialog.getSaveFileName(self, ‘Ouvrir fichier’, os.getenv(‘HOME’), « *.png *.jpg;; *.gif ») # ouvre l’interface fichier – avec sélection
                        #self.filename=QFileDialog.getOpenFileName(self, ‘Ouvrir fichier’, QDir.currentPath()) # ouvre l’interface fichier – chemin courant par défaut
                else:
                        info=QFileInfo(self.lineEditCheminImage.text()) # définit un objet pour manipuler info sur fichier à partir chaine champ
                        print info.absoluteFilePath() # debug  
                        self.filenameImage=QFileDialog.getSaveFileName(self, ‘Ouvrir fichier’, info.absoluteFilePath(), « *.png *.jpg;; *.gif ») # ouvre l’interface fichier – à partir chemin – avec sélection
                        # ;; pour avoir choix de sélection sur plusieurs lignes ex : « Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml) »

                print(self.filenameImage)
                self.lineEditCheminImage.setText(self.filenameImage)

        def pushButtonEnregistrerImageClicked(self):           
                print(« Bouton <ENREGISTRE> appuyé »)                    

                if self.lineEditCheminImage.text()!=«  »:

                        self.image.save(self.filenameImage) # le suffixe utilisé est celui du nom de fichier

        # — les fonctions appelées, utilisées par les signaux hors widgets —

        # — fonctions de classes autres—    

        # fonction de MAJ du QPixmap : chargement QImage +/- dessin + affichage dans QLabel
        def updatePixmap(self):

                # chargement du QImage dans le QPixmap
                self.pixmap.convertFromImage(self.image) # recharge le QImage dans le QPixmap existant – met à jour le QPixmap

                #– affichage du QPixmap dans QLabel
                self.labelImage.setPixmap(self.pixmap) # met à jour le qpixmap affiché dans le qlabel  

# — Autres Classes utiles —

# — Classe principale (lancement)  —
def main(args):
        a=QApplication(args) # crée l’objet application
        f=QWidget() # crée le QWidget racine
        c=myApp(f) # appelle la classe contenant le code de l’application
        f.show() # affiche la fenêtre QWidget
        r=a.exec_() # lance l’exécution de l’application
        return r

if __name__==« __main__ »: # pour rendre le code exécutable
        main(sys.argv) # appelle la fonction main

Utilisation

  • Les 2 fichiers suivants sont à enregistrer dans un même répertoire, l’un en nom.py et l’autre en nomMain.py.
  • Puis lancer l’application depuis Geany ou équivalent, en exécutant le fichier nomMain.py
  • Pour créer un nouveau fichier : clic sur <NOUVEAU> et choisir le chemin voulu dans la fenêtre qui s’ouvre.
  • Pour enregistrer le fichier : clic sur <ENREGISTRER>. Le chemin défini avec <NOUVEAU> est utilisé.
  • Pour ouvrir un fichier : clic sur <OUVRIR> et choisir le fichier dans la fenêtre qui s’ouvre.
Noter cet article

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Archive Mon Club Elec

Articles populaires

Newsletter

Inscrivez-vous maintenant et bénéficiez d'un soutien continu pour réaliser vos travaux électriques en toute sécurité.