VxWorks操作系统是风河(WindRiver)公司于1983年设计开发的一种嵌入式实时操作系统。它以其卓越的实时性及可靠性被广泛地应用于通信、军事、航空、航天等实时性和可靠性要求较高的领域中[1-2]。为了提供系统对多媒体技术的支持,VxWorks提供了WindML多媒体开发组件,利用该组件用户可以方便、高效地开发出基于VxWorks的图形界面。本文主要介绍WindML配置方法,基于WindML的图形开发及图片显示的关键技术,提出了一种屏幕任意矩形区域图像截取方法,利用VxSim工具进行仿真,给出了仿真后的结果和关键代码。
1 WindML概述Wind media library(WindML)提供了对VxWorks嵌入式操作系统应用多媒体技术的支持[3],它提供了丰富的图形、视频和音频操作接口,用来开发多媒体应用程序及驱动程序。WindML包括:软件开发组件(SDK)和驱动开发组件(DDK)。
SDK组件用于多媒体应用程序的开发,该组件提供了一个全面的图形开发函数集,用于处理图形、视频、音频、字体等多媒体操作,允许开发者开发独立于各种硬件平台的可移植代码[3-4]。在首次进行WindML图形开发前,需要对WindML进行配置。
2 WindML配置WindML的配置工作可以使用Tornado的工具菜单项tools下面的WindML配置对话框(如图 1),可视化地完成配置[5-7]。本文实验用到的重要配置参数如下:处理器类型为SIMNT,颜色表类型为16RGB565;分辨率是800×600;勾选Jpeg和双缓冲支持选项。点击Build,编译WindML库,在对应(本文的位置为$(WIND_BASE)\\target\\lib\\simpc\\SIMNT\\gnu)目录下生成一个名为libwndml.a的静态库。将该库文件链接到应用程序中,即可利用WindML提供的API进行图形界面开发。
3 WindML图形界面开发及图片显示技术使用WindML进行图形程序的开发一般有3个步骤:首先设置调色板,然后定义图形上下文,最后调用WindML相关API完成图形的绘制与显示。
下面给出一个WindML图形开发简单例子的关键部分代码[8-10]:
…
uglInitialize(); //UGL 环境初始化
devId = (UGL_DEVICE_ID)uglRegistryFind (UGL_DISPLAY_TYPE,0,0,0)->id; //获取图形显示设备
gc = uglGcCreate(devId); //创建图形显示上下文
下面一段代码负责申请调色板所需要的内存。
uglColorAlloc (devId,& colorTable[BLACK].rgbColor,UGL_NULL,&colorTable[BLACK].uglColor,1);
uglColorAlloc(devId,& colorTable[BLUE].rgbColor,UGL_NULL,& colorTable[BLUE].uglColor,1);
…
至此就完成了WindML图形开发所需要的准备工作,其中调色板部分根据需要进行增减申请内存代码行。
下面介绍WindML中图片显示的基本方法。假定需要显示一幅名字为show.jpg的JPEG图片到屏幕作为背景图片,下面给出图片显示的关键代码:
//只读方式打开需要显示的图片文件
fp_jpg = fopen("host:D:\\\\show.jpg","rb");
//设置Jpeg参数
jpegMode.quality=75;
jpegMode.smooth=0;
jpegMode.scale=1;
//初始化,并获取jpeg控制句柄
jpegId = uglJpegInit(devId,& jpegVersion);
//设置jpeg解压缩参数
uglJpegModeSet(jpegId,& jpegMode);
//利用WindML提供的API读取jpeg图片数据到jpegId
uglJpegToDDBFromFile(jpegId,fp_jpg,& jpegDdbId,UGL_NULL,0,0);
uglBitmapSizeGet(jpegDdbId,& jpegWidth,& jpegHeight); //获取图片的高度和宽度
//将jpeg图片显示在屏幕上
uglBitmapBlt(gc,jpegDdbId,0,0,jpegWidth-1,pegHeight-1,UGL_DEFAULT_ID,0,0);
同时可以利用WindML提供的API进行基础绘图工作,例如uglLine用于画线操作,uglEllipse用于绘制椭圆,uglRectangle用于绘制矩形等。本文以椭圆为例,其他复杂的图形设计,可以同理实现。具体代码如下:
uglForegroundColorSet(gc,colorTable[BLUE].uglColor);//设置前景色,蓝色
uglBackgroundColorSet(gc,colorTable[BLACK].uglColor);//设置背景色,黑色
uglLineWidthSet(gc,5); //设置线条宽度
uglEllipse(gc,100,100,300,300,0,0,0,0);//在坐标(100,100)处绘制半径为200的圆
uglGcDestroy (gc); //释放资源
…
至此,完成图形显示功能,即背景图片的显示和绘制了一个蓝色外边框,背景色为黑色的圆形图案,使用Tornado2.2进行编译,利用Tornado自带模拟测试工具VxSim进行模拟测试,这里需要注意,适当增加默认的Memory Size值,例如本次使用的Memory Size为200 000 000,否则在图片显示阶段,会因为内存不足而报错。实验结果如图 2所示。
4 局部截图技术实现在应用中,可能需要将当前感兴趣的内容截图,在Windows环境下,可以按下键盘PrtSc完成屏幕的全屏截图,网上也有很多优秀的局部截图工具可用,然而在Vxworks操作系统环境里,却没有这样方便的系统接口可以使用,而在实际应用中同样面临着截图的需要,鉴于此提出了一种基于Vxworks操作系统的屏幕任意矩形区域的截图方法,并且能够将截图内容以jpg和bmp两种常用的图片存储格式进行存储,便于后续的使用。
4.1 流程图本文提出的截图方法具体流程如图 3所示。
4.2 关键代码首先给出BMP格式的定义如下:
typedef struct tagBIAMAPFILEHEADER
{//14字节BMP文件头定义
WORD bfType;// 0x4D42
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
}BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{//40字节BMP信息头定义
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
}BITMAPINFOHEADER;
lineBytes = (capWidth*3+3)/4*4;//bmp图片每行所需要字节数目,需要4 bytes对齐。
为了读取显存数据,调用uglBitmapRead方法;将整个屏幕图形缓存读取到pDib数据结构中。将pDib对应的数据区内容按照矩形区域进行截取,并且将RGB565颜色模式转换为BMP存储需要的RGB888颜色模式,具体的代码如下所示:
for(i=left; i < right;++i)
for(j=top; j < bottom; ++j)
{
pSaveBuf[((j-top)*capWidth + i-left)*4] = ((unsigned char *)(pDib->pImage))[(j*screenWidth+i)*4] pSaveBuf[((j-top)*capWidth + i-left)*4+1] = ((unsigned char *)(pDib->pImage))[(j*screenWidth+i)*4+1];
pSaveBuf[((j-top)*capWidth + i-left)*4+2] = ((unsigned char *)(pDib->pImage))[(j*screenWidth+i)*4+2];
pSaveBuf[((j-top)*capWidth + i-left)*4+3] = ((unsigned char *)(pDib->pImage))[(j*screenWidth+i)*4+3];
//将读取的RGB565彩色模式转换为bmp彩色模式
Blue = (pSaveBuf[((j-top)*capWidth+i-left)*4] & 0x1f) < < 3;
Green = (pSaveBuf[((j-top)*capWidth+i-left)*4]>>5 | ((pSaveBuf[((j-top)*capWidth+i-left)*4+1] & 0x07) < < 3)) < < 2;
Red = pSaveBuf[((j-top)*capWidth+i-left)*4+1]& 0xf8;
pBmpBuf[(bottom-j)*lineBytes+(i-left)*3] = Blue;
pBmpBuf[(bottom-j)*lineBytes+(i-left)*3+1] = Green;
pBmpBuf[(bottom-j)*lineBytes+(j-left)*3+2] = Red;
}
利用uglJpegFromDDB(jpegId,capDdbId,0,0,capWidth-1,capHeight-1,fp),来实现JPEG文件类型的存储。
4.3 注意事项这里需要注意的要点有: WindML中每个像素用4个字节表示,本次WindML使用的颜色类型是RGB565格式,颜色排布如图 4所示。BMP24色模式中,每个像素使用3个字节来表示,按照G(绿色)、B(蓝色)和R(红色)顺序排列。因此需要将RGB565 颜色类型转换到BMP所需要的格式,具体转换过程参见上述代码。
4.4 实验结果将上述代码编译并使用VxSim进行测试,给出1次截图的结果,如图 5所示。
5 结束语为了解决VxWorks操作系统下屏幕截图问题,提出了一种基于WindML的截图方法。实验结果表明,本文给出的方法能够灵活的、高效的完成VxWorks操作系统下的屏幕任意矩形区域图像截图任务,填补了VxWorks操作系统下没有自带截图工具的空白。实际应用中,可以利用本文提出的截图方法对VxWorks下图形界面中感兴趣的画面进行截图,记录当前画面的瞬态效果,以便后续的对比研究。
本文的研究内容可进一步深入:利用截取屏幕的方法进行屏幕录制。首先按照一定频率截取屏幕内容,然后利用视频压缩算法(如H.264)转换为视频数据并保存为视频格式文件,即完成了屏幕录制功能,本文作者正在进行相关的研究。
[1] | 胥小武, 余立建, 刘洪雨. 在WindML下汉字、图形界面及图片显示的开发研究[J]. 铁路计算机应用,2014, 23 (8) : 49 –52. |
[2] | 蔡华, 卞新高, 史中权, 等. 基于VxWorks的WindML图形界面开发方法[J]. 工业控制计算机,2005, 18 (8) : 28 –30. |
[3] | 郑元珠. 基于VxWorks操作系统的雷达显示软件屏幕截图技术研究[J]. 舰船电子对抗,2010, 33 (2) : 116 –120. |
[4] | 陈恩庆, 宋豫冀, 王忠勇. VxWorks下图形用户界面的开发[J]. 微计算机信息,2003, 19 (3) : 48 –49. |
[5] | Wind River. VxWorks Programmer's guide 5.4[M]. Alameda, USA: WindRiver Systems Inc, 1999 . |
[6] | Wind River. Tornado user's guide[M]. Alameda, USA: Wind River Systems Inc., 1999 . |
[7] | 孔样营, 柏桂枝. 嵌入式实时操作系统VxWorks及其开发环境Tornado[M]. 北京: 中国电力出版社, 2002 : 89 -92. |
[8] | 邝坚. Tornado/VxWorks入门与提高[M]. 北京: 科学出版社, 2004 : 11 -35. |
[9] | 王国夫, 孙尧, 苏柏泉. WindML事件驱动机制分析[J]. 计算机工程,2003, 29 (10) : 193 –195. |
[10] | 练学辉, 朱佳丽, 乔大雷. 基于WindML的图形开发与应用[J]. 雷达与对抗,2015, 35 (1) : 65 –68. |