How to do a crossfade transition between images?

PsychoPy version (Psychopyv2023.2.3)

**What are you trying to achieve?:
I want to display images with crossfade transitions: images transitioning smoothly from one image to another by gradually fading out the first image while simultaneously fading in the second image.

**What did you try to make it work?:
I created a routine in which images are randomly selected from a folder (with one loop), and then I added this code component (each frame section):

continueRoutine = True
#variables
fade_duration = 0.8  
image_display_duration = 1.6  
start_time = 0  
current_opacity = 0  

routineForceEnded = not continueRoutine
while continueRoutine and routineTimer.getTime() < 1.6:
    t = routineTimer.getTime()

    elapsed_time = t - start_time
    if elapsed_time < fade_duration:
        current_opacity = elapsed_time / fade_duration
    elif elapsed_time > image_display_duration - fade_duration:
        current_opacity = 1 - ((elapsed_time - (image_display_duration - fade_duration)) / fade_duration)
    else:
        current_opacity = 1

    image.setOpacity(current_opacity)
    win.flip() 

**What specifically went wrong when you tried that?:
The code runs without errors, but the images are displayed with a fade-in/fade-out effect one after the other (flashing), without them being superimposed during the transition time. I’m having difficulty setting up the crossfade effect. Does anyone have a solution?
Thank you !

Don’t use win.flip() in Builder experiments. There’s also no need to set continueRoutine = True

Your code seems to be setting the opacity for one image but not the other. Shouldn’t you have two?

Presumably your variables are set in Begin Routine, not Each Frame.

Thank you for your answer
Since images are already called from a folder within the loop, I did not specify anything about images in the code component
That might be why the images don’t have a crossfade effect. Do you have a solution for that?

I would recommend a crossfade routine at the start of your loop which (from trials.thisN == 1 onwards) crossfades the old image (stored to an oldImage variable) with the new image from the spreadsheet.

I don’t know offhand whether crossfade will work but if it does then it definitely needs two image components where one is increasing opacity and the other is decreasing.

You could do this in your main trial routine if you are happy with the start of the trial being when the new image starts to appear. For the first loop you could set oldImage to a transparent png (or perhaps a screenshot of the instructions or a fixation cross)

Thanks for your answer,

I tried, and added 2 image components and then added this code component:

# Begin experiment
frame_rate = win.getActualFrameRate()
crossfade_duration = 0.8  

# Begin routine
image_index = 0  
current_image = oldImage  
next_image = newImage  
current_opacity = 1.0  
next_opacity = 0.0  
crossfade_timer = 0.0 

# Each frame
if crossfade_timer < crossfade_duration:
    crossfade_timer += 1 / frame_rate

    crossfade_progress = min(1.0, crossfade_timer / crossfade_duration)

    current_image.opacity = max(0.0, 1.0 - crossfade_progress)
    next_image.opacity = min(1.0, crossfade_progress)
else:
    image_index = (image_index + 1) % len(images)
    current_image = next_image
    next_image = images[(image_index + 1) % len(images)]
    current_opacity = 1.0
    next_opacity = 0.0
    crossfade_timer = 0.0

Now it is working but only for the image couple (oldImage/newImage). I can’t find the logic to apply this cross-fade transition between all the images (including newImage/oldImage), not just the first. Do you have any ideas?
Thank you !

You need some End Routine code to update the value of oldImage (oldImage = newImage assuming that your spreadsheet contains values for newImage