File: SimpleHDRLinuxStereoDemo.m

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (171 lines) | stat: -rw-r--r-- 6,768 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
function SimpleHDRLinuxStereoDemo(imfilename)
% SimpleHDRLinuxStereoDemo([imfilename]) - Load and show a HDR image on a compatible
% HDR stereo display setup.
%
% Press any key to terminate the demo.
%
% 'imfilename' - Optional filename of the HDR image to load. This will load
% a standard HDR demo image bundled with Matlab, if omitted, or abort if
% the default demo image is missing. Currently only '.hdr' RGBE images are
% supported.
%
% See SimpleHDRDemo for explanations. This is the same demos, but displaying
% stereoscopically on Linux + X11 via the special Linux hack enabled by the
% Linux only PsychImaging task
%
% PsychImaging('AddTask', 'General', 'UseStaticHDRHack', hdrMeta);
%
% See help PsychImaging in the 'UseStaticHDRHack' section for explanations,
% background info and setup instructions.
%

% History:
%
% 18-Dec-2020   mk  Written. Derived from SimpleHDRDemo.

if ~IsLinux || IsWayland
    fprintf('Sorry, this demo only works on Linux/X11, not under Wayland or other operating systems.\n');
    return;
end

% Make sure we run on Psychtoolbox-3. Abort otherwise. Use unified key names for
% keyboard input across all supported operating systems. Use normalized color range,
% not the old 0-255 8 bit color convention:
PsychDefaultSetup(2);

% imfilename provided?
if nargin < 1 || isempty(imfilename)
    % No: Try some default file from our bundled OpenEXR sample images:
    imfilename = [PsychtoolboxRoot 'PsychDemos/OpenEXRImages/Desk.exr'];
end

% Does imfilename exist?
if ~exist(imfilename, 'file')
    error('Specified HDR image file does not exist under path %s.', imfilename);
end

% Read HDR file, abort on error. Must be in a file format recognized by HDRRead:
[img, info] = HDRRead(imfilename);

% Show metadata:
disp(info);

% Find screen to display on: We choose the one with the highest number,
% assuming this is the HDR display:
screenid = max(Screen('Screens'));

% Set a cleanup function: If the variable 'canary' goes out of scope due to
% script termination (error or user abort), call "sca" which will close the display:
canary = onCleanup(@sca);

% Define static HDR metadata to use for the whole duration of this demo session:
hdrMeta.MetadataType = 0;
hdrMeta.MinLuminance = 0.050;
hdrMeta.MaxLuminance = 600;
hdrMeta.ColorGamut = [0.6400, 0.3000, 0.1500, 0.3127 ; 0.3300, 0.6000, 0.0600, 0.3290];

% Convert img from its source colorspace to the display colorspace defined for
% the mastering display. info.ColorGamut is the color gamut parsed from the
% image file, or a default color gamut as mandated by the image file format
% spec for the image file:
[foo, img] = ConvertRGBSourceToRGBTargetColorSpace(info.ColorGamut, hdrMeta.ColorGamut, img);

switch info.format
    case 'rgbe'
        % HACK: Multiply by 179.0 as a crude approximation of Radiance
        % units to nits: This is not strictly correct, but will do to get a
        % nice enough picture for demo purpose. See 'help HDRRead' for the
        % motivation for the 179 multiplicator for Radiance images:
        % This is always RGB, no alpha channel to deal with.
        img = img * 179;

    case 'openexr'
        % Known scaling factor for scaling pixel values into units of nits?
        % Otherwise it is best to just leave it as is:
        if info.sampleToNits > 0
            % Only scale RGB channels, not the alpha channel.
            img(:,:,1:3) = img(:,:,1:3) * info.sampleToNits;
        end

    otherwise
        error('Unknown image format. Do not know how to convert into units of Nits.');
end

% Compute and assign maximum and max mean luminance of the image:
[maxFALL, maxCLL] = ComputeHDRStaticMetadataType1ContentLightLevels(img);
hdrMeta.MaxFrameAverageLightLevel = maxFALL;
hdrMeta.MaxContentLightLevel = maxCLL;

% Open a double-buffered fullscreen onscreen stereo window in HDR mode on the HDR
% display, with black background color. Color values will be specified in
% units of nits, the display is done according to HDR10 standard, ie.
% Color space is BT2020, SMPTE ST-2084 PQ encoding is used to drive the
% display, output color signals have 10 bpc precision. Use a dual-display or
% side-by-side single display stereo configuration:
PsychImaging('PrepareConfiguration');
PsychImaging('AddTask', 'General', 'EnableHDR', 'Nits', 'HDR10'); %, 'Dummy');
PsychImaging('AddTask', 'General', 'UseStaticHDRHack', hdrMeta);
win = PsychImaging('OpenWindow', screenid, 0, [], [], [], 4);
HideCursor(win);

% Build a 32 bpc single-precision float texture from the image
% array by setting the (optional) 'floatprecision' flag to 2.
% texid = Screen('MakeTexture', win, img, [], [], 2);
%
% Or simply don't, because the 'floatprecision' flag defaults to 2
% in HDR display mode anyway if omitted, for your convenience:
texid = Screen('MakeTexture', win, img);

% Some variable rotation angle for the image, for some simplistic animation:
rotAngle = 0;

% Some framecounter for stats:
framecounter = 0;

% Initial Flip to sync us to retrace:
vbl = Screen('Flip', win);
tstart = vbl;

% Animation loop: Show a rotating HDR image, until key press:
while ~KbCheck
    % Draw left eye stim:
    Screen('SelectStereoDrawBuffer', win, 0);

    % Draw our HDR texture at specified rotation angle, centered in the window:
    Screen('DrawTexture', win, texid, [], [], rotAngle);

    % Draw some 2D filled oval, with a bounding box of [left,top,right,bottom]
    % = [500 500 600 600], and a color value of [R, G, B] = [300 nits, 300 nits, 0 nits],
    % ie. a yellow oval with 300 nits:
    Screen('FillOval', win, [300 300 0], [500 500 600 600]);

    % Draw right eye stim:
    Screen('SelectStereoDrawBuffer', win, 1);

    % Draw our HDR texture at specified rotation angle, centered in the window:
    Screen('DrawTexture', win, texid, [], [], rotAngle);

    % Draw some 2D filled oval, with a bounding box of [left,top,right,bottom]
    % = [520 500 620 600], and a color value of [R, G, B] = [300 nits, 300 nits, 0 nits],
    % ie. a yellow oval with 300 nits. This is shifted 40 pixels to the left, wrt.
    % the otherwise identical left-eye stimulus to create a teeny tiny bit of stereo:
    Screen('FillOval', win, [300 300 0], [460 500 560 600]);

    % Show updated HDR framebuffer at next vertical retrace:
    vbl = Screen('Flip', win, vbl);

    % Increase rotation angle to make it a bit more interesting:
    rotAngle = rotAngle + 0.1;

    % Count our frames:
    framecounter = framecounter + 1;
end

% We are done. Release all textures, close all windows, shutdown:
sca;

% Print the stats:
duration = vbl - tstart;
averagefps = framecounter / duration;
fprintf('Displayed %i stereo-frames in %f seconds, for an average framerate of %f fps.\n', framecounter, duration, averagefps);
fprintf('Bye bye!\n');