FAQ: Screenshots or Recordings - Psychtoolbox-3/Psychtoolbox-3 GitHub Wiki

Screenshot or Record Stimuli

Q: How do I take a screen shot of my stimuli?

A: Via the PTB-3 function Screen('GetImage', ...)

PTB-3 is based around a dual buffer system; you send draw commands to a back buffer (offscreen) then 'Flip' that back buffer to the front, where it will be displayed. The Screen subfunction GetImage can read from either buffer, defaulting to reading the frontbuffer.

GetImage returns a matrix of RGB values that can be converted to an image via the Matlab function imwrite. Different image formats require different arguments; refer to the help for imwrite for more detail.

Common problems:

  1. The output image is blank

    Ensure GetImage is recording from the correct buffer, and ensure you have a suitable graphics card.

  2. imwrite returns errors

    Double check you have sent the correct format imageArray to imwrite -- different image file formats have different rules and the return value from GetImage may need to be converted. Refer to the imwrite documentation.

Example code:

function imageArray = testImageWriting
% Draws an oval in the top left corner of the screen, and outputs a jpg image
% of that dot. 

try
    wPtr = Screen('OpenWindow', 0);
    HideCursor;

    Screen('FillRect', wPtr, 0);
    Screen(wPtr, 'Flip');
    white = WhiteIndex(wPtr);

    % Draws the display to be turned into an image file
    a = [100 100 150 150]';
    b = [100 200 150 200]';
    ovalSpecs = [a b];
    Screen('FillOval', wPtr, white, ovalSpecs );
    Screen(wPtr, 'Flip');

    % GetImage call. Alter the rect argument to change the location of the screen shot
    imageArray = Screen('GetImage', wPtr, [0 0 300 300]);

    % imwrite is a Matlab function, not a PTB-3 function
    imwrite(imageArray, 'test.jpg')

    WaitSecs(.5);
    ShowCursor;
    Screen('CloseAll');
catch
    ShowCursor;
    Screen('CloseAll');
end
function imageArray = movingDots
% Produces a dynamic display and outputs an animated .gif record of the trial
imageArray={};

try
    [wPtr, rect] = Screen('OpenWindow', 0)
    HideCursor;
    Screen('FillRect', wPtr, 0);
    Screen(wPtr, 'Flip');

    %Animation parameters
    centre = rect(3)/2;
    dotDiameter = 50;
    yTop = 304; 
    amplitude = 300; 
    frequency = 1; 
    
    white = WhiteIndex(wPtr);

    % Draws the display to be turned into an image file
    start = GetSecs;
    while GetSecs < start + 2
        time = GetSecs-start;
        oval = centre + (amplitude * cos(frequency * time *(2*pi))); 

        ovalSpecs = [oval yTop oval+dotDiameter yTop+dotDiameter]';

        % You can try calling GetImage at this point prior to the call to
        % 'Flip'  and specifying the backbuffer

        Screen('FillOval', wPtr, white, ovalSpecs);
        Screen(wPtr, 'Flip');

        % Records the frame from front buffer and appends to the imageArray
        % matrix
        % Assumes a screen resolution of 1024x768; alter the rect coordinates
        % to change this
        imageArray = [imageArray; {Screen('GetImage', wPtr, [200 264 874 544])}];
    end

    ShowCursor;
    Screen('CloseAll');

    %Creates the .gif
    delayTime = 1/60; %Screen refresh rate of 60Hz
    for i = 1:length(imageArray)
        % Gifs can't take RBG matrices: they have to be specified with the
        % pixels as indices into a colormap
        % See the help for imwrite for more details
        [y, newmap] = cmunique(imageArray{i});

        %Creates a .gif animation - makes first frame, then appends the rest
        if i==1
            imwrite(y, newmap, 'Zero Phase.gif');
        else
            imwrite(y, newmap, 'Zero Phase.gif', 'DelayTime', delayTime, 'WriteMode', 'append');
        end
    end
catch
    ShowCursor;
    Screen('CloseAll');
end

Q: How do I record a movie of my dynamic visual stimuli?

A: Via the functions Screen('CreateMovie', ...) and Screen('AddFrameToMovie', ...).

movie = Screen('CreateMovie', ...); allows to prepare movie recording of onscreen stimuli into a movie file, e.g., an AVI, Quicktime, Matroska or similar file format, encoded with modern video codecs like H264, H265 etc. You can specify the name of the movie file, the size of the images (width x height) stored in the movie, the type and encoding of the movie, the nominal framerate at which the movie should play back , the number of color channels and the color depth. Once the movie handle has been created, you can use the command Screen('AddFrameToMovie', ...) in the places and in the same way as you'd use the Screen('GetImage', ...) command described above in the section about screen shots. Each call to Screen('AddFrameToMovie', ...) will take a snapshot of a portion of the specified onscreen or offscreen window, but store the screen grabbed image in the created movie file, instead of returning the image as a Matlab matrix. At the end of a session, you call Screen('FinalizeMovie', ...) to finish movie recording and create the final movie file. If you chose suitable movie formats and encoding parameters, the resulting movie file will not only play back with Psychtoolbox movie playback functions, but also with standard movie and video players. The approach is demonstrated in ImagingStereoDemo.m if you pass it the optional writeMovie parameter, e.g., ImagingStereoDemo([],[],1);. A setting of 2 in that demo will also demonstrate how one can add an audio track to such a recorded movie with the help of the function Screen('AddAudioBufferToMovie', ...). On modern systems with modern graphics cards, movie recording should be possible for high resolution movies at reasonable performance. It may even use hardware accelerated video encoding if your graphics card supports this.

⚠️ **GitHub.com Fallback** ⚠️