Search code examples
matlabpsychtoolbox

How can I get pixel information from DrawFormattedText


I'm using the function DrawFormattedText to present text in Psychtoolbox. I'm wondering how I could count the number of pixels produced by the text from this function.

A minimal example looks like this (you should be able to copy/paste this):

[w, wRect]=Screen('OpenWindow', 0, [0 128 128],[],[],[],[],128);
Screen('TextFont',w, 'Arial'); %Set font
Screen('TextSize',w, 16); %Set text size
[nx, ny, bbox] = DrawFormattedText(w, 'HowManyPixelsDoIHave?', 'center', 'center', 60);
Screen('Flip',w);
KbWait; %Wait for response before closing
Screen('CloseAll');

In this example I want to find out how many pixels are used to write the text "HowManyPixelsDoIHave?" I need a metric to compare various printed text strings.

I don't seem to have a grasp on how to access the content produced by the DrawFormattedText function.

A matrix of the entire screen and its pixel values would be sufficient. If anyone would know how to narrow it down to specific regions of the screen, this would be greatly appreciated.

Thanks for any help you might be able to provide!


Solution

  • Extracting the pixels is actually relay easy.I'm not sure if you want the information ho many space is needed for the text do display, or you want the information for example how many black pixels does the letter B contain.

    Version 1 - how much space do I need

    All the information is stored in the bbox variable. bbox contains the the points which define the rectangle in which the Text is printed.

    You can get those values by typing bbox in your command line. The output should look like this:

    >> bbox
    bbox =
    
       1592    517   1770    533
    

    The individual values you can get by:

    bbox(1) % x left
    bbox(2) % y top
    bbox(3) % x right
    bbox(4) % y botom
    

    so here's the code for your problem

     [w, wRect]=Screen('OpenWindow', 0, [0 128 128],[],[],[],[],128);
    Screen('TextFont',w, 'Arial'); %Set font
    Screen('TextSize',w, 16); %Set text size
    [nx, ny, bbox] = DrawFormattedText(w, 'HowManyPixelsDoIHave?', 'center', 'center', 60);
    Screen('Flip',w);
    KbWait; %Wait for response before closing
    Screen('CloseAll');
    
    pixelWidth  =  bbox(3) - bbox(1) %x
    pixelHeight = bbox(4) - bbox(2) %y
    

    pixelWidth contains the number of pixels needed to print the whole text (including white space) for your x-axis. pixelHeight does the same for your y-axis.

    I think you should have a look at some matlab/octave basics, the accessing a specific element of a vector is easy to learn and super important.

    Version 2 - how many black pixels are needed for letter B

    There is a function called Screen('GetImage', that saves your current screen to a variable. For this propose we create a window that is 100 * 100 px big. so if we save our window we get a 100*100*3 image as a variable. *3 tell us that there are three layers of that image that are the R the G and the B value of a RGB color space. RGB has values from 0 to 255.

    What we do is we open a window with black [0 0 0] background and write on that screen with a slightly brighter black [1 1 1]. When we save the window now with Screen('GetImage', you get something like this for the first layer image(:,:,1):

      0  0  0  0  0  0  0  0  0  0  0  0  0  0
      0  0  0  0  0  0  0  0  0  0  0  0  0  0
      0  0  0  1  1  1  1  1  1  1  0  0  0  0
      0  0  0  1  0  0  0  0  0  0  1  0  0  0
      0  0  0  1  0  0  0  0  0  0  0  1  0  0
      0  0  0  1  0  0  0  0  0  0  0  1  0  0
      0  0  0  1  0  0  0  0  0  0  1  0  0  0
      0  0  0  1  1  1  1  1  1  1  1  0  0  0
      0  0  0  1  0  0  0  0  0  0  1  0  0  0
      0  0  0  1  0  0  0  0  0  0  0  1  0  0
      0  0  0  1  0  0  0  0  0  0  0  1  0  0
      0  0  0  1  0  0  0  0  0  0  0  1  0  0
      0  0  0  1  0  0  0  0  0  0  1  0  0  0
      0  0  0  1  1  1  1  1  1  1  0  0  0  0
      0  0  0  0  0  0  0  0  0  0  0  0  0  0
      0  0  0  0  0  0  0  0  0  0  0  0  0  0
    

    Just sum that up 2 times and you know how many pixels are contained.

    WINDOWSIZE = [100 100 200 200]
    [w, wRect]=Screen('OpenWindow', 0, [0 0 0] ,WINDOWSIZE );
    
    Screen('TextFont', w, 'Arial'); %Set font
    Screen('TextSize',  w, 16); %Set text size
    Screen('TextColor', w  ,[1 1 1]); % rgb for the textfont displays 1
    
    [nx, ny, bbox] = DrawFormattedText(w, 'Ban', 'center', 'center' );
    Screen('Flip',w);
    ban = Screen('GetImage', w);
    KbWait; %Wait for response before closing
    [nx, ny, bbox] = DrawFormattedText(w, 'San', 'center', 'center' );
    Screen('Flip',w);
    san = Screen('GetImage', w);
    KbWait; %Wait for response before closing
    Screen('CloseAll');
    
    pixelsum_san= sum(sum(san(:,:,1)))
    pixelsum_ban =sum(sum(ban(:,:,1)))
    

    Here's the result:

    pixelsum_san =  79
    pixelsum_ban =  90