Ren'Py What's the simplest way to show a random image from a folder?

rb813

Well-Known Member
Aug 28, 2018
1,217
778
I'm working on a mod of an existing game (which means I'm mostly just tweaking little things here and there, so I haven't needed a high level of expertise in Python so far), and I'd like to do a function where pressing a certain button will just yield a random image from a specific folder. I know you can do like
renpy.random.choice(["imageone.png", "imagetwo.png", "imagethree.png"]), but I'm expecting to have quite a lot of images in that folder, so I want to set it up where I can just move images in and out freely without having to rename or define them, or do anything additional to make them be recognized by the existing function. What's the best way to do that?
 
Last edited:

OscarSix

Active Member
Modder
Donor
Jul 27, 2019
829
6,671
I'm working on a mod of an existing game (which means I'm mostly just tweaking little things here and there, so I haven't needed a high level of expertise in ren'py so far), and I'd like to do a function where pressing a certain button will just yield a random image from a specific folder. I know you can do like
renpy.random.choice(["imageone.png", "imagetwo.png", "imagethree.png"]), but I'm expecting to have quite a lot of images in that folder, so I want to set it up where I can just move images in and out freely without having to rename or define them, or do anything additional to make them be recognized by the existing function. What's the best way to do that?
Python:
import os

modImageList = []

path = os.getcwd()
directory = path+"\images\Ep1"
for filename in os.listdir(directory):
    if filename.endswith(".webp") or filename.endswith(".png"):
        modImageList.append(os.path.join(directory, filename))
    else:
        continue

# Then you can use renpy.random.choice(modImageList) to get a random image
Note: Might need some tweaking and has not been tested just my thoughts on how to do it.
 

rb813

Well-Known Member
Aug 28, 2018
1,217
778
So that would go all the way at the top of the script, right?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,978
16,234
Note: Might need some tweaking and has not been tested just my thoughts on how to do it.

Python:
init python:
#  Not needed, the OS module is already available through the /renpy/ module.
#    import os

#  Totally correct. Placed here, the variable will not be saved, which is
# what HAVE to happen, in order to ensure the compatibility.
    modImageList = []

#  Normally have no reason to not works, but there's a safest way to do it.
# Ren'py have a /config.basedir/ variable which correspond to this, and a
# /config.game/ variable that point to the directory where the game content is
# located ; the later being more useful here.
#    path = os.getcwd()
#  Do NOT use "\" as path separator, it's specific to Windows, and Ren'py
# also works with MacOS, Linux, iOS and Android. If really you need to hard
# code it, use "/", which should be understood by all the OSes. But still it's
# better ot use /os.path.join/.
#  Also, this will not works because the "game" folder is missing.
#    directory = path+"\images\Ep1"
    directory = renpy.os.path.join( config.gamedir, "images", "Ep1" )

    for filename in renpy.os.listdir( directory ):
#  JPEG files were forgot.
        if filename.endswith(".webp") or filename.endswith(".png") or filename.endswith(".jpg"):
#  If the directory is guaranty to only contain images, this can be used instead
#        if not renpy.os.path.isdir( renpy.os.path.join( directory, filename ) ):
            modImageList.append( renpy.os.path.join( directory, filename ) )
# Useless, the loop while continue anyway.
#        else:
#            continue
 

rb813

Well-Known Member
Aug 28, 2018
1,217
778
# Do NOT use "\" as path separator, it's specific to Windows, and Ren'py # also works with MacOS, Linux, iOS and Android. If really you need to hard # code it, use "/", which should be understood by all the OSes. But still it's # better ot use /os.path.join/.
Can you clarify this a little more? When I enter these lines into my script, and I press the button that's supposed to show the random selection from the ModImageList, it just has that default placeholder with the filename, but the filename says forward-slash game, back-slash images. So it seems like it using "\" as a path separator automatically, and that might be what's causing the actual image to not show up (I am on Windows, though).

(It also does the placeholder with file name thing if I just have "renpy.show(modImageList[0])" instead of trying to do a random one.)
 

rb813

Well-Known Member
Aug 28, 2018
1,217
778
...For testing purpose, I tried declaring an image at the top, "image test_image = modImageList[0]" and then doing "renpy.show("test_image")" instead of "renpy.show(modImageList[0])". When I did that, I got an error message which said, "Exception: Backslash in filename, use '/' instead"
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,978
16,234
Can you clarify this a little more?
With Windows, you separate the directories by putting "\", in between each one. But with Linux and most of UNIX derived OSes, like MacOS X, Android and iOS, it's "/" that is used to separate the directories, because "\" already have another signification ; it's the escape character, a character used to specify that the following character have to be understood differently.
Therefore, for other OSes than Windows, "[path_to_game]\game\image\whatever.ext" should be understood as "[path_to_game][BEEP]ammagehatever.ext" ; \g being the BEL character, \i a backspace, and \w an attempt of synchronization.

When you use them directly with Ren'py statements, it's not a problem, because Ren'py internally change all the "\" into "/" to ensure the compatibility.
But here it's used directly with Python, therefore there will be no corrections ; it will works on Windows, but mostly fail on other platforms.


(It also does the placeholder with file name thing if I just have "renpy.show(modImageList[0])" instead of trying to do a random one.)
Because renpy.show expect a displayable, while you provide it a string. You have to use them through the statement:
Code:
label whatever:
    show expression modImageList[0]
[code]
 

OscarSix

Active Member
Modder
Donor
Jul 27, 2019
829
6,671
Python:
init python:
#  Not needed, the OS module is already available through the /renpy/ module.
#    import os

#  Totally correct. Placed here, the variable will not be saved, which is
# what HAVE to happen, in order to ensure the compatibility.
    modImageList = []

#  Normally have no reason to not works, but there's a safest way to do it.
# Ren'py have a /config.basedir/ variable which correspond to this, and a
# /config.game/ variable that point to the directory where the game content is
# located ; the later being more useful here.
#    path = os.getcwd()
#  Do NOT use "\" as path separator, it's specific to Windows, and Ren'py
# also works with MacOS, Linux, iOS and Android. If really you need to hard
# code it, use "/", which should be understood by all the OSes. But still it's
# better ot use /os.path.join/.
#  Also, this will not works because the "game" folder is missing.
#    directory = path+"\images\Ep1"
    directory = renpy.os.path.join( config.gamedir, "images", "Ep1" )

    for filename in renpy.os.listdir( directory ):
#  JPEG files were forgot.
        if filename.endswith(".webp") or filename.endswith(".png") or filename.endswith(".jpg"):
#  If the directory is guaranty to only contain images, this can be used instead
#        if not renpy.os.path.isdir( renpy.os.path.join( directory, filename ) ):
            modImageList.append( renpy.os.path.join( directory, filename ) )
# Useless, the loop while continue anyway.
#        else:
#            continue
Glad to know I was along the right lines, just needed to be tidied up a bit.
 
  • Like
Reactions: anne O'nymous

rb813

Well-Known Member
Aug 28, 2018
1,217
778
But here it's used directly with Python, therefore there will be no corrections ; it will works on Windows, but mostly fail on other platforms.
But I'm using Windows, and it's still giving me that exception about having the wrong type of slash.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,978
16,234
But I'm using Windows, and it's still giving me that exception about having the wrong type of slash.
Because you're using a Python equivalent, and not the statement itself. It's the statements that translate the "\" into "/", while most of the Python equivalent just ensure that the format is correct ; which isn't the case here.
 

rb813

Well-Known Member
Aug 28, 2018
1,217
778
So, it seems like the code you gave me does work to populate the list of images in the folder. But I'm still at square one as far as what line of code will actually make one of the images from that list appear on the screen.
 

NightTrain

Active Member
May 27, 2017
512
965
So, it seems like the code you gave me does work to populate the list of images in the folder. But I'm still at square one as far as what line of code will actually make one of the images from that list appear on the screen.
Building on the answer by anne O'nymous there are two ways to display the image, either in python using renpy.show:
Code:
renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))
where "randimg" can be any string (it's the image 'tag', whatever that is), or in renpy using
Code:
show expression filename
Below are full examples of both methods:
Python:
init python:
    def showRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))

label some_renpy_label:
    $ showRandomImage("Ep1")
    "You should see a random image now"
    return
Python:
init python:
    def getRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        return renpy.random.choice(modImageList)

label some_renpy_label:
    show expression getRandomImage("Ep1")
    "You should see a random image now"
    return
 
Last edited:

EightEightOne

New Member
Jul 3, 2017
1
1
Below are full examples of both methods:
Python:
init python:
    def showRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))

label some_renpy_label:
    $ showRandomImage("Ep1")
    "You should see a random image now"
    return
Python:
init python:
    def getRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        return renpy.random.choice(modImageList)

label some_renpy_label:
    show expression getRandomImage("Ep1")
    "You should see a random image now"
    return
Hey this works great. I got both codes to work. Is there a way I can get the images to Align center. I tried

show expression getRandomImage("Ep1", xalign=0.5)

but i keep getting errors. I know there is a simple answer somewhere but been able to find it searching.
 
  • Like
Reactions: ohrmazd

onionbros

Rodion Raskolnikov
Game Developer
Feb 1, 2019
64
159
Building on the answer by anne O'nymous there are two ways to display the image, either in python using renpy.show:
Code:
renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))
where "randimg" can be any string (it's the image 'tag', whatever that is), or in renpy using
Code:
show expression filename
Below are full examples of both methods:
Python:
init python:
    def showRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))

label some_renpy_label:
    $ showRandomImage("Ep1")
    "You should see a random image now"
    return
Python:
init python:
    def getRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        return renpy.random.choice(modImageList)

label some_renpy_label:
    show expression getRandomImage("Ep1")
    "You should see a random image now"
    return
Hi all,
I've tried the same code, except I want to use it for random videos (.webms):

Python:
init python:
    def showRandomImageWhite(subdir="."):
            directory = "/".join([config.gamedir.replace("\\", "/"), "movies/masturbation/white", subdir])
            modImageList = [ "/".join([directory, filename])
                             for filename in renpy.os.listdir(directory)
                                 if filename.endswith((".webm")) ]

            #tag is any nametag for the image file, not needed since files are picked randomly from the movies/random folder (not by tag)
            renpy.show("tag", what=Movie(size=(1366,768), play=(renpy.random.choice(modImageList))), at_list=[Position(xalign=0.5, ypos=883)])

# renpy label
label Masturbate:
    show laptop_bg
    if white:
        menu:
            m "What do I feel like watching?"
            "Asian":
                $ showRandomImageWhite("asian")
            "Black":
                $ showRandomImageWhite("black")
            "Latina":
                $ showRandomImageWhite("latina")
It seems that this does not work at all for the "getRandomImage" method, where I end up with an error along the lines of "this image type is not supported". For the other method it does work almost perfectly, except when I try to reload the game or a save file. Then I end up with the following error:

File "F:\Project\Ren'Py\renpy\audio\audio.py", line 915, in get_channel
raise Exception("Audio channel %r is unknown." % name)
Exception: Audio channel '_movie_155' is unknown.

Where the "_movie_XXX" ID is not always the same. Is there some way to fix this?
 

NightTrain

Active Member
May 27, 2017
512
965
Hi all,
I've tried the same code, except I want to use it for random videos (.webms):

Python:
init python:
    def showRandomImageWhite(subdir="."):
            directory = "/".join([config.gamedir.replace("\\", "/"), "movies/masturbation/white", subdir])
            modImageList = [ "/".join([directory, filename])
                             for filename in renpy.os.listdir(directory)
                                 if filename.endswith((".webm")) ]

            #tag is any nametag for the image file, not needed since files are picked randomly from the movies/random folder (not by tag)
            renpy.show("tag", what=Movie(size=(1366,768), play=(renpy.random.choice(modImageList))), at_list=[Position(xalign=0.5, ypos=883)])

# renpy label
label Masturbate:
    show laptop_bg
    if white:
        menu:
            m "What do I feel like watching?"
            "Asian":
                $ showRandomImageWhite("asian")
            "Black":
                $ showRandomImageWhite("black")
            "Latina":
                $ showRandomImageWhite("latina")
It seems that this does not work at all for the "getRandomImage" method, where I end up with an error along the lines of "this image type is not supported". For the other method it does work almost perfectly, except when I try to reload the game or a save file. Then I end up with the following error:

File "F:\Project\Ren'Py\renpy\audio\audio.py", line 915, in get_channel
raise Exception("Audio channel %r is unknown." % name)
Exception: Audio channel '_movie_155' is unknown.

Where the "_movie_XXX" ID is not always the same. Is there some way to fix this?
I'm not really sure what the problem is, since I've struggled in the past to get movies working in Ren'Py, although I think it's improved in recent years.

However, I'd suggest adding a fixed audio channel when creating the Movie() object. Something like:
Code:
renpy.show("tag", what=Movie(size=(1366,768), channel='mymovie', play=(renpy.random.choice(modImageList))), at_list=[Position(xalign=0.5, ypos=883)])
(but don't change 'mymovie' to 'movie' because that would certainly give you the problem you currently have).
 

onionbros

Rodion Raskolnikov
Game Developer
Feb 1, 2019
64
159
I'm not really sure what the problem is, since I've struggled in the past to get movies working in Ren'Py, although I think it's improved in recent years.

However, I'd suggest adding a fixed audio channel when creating the Movie() object. Something like:
Code:
renpy.show("tag", what=Movie(size=(1366,768), channel='mymovie', play=(renpy.random.choice(modImageList))), at_list=[Position(xalign=0.5, ypos=883)])
(but don't change 'mymovie' to 'movie' because that would certainly give you the problem you currently have).
Hmm, thanks for helping but that didn't work either. I found a much better way on reddit how this work, so for anyone else in the future try this:

Python:
init python:
    mast_vids_white = []
    for file in renpy.list_files():
        if file.startswith("movies/masturbation/white/") and file.endswith(".webm"):
            mast_vids_white.append(Movie(size=(1366,768), play=file))

    def play_mast_white():
        global mast_vids_white
        return renpy.random.choice(mast_vids_white)
    
label abc:
    show expression play_mast_white() as mov #at pcvid
 
  • Like
Reactions: NightTrain

The Insider

Member
Game Developer
May 4, 2017
144
255
Building on the answer by anne O'nymous there are two ways to display the image, either in python using renpy.show:
Code:
renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))
where "randimg" can be any string (it's the image 'tag', whatever that is), or in renpy using
Code:
show expression filename
Below are full examples of both methods:
Python:
init python:
    def showRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))

label some_renpy_label:
    $ showRandomImage("Ep1")
    "You should see a random image now"
    return
Python:
init python:
    def getRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "images", subdir])
        modImageList = [ "/".join([directory, filename])
                         for filename in renpy.os.listdir(directory)
                             if filename.endswith((".webp", ".png", ".jpg")) ]
        return renpy.random.choice(modImageList)

label some_renpy_label:
    show expression getRandomImage("Ep1")
    "You should see a random image now"
    return
Hello! I've tried your code and it works, but I'd be grateful if you could help me make a statement if an image is displayed. Example:
If image"map.jpg":
jump on label
 

rayminator

Engaged Member
Respected User
Sep 26, 2018
3,130
3,194
Hello! I've tried your code and it works, but I'd be grateful if you could help me make a statement if an image is displayed. Example:
If image"map.jpg":
jump on label
the answer is in his code showRandomImage("Ep1") you just need to change Ep1 to the image you want it to be

Code:
if showRandomImage("Ep1"):
        jump/call your_label
else:
    blah