IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Zoom sur QImage [QtGui]


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 102
    Par défaut Zoom sur QImage
    Bonjour à tous,

    nouvel épisode de mon application, j'ai réussi à effectuer un zoom malgré tout mes outils de fonctionne pas tous avec les niveaux de zoom différents de 100%.
    Je vous remercie d'avance pour la lecture de mon post ^^ et vos conseils.
    J'ai donc une combo box dans ma fênetre principale associée au signal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     def onActivatedComboBox(self,text):        
     
            if text == "300%":
                self.__actionZoom(3)
            if text=="200%":
                self.__actionZoom(2)
            if text == "100%":
                self.__actionZoom(1)
            if text == "75%":
                self.__actionZoom(0.75)
            if text == "50%":
                self.__actionZoom(0.5)
    qui appelle l'action zoom qui est en faite celle de la scène ( elle renvoie aussi l'index à mes outils pour connaitre le facteur de zoom).
    Puis, dans ma scène, l'action zoom.
    GraphicsScene.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
      def zoomAction(self, factor ):
            print "zoom : ", factor
     
            #Not rezoom in same factor
            if factor == self.oldFactor:
                pass
            else :
                self.image = self.getCurrentImage()
                w_img, h_img = self.image.width(), self.image.height()
                w, h = w_img * factor, h_img * factor
                self.pixmap = QPixmap().fromImage(self.image.scaled(w, h, 
                                                   Qt.KeepAspectRatio, 
                                                   Qt.SmoothTransformation))
     
                #Copy of the old one to keep the trace of the items before the zoom
                self.pixItem = PixmapItem(self,self._model)
                self.pixItem.setPixmap(self.pixmap)
     
                self.clear()
                self.addItem(self.pixItem)
                self.pixItem.undoView.hide()
                #Adjusting the size of the scene to the new zooming pixmap
                self.setSceneRect(0, 0, w, h)
                self.oldFactor = factor
    Elle recrée pour chaque niveau de zoom un pixItem intégré à la scène.
    Sachant que pixmapItem gère les actions. (j'arrive bientôt à mon problème lol)
    PixmapItem.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    '''
     PixmapItem handles :
         + Mouses events
         + by calling the currentTool set in the Model
    '''
    class PixmapItem(QGraphicsPixmapItem):
        def __init__(self, scene, model, pixmap=None, parent=None ):
            super(PixmapItem, self).__init__()
            self.scene = scene
            self._model = model
            self.currentTool = None
     
            #Undostack has all the actions to undo/redo shapes
            self.undoStack = QUndoStack()
     
            # Here we can fix the limit of the actions saved
            self.undoStack.setUndoLimit(200)
            '''
            
            TODO:
                + autorub, allows you to rub automatically the color selected from the pixel
                
            '''
            self._createUndoView()
     
        def _createUndoView(self):
            # we give the undoview the stack with all the items to display the actions
            self.undoView = QUndoView(self.undoStack)
            self.undoView.setWindowTitle("Commands list")
            self.undoView.setAttribute(Qt.WA_QuitOnClose,False)
          def mousePressEvent(self, event):
            tool = self._model.currentTool()
              if tool is not None:
                      tool.mousePress(event)
          #etc.. pour move et release
    Mon souci est le suivant , j'ai un outil pipette qui fonctione bien avec le zoom,
    j'applique seulement le facteur comme ceci .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    color = self.scene().getCurrentImage().pixel(int(x/self.getZoomFactor()), int(y/self.getZoomFactor()))
    Je divise les coordonnées par le facteur et cela fonctionne. Mais avec un outil d'effacement d'une couleur, cela ne fonctione pas du tout.
    ColorEraserTool
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    class ColorEraserTool(AbstractTool):
     
        def __init__(self,*args):
            AbstractTool.__init__(self,*args)
     
            self._model = self.model()
            self.pen = QPen(Qt.SolidLine)
            self.brush = QBrush()
            self.color = QColor()
            self._colorPix = QColor(Qt.white)
            self._name = 'ColorEraserTool'
            self._cursor = QCursor()
            self.x = 0
            self.y = 0
            self._deltaE=0
            self._image = QImage()
            self.pixmap = None
            self.pixmapItem = None
     
            #Allows to get the right color when zoom in Action        
            self._zoomFactor = 1
            #List of the items to put into undostack
            self.items = []
        def getZoomFactor(self):
            return self._zoomFactor
        def setZoomFactor(self,fact):
            self._zoomFactor = fact                   
        def name(self):
            return self._name
     
        def cursor(self):
            _img = QPixmap(2*self._model.width(),2*self._model.width())
            _p = QPainter(_img)
            _p.fillRect(_img.rect(), QBrush(QColor(self._model.foregroundColor())))
            _p.end()
            self._cursor = QCursor(_img,-16,-16)#   
            return self._cursor
     
        def choose(self, p):
            foreColor = QColor(self._model.foregroundColor())
            c_hsv = foreColor.toHsv()
            p_hsv = p.toHsv()
            colorDist =self.color_dist(c_hsv,p_hsv)
            if colorDist < 0.5:
                #print "colorDist",colorDist
                if c_hsv.valueF() !=0 :
                    p_hsv.setHsvF(p_hsv.hueF(), 0, min(1.0, p_hsv.valueF() / c_hsv.valueF()))
                    return p_hsv.toRgb()
            else:
                return p
     
     
     
        def erase(self, x, y):
            self._colorPix = pc = QColor(self.getImage().pixel(x, y))
            #if pc != Qt.white and self.colorDist() < 20:
            #    return 
            if pc != Qt.white:
                return self.choose(pc)
     
        def applyRubber(self, mx, my):
            w = self._model.width()
            pm = QPixmap(w * 2, w * 2)
            pm.fill(Qt.transparent)
            p = QPainter(pm)
            for x in xrange(-w, w):
                for y in xrange(-w, w):
                    #mx,my = int(mx/self.getZoomFactor()), int(my/self.getZoomFactor())
                    c = self.erase(mx + x, my + y)
                    if c is not None :
                        p.setPen(c)
                        p.drawPoint(x + w, y + w)
            p.end()
            p = QPainter(self.pixmap)
            #mx,my = int(mx * self.getZoomFactor()),int(my * self.getZoomFactor())
            print "Mx , my", mx ,",", my
            p.drawPixmap(mx - w, my - w, pm)
            p.end()
            self.pixmapItem.setPixmap(self.pixmap)
     
        def overlay(self):
            #Creates an overlay on which we 'll apply the rub
            self.pixmap = QPixmap(self.getImage().size())
            self.pixmap.fill(Qt.transparent)
            self.pixmapItem = QGraphicsPixmapItem()
            self.scene().addItem(self.pixmapItem)
            self.items.append(self.pixmapItem)
     
        def getImage(self):
            #Get the image from the scene newly updated
            return self._image
     
        def setImage(self,img):
            self._image= img
     
        def color_dist(self, c1, c2):
            """ returns the squared euklidian distance between two color vectors in hsv space """
            _result = (abs(c1.hueF()-c2.hueF()))**2 + (abs(c1.saturationF() - c2.saturationF()))**2 + (abs(c1.valueF()-c2.valueF()))**2
            return (_result ** 0.5)
     
        def mousePress(self, event):
            self.items = []
            x,y = event.pos().x(), event.pos().y()
            x,y = int(x/self.getZoomFactor()), int(y/self.getZoomFactor())
            self.setImage(self.scene().getCurrentImage())
            self.overlay()
            self.applyRubber(x,y)
     
     
        def mouseMove(self, event):
            x,y = event.pos().x(), event.pos().y()
            x,y = int(x/self.getZoomFactor()), int(y/self.getZoomFactor())
            self.applyRubber(x,y)
            self.scene().update()
     
        def mouseRelease(self, event):
            for i in range(0,len(self.items)):
                addCmd = AddCommand(self.items[i], self.scene(), self.name())
                self.scene().pixItem.undoStack.push(addCmd)
            self.pixmap = None
            self.pixmapItem = None
    C'est à dire que la division ne fonctionne pas quand l'index est différent de 1 bien sur, le résultat est que l'image que je souhaite modifier est dessinée à un
    autre endroit.
    Merci d'avance ^^.

  2. #2
    Membre expérimenté Avatar de ashren
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2012
    Messages : 101
    Par défaut
    Bonjour, tu as essayé ceci http://www.riverbankcomputing.co.uk/...iew.html#scale avant de ré-implémenter le zoom depuis zéro ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 102
    Par défaut
    Je pense que je le fais déjà ici

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    self.pixmap = QPixmap().fromImage(self.image.scaled(w, h, 
                                                   Qt.KeepAspectRatio, 
                                                   Qt.SmoothTransformation))
    Où tu veux dire qu'il faut le faire dans le ColorPickerTool ?

  4. #4
    Membre expérimenté Avatar de ashren
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2012
    Messages : 101
    Par défaut
    Le self.image ce n'est pas la QGraphicsView, si ? (ce n'est pas très clair ce qu'il y a dedans).

    D'autre part, le scale dont j'ai fait mention ne retourne rien.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 102
    Par défaut
    Non, la self.image, c'est l'image courante.

    Le problème, je n'ai pas accès réellement à la view je l'appel uniquement dans la fênetre principale.

    Le soucis, c'est que les cordonnées sont bons dans la pipette mais pas l'autre tool ce qui est étrange :s.

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 102
    Par défaut UP^^
    J'ai trouvé la source du problème , c'est les coordonnées détectées dans le ColorEraser sont étranges (ils ne correspondent pas aux dimensions de la scène) à cause du zoom.
    Ce qui est étonnant, c'est avec le Colorpicker, cela marche par division.
    J'ai essayé avec mapToScene etc.. mais je ne vois pas trop comment faire :s ?

    si vous avez une idées, hésitez pas ^^.
    EDIT: tout le monde est en vacances , j'imagine, merci à toi Ashren quand même tu m'as bien aidé avant.
    J'espère qu'en avançant je vais résoudre ce problème mais d'autres se profilent peut être aurais -je plus d'aide la prochaine fois^^.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Zoom sur Tchart
    Par c@pu dans le forum C++Builder
    Réponses: 5
    Dernier message: 18/07/2005, 15h21
  2. [DirectX9] Plein écran et zoom sur texture
    Par SteelBox dans le forum DirectX
    Réponses: 10
    Dernier message: 21/03/2005, 23h26
  3. Zoom sur une image
    Par AurelBUD dans le forum C++Builder
    Réponses: 5
    Dernier message: 07/05/2004, 17h05
  4. zoom sur image de formulaire
    Par bourvil dans le forum VBA Access
    Réponses: 2
    Dernier message: 01/10/2003, 09h25
  5. Zoom sur des vecteurs ou lignes
    Par mat.M dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 25/11/2002, 10h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo