Ni Na
Ni Na

Reputation: 51

How to update image file realtime Pygame?

I import an image from file and that file always updates (always save the new picture in the same file name) and now when that image change in file My GUI not update must change page or do something that image will change I mean change on display. But I would like image change on display in real-time (change every time when an image in the file change)

And I write code like this :

def first():

    # crop
    img_crop = mpimg.imread('Crop.jpg')
    #img_crop = numpy.load('bur.npy')
    x = numpy.arange(10)
    y = numpy.arange(20)
    X, Y = numpy.meshgrid(x, y)
    img_crop_re = cv2.resize(img_crop, dsize=(200,200), interpolation=cv2.INTER_CUBIC)
    img_crop_ro = cv2.rotate(img_crop_re, cv2.ROTATE_90_COUNTERCLOCKWISE)
    img_crop_flip = cv2.flip(img_crop_ro,0)
    surf_crop = pygame.surfarray.make_surface(img_crop_flip)

    # mask
    img_mask = mpimg.imread('mask.jpg')
    #img_mask = numpy.load('bur.npy')
    x = numpy.arange(10,50)
    y = numpy.arange(20,50)
    X, Y = numpy.meshgrid(x, y)
    img_mask_re = cv2.resize(img_mask, dsize=(200, 200), interpolation=cv2.INTER_CUBIC)
    img_mask_ro = cv2.rotate(img_mask_re, cv2.ROTATE_90_COUNTERCLOCKWISE)
    img_mask_flip = cv2.flip(img_mask_re,0)
    surf_mask = pygame.surfarray.make_surface(img_mask_flip)


    running = True
    while running:
        screen.fill((30,30,30))

        screen.blit(surf_crop, (850, 360))
        screen.blit(surf_mask, (1170, 360))
       
        ...

        pygame.display.flip()
        pygame.display.update()
        mainClock.tick(60)

Upvotes: 5

Views: 706

Answers (2)

Kingsley
Kingsley

Reputation: 14916

Ideally you don't want to reload the image unless it has changed. One shortcut to this is to check the image file "last updated" time.

import os.path

IMAGE_PATH = "/path/to/image.jpg"
timestamp = os.path.getmtime( IMAGE_PATH )

Wrapping this together with the image loader:

class UpdatedImage:
    def __init__( self, filename ):
        self.filename    = filename
        self.last_update = 0         # trigger initial load
        self.image       = None      # final surface
        self.reLoadImage()           # make sure we load once, first
    
    def drawAt( self, window, position ):
        """ Draw the image to the screen at the given position """
        window.blit( self.image, position )

    def reLoadImage( self ):
        """ Load in the image iff it has changed on disk """
        current_file_time = os.path.getmtime( self.filename )
        if ( current_file_time > self.last_update ):
            self.last_update = current_file_time
            img_crop = mpimg.imread( self.filename )
            x = numpy.arange(10)
            y = numpy.arange(20)
            X, Y = numpy.meshgrid(x, y)
            img_crop_re = cv2.resize(img_crop, dsize=(200,200), interpolation=cv2.INTER_CUBIC)
            img_crop_ro = cv2.rotate(img_crop_re, cv2.ROTATE_90_COUNTERCLOCKWISE)
            img_crop_flip = cv2.flip(img_crop_ro,0)
            self.image = pygame.surfarray.make_surface(img_crop_flip)

Which would give you a main loop of:

crop_image = UpdatedImage( "Crop.jpg" )

running = True
while running:
    screen.fill((30,30,30))

    crop_image.reLoadImage()
    crop_image.drawAt( screen, ( 850, 360 ) )
    # ...

So although crop_image.reLoadImage() is called every frame, it only loads the image if it has a modified time in the future on the disk.

Upvotes: 3

Qiu YU
Qiu YU

Reputation: 519

Put the code that loads the image into the while loop so the image is repeatedly updated. This could slow down your program though. With this method, make sure the image name and position is exactly the same.

Upvotes: 4

Related Questions