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

The Insider

Member
Game Developer
May 4, 2017
144
255
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
Thanks for the answer but it still doesn't work, cuz Ep1 is a folder. I tried to insert my separate image into another folder but still doesn't work.

Here's what I did:

label search:

if showRandomImage("Random/specified"): #"specified" is a folder cuz image doesn't work
jump save_her1
else:
$ showRandomImage("Random")
pause
jump search1





init python:

modImageList = []
directory = renpy.os.path.join( config.gamedir, "images/0.2", "Random" )
for filename in renpy.os.listdir( directory ):

if not renpy.os.path.isdir( renpy.os.path.join( directory, filename ) ):
modImageList.append( renpy.os.path.join( directory, filename ) )




def showRandomImage(subdir="."):
directory = "/".join([config.gamedir.replace("\\", "/"), "images/0.2/", subdir])
modImageList = [ "/".join([directory, filename])
for filename in renpy.os.listdir(directory)
if filename.endswith((".png"))]
renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))
 

The Insider

Member
Game Developer
May 4, 2017
144
255
Thanks for the answer but it still doesn't work, cuz Ep1 is a folder. I tried to insert my separate image into another folder but still doesn't work.

Here's what I did:

label search:

if showRandomImage("Random/specified"): #"specified" is a folder cuz image doesn't work
jump save_her1
else:
$ showRandomImage("Random")
pause
jump search1





init python:

modImageList = []
directory = renpy.os.path.join( config.gamedir, "images/0.2", "Random" )
for filename in renpy.os.listdir( directory ):

if not renpy.os.path.isdir( renpy.os.path.join( directory, filename ) ):
modImageList.append( renpy.os.path.join( directory, filename ) )




def showRandomImage(subdir="."):
directory = "/".join([config.gamedir.replace("\\", "/"), "images/0.2/", subdir])
modImageList = [ "/".join([directory, filename])
for filename in renpy.os.listdir(directory)
if filename.endswith((".png"))]
renpy.show("randimg", what=Image(renpy.random.choice(modImageList)))

My problem is that I have several images in that folder, but when it gets to a specific one of them I have to jump to another label.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,263
15,073
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
It need to completely refactor the code, in order to keep a copy of the selection:
/!\ I past the last ~15 hours coding in QScript, it's possible that my Python is temporarily tainted. /!\
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")) ]
        store.selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( store.selectedImage ) )

default selectedImage = None
Then you can test the value of selectedImage to know what image is displayed.
Code:
label whatever:
    if selectedImage.endswith( "map.jpg" ):
        jump whateverElse

But all this raise some concern regarding the code logic.

If you need to react differently depending of the image, or group of images, or at least for few of them, is this approach really the best one ?
 
  • Like
Reactions: The Insider

The Insider

Member
Game Developer
May 4, 2017
144
255
It need to completely refactor the code, in order to keep a copy of the selection:
/!\ I past the last ~15 hours coding in QScript, it's possible that my Python is temporarily tainted. /!\
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")) ]
        store.selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( store.selectedImage ) )

default selectedImage = None
Then you can test the value of selectedImage to know what image is displayed.
Code:
label whatever:
    if selectedImage.endswith( "map.jpg" ):
        jump whateverElse

But all this raise some concern regarding the code logic.

If you need to react differently depending of the image, or group of images, or at least for few of them, is this approach really the best one ?
Thank you, It works! Yes it's the best solution for what i'm doing, this way I don't have to write alot of coding just for this simple task.
Thank you again!
 

NightTrain

Active Member
May 27, 2017
506
949
Thank you, It works! Yes it's the best solution for what i'm doing, this way I don't have to write alot of coding just for this simple task.
Thank you again!
Glad you found a good solution. Just to make your life a little harder, here are some alternatives...

You could also use getRandomImage() instead of showRandomImage(), along with:
Code:
$ img = getRandomImage("Ep1")
show expression img
if (img.endswith("map.jpg")):
    jump to_where_you_want_to_go
This solution is nice in that it follows simple steps: select an image, display the image, and then decide if you need to do something else based on the image that was selected.

But personally I would modify anne O'nymous' version of showRandomImage() to return the image name instead of using a store variable:
Code:
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")) ]
        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage
and then use it with
Code:
if (showRandomImage("Ep1").endswith("map.jpg")):
    jump to_where_you_want_to_go
which will display a random image, and then if it ends in "map.jpg", jump to the specified label. This is probably the fastest way to code, but may get a little confusing for debugging later because the image showing part is hidden in the conditional statement. It's the kind of thing that "today-me" would love, and "tomorrow-me" would hate today-me for.
 

The Insider

Member
Game Developer
May 4, 2017
144
255
Glad you found a good solution. Just to make your life a little harder, here are some alternatives...

You could also use getRandomImage() instead of showRandomImage(), along with:
Code:
$ img = getRandomImage("Ep1")
show expression img
if (img.endswith("map.jpg")):
    jump to_where_you_want_to_go
This solution is nice in that it follows simple steps: select an image, display the image, and then decide if you need to do something else based on the image that was selected.

But personally I would modify anne O'nymous' version of showRandomImage() to return the image name instead of using a store variable:
Code:
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")) ]
        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage
and then use it with
Code:
if (showRandomImage("Ep1").endswith("map.jpg")):
    jump to_where_you_want_to_go
which will display a random image, and then if it ends in "map.jpg", jump to the specified label. This is probably the fastest way to code, but may get a little confusing for debugging later because the image showing part is hidden in the conditional statement. It's the kind of thing that "today-me" would love, and "tomorrow-me" would hate today-me for.
This code helped me a lot because I just needed a simple search by clicking on the images and when you got a specific one, needed to continue the story, so to speak.
Thank you so much for the help!
 
  • Like
Reactions: NightTrain

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,263
15,073
But personally I would modify anne O'nymous' version of showRandomImage() to return the image name instead of using a store variable:
A good change yeah.

And also a good demonstration that the way you present a problem will define the answer you'll get to it.
"make a statement if an image is displayed" made me thought that if can happen at anytime, and therefore that the value need to be saved somewhere.
"make a statement when an image is displayed" would probably have made me think about returning directly the value.

Be noted that it isn't a criticism against the way R1NC35T asked his question, but a reminder that the more thoughtfully you present your problem, the more accurate will be the answers.
 
  • Like
Reactions: NightTrain

NightTrain

Active Member
May 27, 2017
506
949
A good change yeah.

And also a good demonstration that the way you present a problem will define the answer you'll get to it.
"make a statement if an image is displayed" made me thought that if can happen at anytime, and therefore that the value need to be saved somewhere.
"make a statement when an image is displayed" would probably have made me think about returning directly the value.

Be noted that it isn't a criticism against the way R1NC35T asked his question, but a reminder that the more thoughtfully you present your problem, the more accurate will be the answers.
And a reminder to me that I shouldn't jump to conclusions about the question either, because your interpretation is just as valid as mine but it didn't occur to me at all.
 

The Insider

Member
Game Developer
May 4, 2017
144
255
I have a problem with this code, people have told me that they get errors on Linux can someone help me with this one?
code error:
 

rayminator

Engaged Member
Respected User
Sep 26, 2018
3,040
3,123
I have a problem with this code, people have told me that they get errors on Linux can someone help me with this one?
code error:
it's telling what's wrong
IOError: Couldn't find file 'media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png'.

it's properly on their end you should check if the image is there or not

try renaming the image with at least 4 letter longer then 3
 

The Insider

Member
Game Developer
May 4, 2017
144
255
it's telling what's wrong
IOError: Couldn't find file 'media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png'.

it's properly on their end you should check if the image is there or not

try renaming the image with at least 4 letter longer then 3
The img is there.
I will try to make the name longer.
Thank you!
 

gojira667

Member
Sep 9, 2019
255
238
I have a problem with this code, people have told me that they get errors on Linux can someone help me with this one?
code error:
The file it's looking for is media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png. Which is a relative path to the working directory (doesn't start with /).
In Ren'Py files are typically referenced relatively with their path under game (My.innocent.pleasure-0.2-pc/game). Does the following file exist?
Code:
/media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png
Probably not. What's the actual code to pick the image?

edit:
Then again it references the full path in the one spot: :unsure:
While loading <renpy.display.im.Image object (u'/media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png') at 0x7f033367ec10>:
 
Last edited:

The Insider

Member
Game Developer
May 4, 2017
144
255
The file it's looking for is media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png. Which is a relative path to the working directory (doesn't start with /).
In Ren'Py files are typically referenced relatively with their path under game (My.innocent.pleasure-0.2-pc/game). Does the following file exist?
Code:
/media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png
Probably not. What's the actual code to pick the image?
I renamed all the Jpgs in the random document. Now I'm waiting for the Linux player to update me if it got the same error.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,263
15,073
edit:
Then again it references the full path in the one spot: :unsure:
While loading <renpy.display.im.Image object (u'/media/james/2TB_drive/entertainment/My.innocent.pleasure-0.2-pc/game/images/Random/lg8.png') at 0x7f033367ec10>:
Yet you are right, the exception itself reference the file through its relative path:
IOError: Couldn't find file 'image/doNOTexist.jpg'.
And here the relative path clearly include things that shouldn't be there.

It probably come from the random image picker, that would then get and use the full path, instead of building it, relatively, based on the filename only.
 

gojira667

Member
Sep 9, 2019
255
238
It probably come from the random image picker, that would then get and use the full path, instead of building it, relatively, based on the filename only.
Code in use:
Code:
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")) ]
        store.selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( store.selectedImage ) )
At least under Linux Image() appears to strip the initial / if you feed it a full path. Then I get the same type of traceback.

Actually this happens ( .lstrip('/') ).

Now I'm waiting for the Linux player to update me if it got the same error.
It has the same problem.

Switching to renpy.list_files() which gives relative paths works fine:
Code:
init python:

   def showRandomImage(subdir="."):
        directory = "images/"+subdir
        modImageList = [filename for filename in renpy.list_files() if ( directory in filename and filename.endswith((".webp", ".png", ".jpg")) ) ]
        store.selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( store.selectedImage ) )
 
Last edited:

Urist

Newbie
Nov 29, 2016
27
16
It need to completely refactor the code, in order to keep a copy of the selection:
/!\ I past the last ~15 hours coding in QScript, it's possible that my Python is temporarily tainted. /!\
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")) ]
        store.selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( store.selectedImage ) )

default selectedImage = None
Then you can test the value of selectedImage to know what image is displayed.
Code:
label whatever:
    if selectedImage.endswith( "map.jpg" ):
        jump whateverElse

But all this raise some concern regarding the code logic.

If you need to react differently depending of the image, or group of images, or at least for few of them, is this approach really the best one ?
Glad you found a good solution. Just to make your life a little harder, here are some alternatives...

You could also use getRandomImage() instead of showRandomImage(), along with:
Code:
$ img = getRandomImage("Ep1")
show expression img
if (img.endswith("map.jpg")):
    jump to_where_you_want_to_go
This solution is nice in that it follows simple steps: select an image, display the image, and then decide if you need to do something else based on the image that was selected.

But personally I would modify anne O'nymous' version of showRandomImage() to return the image name instead of using a store variable:
Code:
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")) ]
        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage
and then use it with
Code:
if (showRandomImage("Ep1").endswith("map.jpg")):
    jump to_where_you_want_to_go
which will display a random image, and then if it ends in "map.jpg", jump to the specified label. This is probably the fastest way to code, but may get a little confusing for debugging later because the image showing part is hidden in the conditional statement. It's the kind of thing that "today-me" would love, and "tomorrow-me" would hate today-me for.

I know this is months later, but maybe I'll get some help. I got the code to select a random image working, but what if I want to pull from multiple directories? Like A, B, X, Y? And then if it pulls an image from A or B, have ___ happen, and if it pulls from X or Y, ___ happens instead? I essentially want to make a sorting minigame, where the user is presented with say, 10 images (split in to accepted and rejected folders, with the ability to expand & pull from other folders as the game progresses) one by one, and they can either approve or reject an image and get points based off of how many they got right/wrong.
 

rb813

Well-Known Member
Aug 28, 2018
1,027
615
I know this is months later, but maybe I'll get some help. I got the code to select a random image working, but what if I want to pull from multiple directories? Like A, B, X, Y? And then if it pulls an image from A or B, have ___ happen, and if it pulls from X or Y, ___ happens instead? I essentially want to make a sorting minigame, where the user is presented with say, 10 images (split in to accepted and rejected folders, with the ability to expand & pull from other folders as the game progresses) one by one, and they can either approve or reject an image and get points based off of how many they got right/wrong.
As a novice, it seems to me like probably the simplest answer would be to just pick the folder first (by picking a random number, and then saying "if 1, pull from A or B, if 2, pull from X or Y," etc.)
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,263
15,073
As a novice, it seems to me like probably the simplest answer would be to just pick the folder first (by picking a random number, and then saying "if 1, pull from A or B, if 2, pull from X or Y," etc.)
I'm at works and, hmmm... let's say that like we are the 22 December we have touched more glasses than keyboard. So I'll not try to write long code, but globally it's what you said.

Firstly you browse the directory to get the folder, that you store in a list with something like:
Code:
allFolders = []

for filename in renpy.os.listdir( directory ):
       if renpy.os.path.isdir( renpy.os.path.join( directory, filename ) ):
           allFolders.append( renpy.os.path.join( directory, filename ) )
Then renpy.random.choice( allFolders ) will randomly pick one of those folders.
 

Urist

Newbie
Nov 29, 2016
27
16
As a novice, it seems to me like probably the simplest answer would be to just pick the folder first (by picking a random number, and then saying "if 1, pull from A or B, if 2, pull from X or Y," etc.)
I'm at works and, hmmm... let's say that like we are the 22 December we have touched more glasses than keyboard. So I'll not try to write long code, but globally it's what you said.

Firstly you browse the directory to get the folder, that you store in a list with something like:
Code:
allFolders = []

for filename in renpy.os.listdir( directory ):
       if renpy.os.path.isdir( renpy.os.path.join( directory, filename ) ):
           allFolders.append( renpy.os.path.join( directory, filename ) )
Then renpy.random.choice( allFolders ) will randomly pick one of those folders.

Would I need to store the folder it selected somehow, so it remembers the choice? Then have some very basic if/elif/else stuff so that I can have it give points based off of correct answer, then display the next image, etc.? I'm not good at this non beginner friendly ren'py stuff, and this is the conclusion I came to based off of this thread.

edit: small brain is small and ended up just defining two different random image things, a showRandomImageA and a showRandomImageB, then decided to use renpy.random.randint(0,1) and have it jump to showRandomImageA if it's a 0, B if it's a 1. Which works, but I'm derping somewhere because if I have it do a show expression showRandomImageA/B, it won't hide the image after jumping to a different label, and using hide seems to fail me. Renpy docs say it should clear with a jump, but they don't.

edit 2: small pea brain has found that I can clear images using scene black or $ renpy.scene(). Now I just need to figure out a point system, etc. I'm sure all of this could have been done in a really easy way, but here's the vomit of code I have. Ignore the testing bits at the bottom, but yeah.

Python:
init python:

    def showRandomAImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "accepted", subdir])
        modImageList = [ "/".join([directory, filename])
                        for filename in renpy.os.listdir(directory)
                            if filename.endswith((".webp", ".png", ".jpg")) ]


        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage

    def showRandomRImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "rejected", subdir])
        modImageList = [ "/".join([directory, filename])
                        for filename in renpy.os.listdir(directory)
                            if filename.endswith((".webp", ".png", ".jpg")) ]


        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage


label randimgtest2:
    $ randgamenbr = renpy.random.randint(0,1)
    if (randgamenbr == 0):
        jump randimgaccept
    
    elif (randgamenbr == 1):
        jump randimgreject

label randimgaccept:
    show expression showRandomAImage()
    "1"
    pause
    "clearing."
    scene black
    jump start

label randimgreject:
    show expression showRandomRImage()
    "2"
    pause
    "clearing."
    scene black
    jump start
 
Last edited:

NightTrain

Active Member
May 27, 2017
506
949
Would I need to store the folder it selected somehow, so it remembers the choice? Then have some very basic if/elif/else stuff so that I can have it give points based off of correct answer, then display the next image, etc.? I'm not good at this non beginner friendly ren'py stuff, and this is the conclusion I came to based off of this thread.

edit: small brain is small and ended up just defining two different random image things, a showRandomImageA and a showRandomImageB, then decided to use renpy.random.randint(0,1) and have it jump to showRandomImageA if it's a 0, B if it's a 1. Which works, but I'm derping somewhere because if I have it do a show expression showRandomImageA/B, it won't hide the image after jumping to a different label, and using hide seems to fail me. Renpy docs say it should clear with a jump, but they don't.

edit 2: small pea brain has found that I can clear images using scene black or $ renpy.scene(). Now I just need to figure out a point system, etc. I'm sure all of this could have been done in a really easy way, but here's the vomit of code I have. Ignore the testing bits at the bottom, but yeah.

Python:
init python:

    def showRandomAImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "accepted", subdir])
        modImageList = [ "/".join([directory, filename])
                        for filename in renpy.os.listdir(directory)
                            if filename.endswith((".webp", ".png", ".jpg")) ]


        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage

    def showRandomRImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"), "rejected", subdir])
        modImageList = [ "/".join([directory, filename])
                        for filename in renpy.os.listdir(directory)
                            if filename.endswith((".webp", ".png", ".jpg")) ]


        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage


label randimgtest2:
    $ randgamenbr = renpy.random.randint(0,1)
    if (randgamenbr == 0):
        jump randimgaccept
   
    elif (randgamenbr == 1):
        jump randimgreject

label randimgaccept:
    show expression showRandomAImage()
    "1"
    pause
    "clearing."
    scene black
    jump start

label randimgreject:
    show expression showRandomRImage()
    "2"
    pause
    "clearing."
    scene black
    jump start
I can't help but chime in here...

Even though your answer is reasonable, you'll find your program is easier to maintain if you try to modify your code to give greater reusability. The original showRandomImage() function already has the subdir parameter, which lets use specify which folder you want to pull the image from. For example, you could pass either "accepted" or "rejected" to pull the image from the appropriate folder.

Python:
init python:

    def showRandomImage(subdir="."):
        directory = "/".join([config.gamedir.replace("\\", "/"),  subdir])
        modImageList = [ "/".join([directory, filename])
                        for filename in renpy.os.listdir(directory)
                            if filename.endswith((".webp", ".png", ".jpg")) ]

        selectedImage = renpy.random.choice(modImageList)
        renpy.show("randimg", what=Image( selectedImage ) )
        return selectedImage

label randimgtest2:
    $ randgamenbr = renpy.random.randint(0,1)
    if (randgamenbr == 0):
        jump randimgaccept
   
    elif (randgamenbr == 1):
        jump randimgreject

label randimgaccept:
    show expression showRandomImage("accepted")
    "1"
    pause
    "clearing."
    scene black
    jump start

label randimgreject:
    show expression showRandomImage("rejected")
    "2"
    pause
    "clearing."
    scene black
    jump start
And, if you really want, you could write the rest as
Python:
label randimgtest2:
    $ isAccepted = renpy.random() < 0.5
    show expression showRandomImage("accepted" if isAccepted else "rejected")
    if (isAccepted):
        "You win!  +1"
    else:
        "You lose!  -1"
    pause
    "clearing."
    scene black
    jump start
The isAccepted = renpy.random() < 0.5 line sets the variable isAccepted to True randomly with a 50% probability. If you want a lower or higher probability, just change the 0.5.