2024年5月11日发(作者:)

利用window API实现matlab屏幕抓取函数

摘要:结合如何用window API实现matlab屏幕抓取函数,介绍了在matlab中如何利用matlab与C/C++的接口,调用操

作系统API,扩展matlab功能。

引言

MATLAB 产品家族是美国 MathWorks公司开发的用于概念设计,算法开发,建模仿真,实时实现的理想的集成环境。由于其

完整的专业体系和先进的设计 开发思路,使得 MATLAB 在多种领域都有广阔的应用空间。

尽管MATLAB在科学研究以及工业技术开发方面有着极为广泛的应用,但是它也不是万能的。在某些场合下,MATLAB自身

携带的函数及其组合并无法完全满足用户的要求,而必须通过调用操作系统的API函数来实现。MATLAB在设计时已经考

虑到这点,为我们提供了mex命令,可用于将调用操作系统API函数的C程序编译成DLL文件,也就是MEX文件,使之

成为MATLAB的一个扩展函数。这样,我们在MATLAB环境下编程时就可以直接调用该扩展函数,达到间接调用操作系统

API函数的目的。本文将通过如何为MATLAB编写屏幕抓取函数来演示上述过程。

MEX接口

MEX是MATLAB Executable的缩写,也就是可以在MATLAB中执行。这是MATLAB和其他主要编程语言如C/C++,FORTRAN

的接口。普通的C/C++或是FORTRAN源程序,只要加上一个特殊的接口函数,就能通过MATLAB里的MEX命令编译成一种

特殊的动态链接库函数,而这种函数可以在MATLAB环境下编程时直接调用,与MATLAB内嵌的函数一样。这个特殊的接

口函数相当于C程序中的main函数,是程序的入口,程序的执行就是从这个入口函数开始的。其原型为

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

其中,参数nlhs和nrhs为输出和输入变量的数目,参数plhs和prhs为输出和输入变量指针的指针,prhs是长度为nrhs

的输入变量的指针数组,plhs是长度为nlhs的输出变量的指针数组。

利用window API实现matlab屏幕抓取函数

本质上就是利用C语言调用window API函数来实现屏幕抓取功能,同时,必须处理好C语言与matlab接口问题和C语

言中数组存储与matlab中数组存储的转化问题。

以下是C源程序,有详细的注释。

// matlab mex file to snap the screen

// compile to use>> mex screensnap.c

// usage:1, >>a=screensnap(0) %exclude the matlab window

// >>imshow(a);

// 2, >>a=screensnap(1); %include the matlab window

// >> imshow(a);

// designed by darnshong ********************

// 2005,12,18

#include

#include

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

{

int cx,cy,recnum;

int dims[3],i,j,k;

char *pchar,*mloc;

bool bshowmatlab;//抓屏时是否屏蔽matlab主窗口

HWND hwin,hactw;

HDC dc,memdc;

RECT rect;

HBITMAP hbitm,hold;

BITMAPINFOHEADER binfoh;

if(nrhs!=1) //对输入参数进行检验

mexErrMsgTxt("Need 1 argument!n");

if(!mxIsDouble(prhs[0]))

mexErrMsgTxt("The input argument must be a numeric!n");

if(*(double*)(mxGetData(prhs[0]))==0)

bshowmatlab=false;

else

bshowmatlab=true;

hactw=GetForegroundWindow();//获取matlab的窗口句柄

hwin=GetDesktopWindow();//获取桌面窗口句柄

dc=GetWindowDC(hwin);//获取桌面窗口DC

GetWindowRect(hwin,&rect);//获取桌面窗口大小

cx=;

cy=;

mexPrintf("cx: %d cy: %dn !",cx,cy);

memdc=CreateCompatibleDC(dc);//创建与桌面窗口DC相适应的内存DC

mexPrintf("Handles: %d %d %dn !",hwin,dc,memdc);

hbitm=CreateCompatibleBitmap(dc,cx,cy);//创建相适应的位图

if(hbitm==0)

mexErrMsgTxt("Fail to create a compatible bitmap!n");

if (!(hold=SelectObject(memdc, hbitm))) //将新建的位图选入内存DC中

mexErrMsgTxt("Compatible Bitmap Selection!n");

// Hide the application window.

if(!bshowmatlab)

{

ShowWindow(hactw, SW_HIDE); //屏蔽matlab主窗口

Sleep(100);//延迟100ms,因为在屏蔽matlab主窗口的过程中不能抓屏

}

//Copy color data for the entire display into a

//bitmap that is selected into a compatible DC.

if (!BitBlt(memdc,0,0,cx,cy,dc,0,0,SRCCOPY)) //将桌面窗口DC拷贝到内存DC中

mexErrMsgTxt("Screen to Compat Blt Failed");

dims[0]=cy;//注意cx,cy的顺序

dims[1]=cx;

dims[2]=3;

plhs[0]=mxCreateNumericArray(3,dims,mxUINT8_CLASS,mxREAL);

//创建输出变量空间来传递图像数据

//由于是彩色图像,含RGB三分量,所以为三维数据

pchar=(char*)mxGetData(plhs[0]);

=sizeof(BITMAPINFOHEADER);

h=cx;

ht=-cy;

es=1;

ount=24;

ression=BI_RGB;

Image=0;

sPerMeter=0;

sPerMeter =0;

sed=0;

mportant=0;

//配置位图信息头结构

mloc=(char*)mxMalloc(cx*cy*3);

//申请空间来存放图像数据

recnum=GetDIBits(memdc,hbitm,0,cy,mloc,(BITMAPINFO*)&binfoh,DIB_RGB_COLORS);

//将图像数据复制到mloc空间里

mexPrintf("Copyed %d lines %dn!",recnum,hbitm);

for(k=0;k<3;k++)

for(j=0;j

for(i=0;i

{

pchar[i*cy+j+k*cx*cy]=mloc[(j*cx+i)*3+2-k];

//由于matlab中数据存储是先列后行的,与C程序中先行后列不一样

//图像数据在复制到输出变量时必须进行适当的处理

}

mxFree(mloc);//释放申请的内存空间

SelectObject(hbitm,hold);

DeleteDC(memdc);

ReleaseDC(hwin,dc);

DeleteObject(hbitm);

//完成之后进行必要的处理防止内存泄漏

if(!bshowmatlab)

ShowWindow(hactw, SW_SHOW);

//恢复matlab主窗口的显示

}