function AlphaImageDemo % AlphaImageDemo % % Display a gaussian masked image, locked to the cursor position, % using the Screen('DrawTexture') command. % % This illustrates an application of OpenGL Alpha blending by displaying % an image masked with a gaussian transparency mask. % % In each frame, first the image is drawn. Then a texture acting as a % transparency mask is drawn "over" the image, leaving only selected % parts of the image. % % Please note that we only use two textures: One holding the image, % the other defining the mask. % % see also: PsychDemos, MovieDemo, DriftDemo % HISTORY % % mm/dd/yy % % 6/28/04 awi Adapted from Denis Pelli's DriftDemo.m for OS 9 % 7/18/04 awi Added Priority call. Fixed. % 9/8/04 awi Added Try/Catch, cosmetic changes to comments and see also. % 1/4/05 mk Adapted from awi's DriftDemoOSX. % 24/1/05 fwc Adapted from AlphaImageDriftDemoOSX, bug in % drawtexture prevents it from doing what I really want % 28/1/05 fwc Yeah, works great now after bug was removed from % drawtexture by mk, cleaned up code % 02/07/05 fwc slightly simplified demo by removing some options % such as automode % 3/30/05 awi Added 'BlendFunction' call to set alpha blending mode % The default alpha blending mode for Screen has % changed, this added call sets it to the previous % default. % 4/23/05 mk Small modifications to make it compatible with % "normal" Screen.mexmac. % 12/31/05 mk Small modifications to make it compatible with Matlab-5 % 10/14/06 dhb Rename without OSX bit. Fewer warnings. % dhb More comments, cleaned. % Standard coding practice, use try/catch to allow cleanup on error. try % This script calls Psychtoolbox commands available only in OpenGL-based % versions of the Psychtoolbox. The Psychtoolbox command AssertPsychOpenGL will issue % an error message if someone tries to execute this script on a computer without % an OpenGL Psychtoolbox AssertOpenGL; % Screen is able to do a lot of configuration and performance checks on % open, and will print out a fair amount of detailed information when % it does. These commands supress that checking behavior and just let % the demo go straight into action. See ScreenTest for an example of % how to do detailed checking. oldVisualDebugLevel = Screen('Preference', 'VisualDebugLevel', 3); oldSupressAllWarnings = Screen('Preference', 'SuppressAllWarnings', 1); % Say hello in command window fprintf('\nAlphaImageDemo\n'); % Get the list of screens and choose the one with the highest screen number. % Screen 0 is, by definition, the display with the menu bar. Often when % two monitors are connected the one without the menu bar is used as % the stimulus display. Chosing the display with the highest dislay number is % a best guess about where you want the stimulus displayed. screenNumber=max(Screen('Screens')); % Open a double buffered fullscreen window and draw a gray background % and front and back buffers. [w, wRect]=Screen('OpenWindow',screenNumber, 0,[],32,2); Screen(w,'BlendFunction',GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); % Find the color values which correspond to white and black. black=BlackIndex(screenNumber); gray=GrayIndex(screenNumber); % Import image and and convert it, stored in % MATLAB matrix, into a Psychtoolbox OpenGL texture using 'MakeTexture'; myimgfile = [ PsychtoolboxRoot 'PsychDemos' filesep 'AlphaImageDemo' filesep 'konijntjes1024x768.jpg']; fprintf('Using image ''%s''\n', myimgfile); imdata=imread(myimgfile); % Crop image if it is larger then screen size. There's no image scaling % in maketexture [iy, ix, iz]=size(imdata); %#ok [wW, wH]=WindowSize(w); if ix>wW || iy>wH fprintf('Image size exceeds screen size\n'); fprintf('Image will be cropped\n'); end if ix>wW cl=round((ix-wW)/2); cr=(ix-wW)-cl; else cl=0; cr=0; end if iy>wH ct=round((iy-wH)/2); cb=(iy-wH)-ct; else ct=0; cb=0; end % Set up texture and rects imagetex=Screen('MakeTexture', w, imdata(1+ct:iy-cb, 1+cl:ix-cr,:)); tRect=Screen('Rect', imagetex); [ctRect, dx, dy]=CenterRect(tRect, wRect); % We create a Luminance+Alpha matrix for use as transparency mask: % Layer 1 (Luminance) is filled with luminance value 'gray' of the % background. ms=100; transLayer=2; [x,y]=meshgrid(-ms:ms, -ms:ms); maskblob=uint8(ones(2*ms+1, 2*ms+1, transLayer) * gray); size(maskblob); % Layer 2 (Transparency aka Alpha) is filled with gaussian transparency % mask. xsd=ms/2.0; ysd=ms/2.0; maskblob(:,:,transLayer)=uint8(round(255 - exp(-((x/xsd).^2)-((y/ysd).^2))*255)); % Build a single transparency mask texture masktex=Screen('MakeTexture', w, maskblob); mRect=Screen('Rect', masktex); fprintf('Size image texture: %d x %d\n', RectWidth(tRect), RectHeight(tRect)); fprintf('Size mask texture: %d x %d\n', RectWidth(mRect), RectHeight(mRect)); % Blank sceen Screen('FillRect',w, uint8(gray)); Screen('Flip', w); % initialize mouse position at center [a,b]=WindowCenter(w); SetMouse(a,b,screenNumber); HideCursor; % Bump priority for speed priorityLevel=MaxPriority(w); Priority(priorityLevel); % Pre-load textures Screen('DrawTexture', w, imagetex); Screen('DrawTexture', w, masktex); Screen('FillRect',w, gray); Screen('Flip', w); % Main mouse tracking loop mxold=0; myold=0; while (1) % We wait at least 10 ms each loop-iteration so that we % don't overload the system in realtime-priority: WaitSecs(0.01); % We only redraw if mouse has been moved: [mx, my, buttons]=GetMouse(screenNumber); if (mx~=mxold || my~=myold) myrect=[mx-ms my-ms mx+ms+1 my+ms+1]; % center dRect on current mouseposition dRect = ClipRect(myrect,ctRect); sRect=OffsetRect(dRect, -dx, -dy); if ~IsEmptyRect(dRect) % Draw image for current frame: Screen('DrawTexture', w, imagetex, sRect, dRect); % Overdraw -- and therefore alpha-blend -- with gaussian alpha mask Screen('DrawTexture', w, masktex, [], myrect); % Useful info for user about how to quit. Screen('DrawText', w, 'Move mouse to see different parts of image through mask. Click mouse to exit.', 20, 20, black); % Show result on screen: Screen('Flip', w); end end mxold=mx; myold=my; % Break out of loop on mouse click if find(buttons) break; end end % The same command which closes onscreen and offscreen windows also % closes textures. sca; ShowCursor; Priority(0); % Restore preferences Screen('Preference', 'VisualDebugLevel', oldVisualDebugLevel); Screen('Preference', 'SuppressAllWarnings', oldSupressAllWarnings); % This "catch" section executes in case of an error in the "try" section % above. Importantly, it closes the onscreen window if it's open. catch sca; ShowCursor; Priority(0); % Restore preferences Screen('Preference', 'VisualDebugLevel', oldVisualDebugLevel); Screen('Preference', 'SuppressAllWarnings', oldSupressAllWarnings); psychrethrow(psychlasterror); end