Partage
  • Partager sur Facebook
  • Partager sur Twitter

Enregistrer une image de Surface dessinée pygame

Sujet résolu
    11 septembre 2019 à 20:24:42

    Bonjour,

    Je suis encore débutant, et je fais un programme pour dessiner avec pygame, cela fonctionne. Pour faire ceci je dessine avec des

    pygame.draw.rect(surface, couleur, position, (hauteur,largeur))

    J'aimerai enregistrer la surface dessinée dans mes fichiers avec :

    pygame.image.save(surface, "image.png")

    Alors bien évidemment au début de mon programme j'ai écrit

    screen = pygame.display.set_mode((400, 400))

    et lorsque j'enregistre l'image avec "screen" en tant que Surface ça m'enregistre bien tout ce qui est présent dans pygame.

    Mon problème est que j'ai placé une seconde surface, plus petite que "screen", que j'ai appelée "planche" (dans laquelle je dessine j'ai fait en sorte qu'on ne puisse pas dessiner à l’extérieur de la surface) :

    taille_planche = (200,200)
    planche = pygame.Surface(taille_planche)
    planche.fill((255, 255, 255))
    screen.blit(planche,(100,100))

    (Je simplifie les vraies valeurs qui n'ont rien à voir)

    Donc je dessine sur la surface "planche" puis quand je fais

    pygame.image.save(planche,"image.png")

    Surprise, ça ne m'enregistre qu'une surface vide, de la couleur que je définis dans planche.fill(), donc je ne comprend pas pourquoi "screen" à le droit de mettre en image tous les éléments, et pas "planche". Y a t'il une solution, ou fais-je vraiment n'importe quoi svp ?

    Par ailleur lorsque que je fais

    pygame.draw.rect(surface, couleur, position, (hauteur,largeur))

    Je suppose qu'il faut le faire sur la Surface "planche", mais je suis quand même obligé de le faire sur la Surface "screen", sinon rien n'apparaît, mais ça me paraît logique (donc deux fois cette ligne de code avec les deux surfaces en question). Je ne sais pas si la cause du problème est là-dedans.

    • Partager sur Facebook
    • Partager sur Twitter
      11 septembre 2019 à 22:18:51

      Donne tout ton code mais je pense que c'est une histoire de lignes pas dans le bon ordre (le 'raisonnement' est bon normalement)

      -
      Edité par Coliculus 11 septembre 2019 à 22:19:19

      • Partager sur Facebook
      • Partager sur Twitter
        11 septembre 2019 à 22:43:09

        import pygame         ##pygame
        from pygame.locals import *
        import time         ##temps
        import random         ##aléatoire
        import os
        
        os.environ['SDL_VIDEO_CENTERED'] = "%d,%d"          ##centrer les fenêtres
        
        
        pygame.init()
        
        screen = pygame.display.set_mode((1500, 800))
        pygame.display.set_caption("Grafitix")
        screen.fill((255, 255, 255))
        pygame.display.flip()
        
        taille_planche_f = (1420,650)         ##planche de fond
        planchef = pygame.Surface(taille_planche_f)
        planchef.fill((230, 230, 210))
        screen.blit(planchef,(78,148))
        
        
        planchet_taille_x=400
        planchet_taille_y=400
        while planchet_taille_x>1300:
            planchet_taille_x=int(input("x"))
        while planchet_taille_y>600:
            planchet_taille_y=int(input("y"))
        
        taille_planche_t = (planchet_taille_x,planchet_taille_y)         ##planche de travail
        planchet = pygame.Surface(taille_planche_t)
        planchet.fill((255, 255, 255))
        x_planchet = (750-(planchet_taille_x/2))
        y_planchet = ((800/2)-(planchet_taille_y/2)+148/2)
        screen.blit(planchet,(x_planchet,y_planchet))
        
        
        lim_planchet_x1=int(750-(planchet_taille_x/2))
        lim_planchet_x2=int(lim_planchet_x1+planchet_taille_x)
        lim_planchet_y1=int((800/2)-(planchet_taille_y/2)+148/2)
        lim_planchet_y2=int(lim_planchet_y1+planchet_taille_y)
        
        
        taille_zone_libre_haut = (1500,148)
        zone_libre_haut = pygame.Surface(taille_zone_libre_haut)
        zone_libre_haut.fill((65, 65, 55))
        screen.blit(zone_libre_haut,(0,0))
        
        taille_zone_libre_bas = (1500,2)
        zone_libre_bas = pygame.Surface(taille_zone_libre_bas)
        zone_libre_bas.fill((65, 65, 65))
        screen.blit(zone_libre_bas,(0,798))
        
        taille_zone_libre_gauche = (78,800)
        zone_libre_gauche = pygame.Surface(taille_zone_libre_gauche)
        zone_libre_gauche.fill((65, 65, 55))
        screen.blit(zone_libre_gauche,(0,0))
        
        taille_zone_libre_droite = (78,800)
        zone_libre_droite = pygame.Surface(taille_zone_libre_droite)
        zone_libre_droite.fill((65, 65, 55))
        screen.blit(zone_libre_droite,(1422,148))
        
        
        CRAYON = True
        
        
        principale=1
        co_pointeur=(0,0)
        new_co_pointeur=(0,0)
        hauteur_point=1         ##crayon
        largeur_point=1         ##crayon
        rond = True
        carré = False
        limx1=50
        limx2=1496
        limy1=150
        limy2=796
        
        point1=False
        point2=False
        
        r=0
        v=0
        b=0
        
        
        
        pygame.display.flip()
        pygame.key.set_repeat(300,50)
        
        while principale==1:
        
            for event in pygame.event.get():
        
                if CRAYON==True:
        
                    if (event.type == KEYDOWN and event.key == K_ESCAPE) or (event.type == QUIT):          ##quitter le programme
                        principale=0
        
                    if (event.type == KEYDOWN and event.key == K_KP9):          ##changer la couleur en code RVB
                        r=int(input())
                        v=int(input())
                        b=int(input())
        
        
                    if (event.type == KEYDOWN and event.key == K_KP3):          ##enregistrer le travail
        
                        _format=str(input("format"))
                        nom=str(input("nom"))
                        if _format == "png":
                            pygame.image.save(planchet,nom+".png")
                        if _format == "jpg":
                            pygame.image.save(planchet,nom+".jpg")
                        if _format == "jpeg":
                            pygame.image.save(planchet,nom+".jpeg")
        
        
                    if (event.type == KEYDOWN and (event.key == K_KP_PLUS or event.key == K_PLUS)) and hauteur_point<=99 and largeur_point<=99:         ##augmenter la taille du crayon
                                hauteur_point+=1
                                largeur_point+=1
                                print("hauteur",hauteur_point)
        
                    if (event.type == KEYDOWN and (event.key == K_KP_MINUS or event.key == K_MINUS)) and hauteur_point>=2 and largeur_point>=2:         ##diminuer la taille du crayon
                            hauteur_point-=1
                            largeur_point-=1
                            print("hauteur",hauteur_point)
        
        
        
        
                    if (event.type == KEYDOWN and event.key == K_KP1):         ##changer de pinceau
                        rond = True
                        carré = False
                    if (event.type == KEYDOWN and event.key == K_KP2):         ##changer de pinceau
                        rond = False
                        carré = True
        
        
                    co_pointeur = pygame.mouse.get_pos()
                    (x_co_pointeur,y_co_pointeur)=co_pointeur
        
                    if pygame.mouse.get_pressed()[0]==True:         ##détecter le clique et déplacement de la souris si le clique est maintenu
        
                      if (lim_planchet_x1)<x_co_pointeur<(lim_planchet_x2) and (lim_planchet_y1)<y_co_pointeur<(lim_planchet_y2):
        
                        if new_co_pointeur!=co_pointeur:
                            print(co_pointeur)
                            new_co_pointeur = co_pointeur
                            x_point, y_point = co_pointeur
        
                            if rond == True:         ##afficher un point rond
                                pygame.draw.circle(screen, (r,v,b),[x_point,y_point],round(hauteur_point/2))
                                pygame.draw.circle(planchet, (r,v,b),[x_point,y_point],round(hauteur_point/2))
        
        
                            if carré == True :         ##afficher un pixel
                                pygame.draw.rect(screen, (r,v,b),[(x_point-(largeur_point/2)),(y_point-(largeur_point/2)),hauteur_point,largeur_point])
                                pygame.draw.rect(planchet, (r,v,b),[(x_point-(largeur_point/2)),(y_point-(largeur_point/2)),hauteur_point,largeur_point])
        
                            pygame.display.update()
        
        pygame.quit()

        Voilà j'ai fait de mon mieux pour enlever tous les trucs inutiles pour mon problème, et il est toujours présent donc c'est bien là-dedans.

        Oui c'est différent de ce que j'ai décrit mais le problème est le même, je l'avais juste simplifié.

        Désolé c'est absolument pas optimisé je connais pas suffisamment tous les modules, c'est peut-être pas très clair, et il y a peut-être trop de lignes inutiles que j'ai pas enlevées. Mais tu peux essayer mon programme, appuis sur la touche 3 pour avoir un input(), tu choisis le format en écrivant png/jpeg/jpg puis le nom du fichier dans le second input()

        -
        Edité par MilanNicolas 11 septembre 2019 à 22:51:32

        • Partager sur Facebook
        • Partager sur Twitter
          11 septembre 2019 à 23:17:40

          import pygame         ##pygame
          from pygame.locals import *
          import time         ##temps
          import random         ##aléatoire
          import os
           
          os.environ['SDL_VIDEO_CENTERED'] = "%d,%d"          ##centrer les fenêtres
           
           
          pygame.init()
           
          screen = pygame.display.set_mode((1500, 800))
          pygame.display.set_caption("Grafitix")
          screen.fill((255, 255, 255))
          pygame.display.flip()
           
          taille_planche_f = (1420,650)         ##planche de fond
          planchef = pygame.Surface(taille_planche_f)
          planchef.fill((230, 230, 210))
          screen.blit(planchef,(78,148))
           
           
          planchet_taille_x=400
          planchet_taille_y=400
          while planchet_taille_x>1300:
              planchet_taille_x=int(input("x"))
          while planchet_taille_y>600:
              planchet_taille_y=int(input("y"))
           
          taille_planche_t = (planchet_taille_x,planchet_taille_y)         ##planche de travail
          planchet = pygame.Surface(taille_planche_t)
          planchet.fill((255, 255, 255))
          x_planchet = (750-(planchet_taille_x/2))
          y_planchet = ((800/2)-(planchet_taille_y/2)+148/2)
          screen.blit(planchet,(x_planchet,y_planchet))
           
           
          lim_planchet_x1=int(750-(planchet_taille_x/2))
          lim_planchet_x2=int(lim_planchet_x1+planchet_taille_x)
          lim_planchet_y1=int((800/2)-(planchet_taille_y/2)+148/2)
          lim_planchet_y2=int(lim_planchet_y1+planchet_taille_y)
          # toutes ces infos là tu peux souvent les avoir directement avec Surface.get_rect().w par exemple pour la largeur, h pour la hauteur
           
          taille_zone_libre_haut = (1500,148)
          zone_libre_haut = pygame.Surface(taille_zone_libre_haut)
          zone_libre_haut.fill((65, 65, 55))
          screen.blit(zone_libre_haut,(0,0))
           
          taille_zone_libre_bas = (1500,2)
          zone_libre_bas = pygame.Surface(taille_zone_libre_bas)
          zone_libre_bas.fill((65, 65, 65))
          screen.blit(zone_libre_bas,(0,798))
           
          taille_zone_libre_gauche = (78,800)
          zone_libre_gauche = pygame.Surface(taille_zone_libre_gauche)
          zone_libre_gauche.fill((65, 65, 55))
          screen.blit(zone_libre_gauche,(0,0))
           
          taille_zone_libre_droite = (78,800)
          zone_libre_droite = pygame.Surface(taille_zone_libre_droite)
          zone_libre_droite.fill((65, 65, 55))
          screen.blit(zone_libre_droite,(1422,148))
           
           
          CRAYON = True
           
           
          principale=1
          co_pointeur=(0,0)
          new_co_pointeur=(0,0)
          hauteur_point=1         ##crayon
          largeur_point=1         ##crayon
          rond = True
          carré = False
          limx1=50
          limx2=1496
          limy1=150
          limy2=796
           
          point1=False
          point2=False
           
          r=0
          v=0
          b=0
           
           
           
          pygame.display.flip()
          pygame.key.set_repeat(300,50)
           
          while principale: # ICI pas besoin de == 1
           
              for event in pygame.event.get():
           
                  if CRAYON: # Pas besoin de == 1 ou == True
           
          
                      # ICI moi je met tout dans un KEYDOWN pour pas répéter puis je refais les if avec que key dedans
                      if (event.type == KEYDOWN and event.key == K_ESCAPE) or (event.type == QUIT):          ##quitter le programme
                          principale=0
           
                      if (event.type == KEYDOWN and event.key == K_KP9):          ##changer la couleur en code RVB
                          r=int(input())
                          v=int(input())
                          b=int(input())
           
           
           
           
           
           
                      if (event.type == KEYDOWN and event.key == K_KP1):         ##changer de pinceau
                          rond = True
                          carré = False
                      if (event.type == KEYDOWN and event.key == K_KP2):         ##changer de pinceau
                          rond = False
                          carré = True
           
           
                      co_pointeur = pygame.mouse.get_pos()
                      (x_co_pointeur,y_co_pointeur)=co_pointeur
           
                      if pygame.mouse.get_pressed()[0]==True: # pareil == True inutile         ##détecter le clique et déplacement de la souris si le clique est maintenu
           
                        if (lim_planchet_x1)<x_co_pointeur<(lim_planchet_x2) and (lim_planchet_y1)<y_co_pointeur<(lim_planchet_y2):
                           # ICI remplaceable par : if planchet.get_rect().collidepoint(co_pointeur)
          

          J'ai fais quelque remarques (il y en aurait d'autres ^^) mais en fait j'ai compris, tu dessine à l'écran et sur l'image mais tu n'as pas décalé la position pour l'image donc tu dessine en dehors en fait d'où l'image blanche. Mais le problème principal c'est surtout que tu devrais dessiner juste sur l'image en corrigeant la position du clic et afficher l'image à l'écran sans dessiner dessus avec screen.blit(image, position).

          Exemple:

          import pygame
          from pygame.locals import *
          
          run = True
          screen = pygame.display.set_mode((1500,800))
          
          draw_color = (0,0,0)
          img = pygame.Surface((500,500)).convert()
          img.fill([255,255,255])
          decalage = 200,200
          
          while run:
              events = pygame.event.get()
              for event in events:
                  if event.type == QUIT:
                      run = False
          
              if pygame.mouse.get_pressed()[0]:
                  x, y = pygame.mouse.get_pos()
                  x -= decalage[0]
                  y -= decalage[1]
          
                  if img.get_rect().collidepoint([x,y]):
                      pygame.draw.circle(img, draw_color, (x, y), 5)
          
              screen.blit(img, decalage)
              pygame.display.update()
          
          pygame.image.save(img, "result.png")



          -
          Edité par Coliculus 11 septembre 2019 à 23:41:20

          • Partager sur Facebook
          • Partager sur Twitter
            11 septembre 2019 à 23:55:34

            Merci beaucoup, je regarde ça demain, et si je m'en sors bien je mets le message en résolu :D

            Une autre question si tu es d'accord (j'ai pas encore essayé tes solutions quand j'edit ce message).

            Lorsque tu dessines, tu as du remarqué qu'il y a des trous dans les tracés, qui sont surement causés par l'actualisation trop longue de mes boucles... cela peut-il être corrigé ? Ou plus le pc sera puissant, moins ces trous apparaîtront ? (car sur un mauvais pc, j'ai pu remarquer que c'est encore pire)

            Si tu ne vois pas de quoi je parle, trace un trait rapide sur la surface et tu pourras constater que les pixels sont écartés en pointillés

            -
            Edité par MilanNicolas 12 septembre 2019 à 0:39:52

            • Partager sur Facebook
            • Partager sur Twitter
              12 septembre 2019 à 18:11:33

              Je vois de quoi tu parle c'est un problème qui existera toujours, pour le 'parer' tu peux interpoler le tracé à partir des points. Il y a des interpolations plus ou moins complexes mais tu peux commencer par déjà juste tracer des lignes qui font la même épaisseur que tes cercles entre chaque point. Si tu dessine pas trop vite le résultat est généralement presque invisible ...

              -
              Edité par Coliculus 12 septembre 2019 à 18:13:51

              • Partager sur Facebook
              • Partager sur Twitter
                12 septembre 2019 à 19:29:43

                En effet merci beaucoup pour cette idée simple, dans mon programme complet j'ai déjà ajouté des choses comme les lignes donc ce ne sera pas un problème à utiliser, j'ai juste à faire un pygame.draw.line() entre les coordonnées des deux derniers points placés.

                Certes, il ne faudra pas dessiner trop vite pour pas que ce soit laid mais en soit c'est déjà laid lorsqu'on dessine trop vite, donc cette méthode me permettra quand même de dessiner un peu plus vite toujours en étant un peu limiter mais ce sera mieux.

                Bref merci pour tes réponses, première fois que je pose une question sur ce forum, bah j'ai bien fait :D

                Edit : Cette technique marche très bien, même en étant rapide, sauf lors de changement brusque de direction on remarque trop le rond/carré (sauf si la taille du crayon est petite). Bref, c'est parfait

                -
                Edité par MilanNicolas 12 septembre 2019 à 19:59:10

                • Partager sur Facebook
                • Partager sur Twitter

                Enregistrer une image de Surface dessinée pygame

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                • Editeur
                • Markdown