% Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license

function [X,m]=getscreen(varargin)
%GETSCREEN replacement for GETFRAME for systems with multiple monitors. Use it just like you use GETFRAME.
%Can also be used to take screenshots of non-MATLAB windows. Requires JAVA.
%
%Calling options:
% Output X is m*n*3 cdata array. Output m is corresponding colormap (if applicable.)
% [X,m]=getscreen         Gets screenshot of current figure
% [X,m]=getscreen(h)      Gets screenshot of axes or figure with handle h
% [X,m]=getscreen(h,rect) Gets screenshot of at position rect relative to axes or figure with handle h.
% [X,m]=getscreen(rect) Gets screenshot of whatever is on your screen at position vector rect. (Relative to bottom left corner.)
%   rect is a 4 element position vector in pixel units, referenced from bottom left as usual for MATLAB.
%
% By Matt Daskilewicz <mattdaskil@gatech.edu> 11/2008
% www.asdl.gatech.edu
%


%process inputs:
if nargin==0
    h=gcf;
    rect=get(h,'position');
    rect(1:2)=[0 0];

elseif nargin==1
    if numel(varargin{1})==1 %it should be a handle
        h=varargin{1};
        if ~strcmp(get(h,'type'),'axes') && ~strcmp(get(h,'type'),'figure')
            error('First input must be a handle to an axes or figure, or a position vector');
        end

        rect = hgconvertunits(h, get(h,'position'), get(h,'units'), 'pixels', get(h,'parent')); %x/y coords of fighandle in pixels
        rect(1:2)=[1 1];

    elseif numel(varargin{1})==4 %it is a position vector
        h=[];
        rect=varargin{1};
    else % isn't a handle or a position vector
        error('First input must be a handle to an axes or figure, or a position vector');
    end

elseif nargin==2 %should be a handle and a position vector
    h=varargin{1};
    if ~ismember(get(h,'type'),{'figure';'axes'})
        error('First input must be a handle to an axes or figure, or a position vector');
    end

    rect=varargin{2};
    if length(rect)~=4
        error('Second input must be a 4 element position vector.')
    end

else
    error('Too many input arguments')
end


%get monitor resolutions... because java references coords from top of screen, need to know how big
%screens is.
monitorz=get(0,'monitorpositions');
maxheight=max(monitorz(:,4)); %max vertical resolution of all monitors

if ~isempty(h)

    %h is the handle to figure or axes whose origin (first 2 elements of position vector) we're taking
    %rect with respect to.
    origin=getpixelposition(h,true);

    %if axes are in a uipanel, nudge rect slightly to account for panel border.
    if strcmp(get(get(h,'parent'),'type'),'uipanel')
        origin=origin+[1 1 0 0];
    end

    %also need position of the figure containing h, since origin is w.r.t this figure:
    fighandle = ancestor(h,'figure'); %handle of parent figure to h

    figorigin = hgconvertunits(fighandle, get(fighandle,'position'), get(fighandle,'units'), 'pixels', 0); %x/y coords of fighandle in pixels

    if strcmp(get(h,'type'),'figure')
        origin=[1 1 0 0]; %avoid double counting figorigin and origin if fighandle==h
    end


    %% calculate dimensions of rectangle to take screenshot of: (in java coordinates)
    %java coordinates start at top left instead of bottom left, and start at [0,0]. Also "top" is defined as the top of your
    %largest monitor, even if that's not the one you're taking a screenshot from.

    x=figorigin(1)+origin(1)+rect(1)-3;
    y=maxheight-figorigin(2)-origin(2)-rect(2)-rect(4)+3;
    w=floor(rect(3));
    h=floor(rect(4));

    %figure(fighandle); %make sure figure is visible on screen
    %drawnow;

else %there is no figure... just take a screenshot of whatever's on the screen at rect

    rect=floor(rect);

    x=rect(1);
    y=maxheight-rect(2)-rect(4); %java coordinates start at top of screen.
    w=rect(3);
    h=rect(4);
end


%% do java:
robo = java.awt.Robot;
target=java.awt.Rectangle(x,y,w,h);
image = robo.createScreenCapture(target); %take screenshot at rect
rasta=image.getRGB(0,0,w,h,[],0,w); %get RGB data from bufferedimage

%convert java color integers to matlab RGB format:
rasta=256^3+rasta;
B=uint8(mod(rasta,256));
G=uint8(mod((rasta-int32(B))./256,256));
R=uint8(mod((rasta-256*int32(G))./65536,256));

X.cdata=uint8(zeros(h,w,3));
X.cdata(:,:,1)=reshape(R,[w h])';
X.cdata(:,:,2)=reshape(G,[w h])';
X.cdata(:,:,3)=reshape(B,[w h])';
X.colormap=[];

if (nargout == 2)
    m=X.colormap;
    X=X.cdata;
end

