工作日志:QNX截屏与黑屏判断
截屏原理:通过捕获屏幕数据,将数据写入BMP文件,生成一张BMP位图。
黑屏判断原理:遍历捕获屏幕的RBG值,如果RGB为(0,0,0),说明都是黑色,那么就是黑屏。本代码捕获的是32bit数据,分别是A R G B(阿尔法透明度、红、绿、蓝),每项各一个字节,所以是32bit。然后循环遍历RGB的值,也可以将数据写入BMP文件后再打开BMP文件在去读RGB也可以,本文是在写BMP之前遍历数据的。
此书省略.h声明
void CScreenShot::WriteBitmapHeader(int nbytes, int fd, const int size[])
{ //写BMP文件头
char header[54];
/* Set standard bitmap header */
header[0] = 'B';
header[1] = 'M';
header[2] = nbytes & 0xff;
header[3] = (nbytes >> 8) & 0xff;
header[4] = (nbytes >> 16) & 0xff;
header[5] = (nbytes >> 24) & 0xff;
header[6] = 0;
header[7] = 0;
header[8] = 0;
header[9] = 0;
header[10] = 54;
header[11] = 0;
header[12] = 0;
header[13] = 0;
header[14] = 40;
header[15] = 0;
header[16] = 0;
header[17] = 0;
header[18] = size[0] & 0xff;
header[19] = (size[0] >> 8) & 0xff;
header[20] = (size[0] >> 16) & 0xff;
header[21] = (size[0] >> 24) & 0xff;
header[22] = -size[1] & 0xff;
header[23] = (-size[1] >> 8) & 0xff;
header[24] = (-size[1] >> 16) & 0xff;
header[25] = (-size[1] >> 24) & 0xff;
header[26] = 1;
header[27] = 0;
header[28] = 32;
header[29] = 0;
header[30] = 0;
header[31] = 0;
header[32] = 0;
header[33] = 0;
header[34] = 0; /* image size*/
header[35] = 0;
header[36] = 0;
header[37] = 0;
header[38] = 0x9;
header[39] = 0x88;
header[40] = 0;
header[41] = 0;
header[42] = 0x9l;
header[43] = 0x88;
header[44] = 0;
header[45] = 0;
header[46] = 0;
header[47] = 0;
header[48] = 0;
header[49] = 0;
header[50] = 0;
header[51] = 0;
header[52] = 0;
header[53] = 0;
/* Write bitmap header to file */
write(fd, header, sizeof(header));
}
void CScreenShot::WriteBitmapFile(const int size[], const char* screenshot_ptr,
const int screenshot_stride,
const BITMAP_FILE_PATH emFileIndex,
const bool bDetectScreen)
{
int nbytes; /* number of bytes of the bimap */
int fd; /* file descriptor */
int i; /* iterator to iterate over the screenshot buffer */
const char *fname = NULL; /* bitmap filename */
unsigned int *pScreenShotData = (unsigned int *)screenshot_ptr;
switch(emFileIndex)
{
case BM_BLACKSCREEN_PATH: fname = BM_BLACKSCREEN_PATH_; break;
case BM_LAMPMONITO_PATH: fname = BM_LAMPMONITO_PATH_; break;
default: fname = BM_BLACKSCREEN_PATH_; break;
}
/* Calculate the size of the bitmap */
nbytes = size[0] * size[1] * 4;
/* Perform this action only if you need to detect a black screen */
if(bDetectScreen)
{
for ( i = 0; i < nbytes / 4; i++ )
{
if ( pScreenShotData[i] & 0x00ffffff ) {
break;
}
}
/*Blank Screen*/
if ( i >= nbytes / 4 ) {
printf(" Program error, black screen detected\n");
}
/*Normal screen display*/
else
{
// printf("BlackScreenDet : Screen display is normal ......................\n\n");
}
}
/* Open file*/
fd = creat(fname, S_IRUSR | S_IWUSR);
/* Write the standard bitmap header */
WriteBitmapHeader(nbytes, fd, size);
/* Write screenshot buffer contents to bitmap file */
/* stride: The number of pixels written horizontally one line at a time (x->1920 * 4)*/
for (i = 0; i < size[1]; i++) {
write(fd, screenshot_ptr + i * screenshot_stride, size[0] * 4);
}
close(fd);
}
int CScreenShot::CaptureADisplayScreenShot(const BITMAP_FILE_PATH emFileNameIndex, const bool bDetectScreen)
{//截屏(基本上都是协同调用)
screen_context_t screen_ctx = NULL;
screen_display_t screen_disp = NULL;
screen_display_t *screen_displays = NULL;
screen_pixmap_t screen_pix = NULL;
screen_buffer_t screen_buf = NULL;
char *disp = NULL;
int size[2] = { 0, 0 };
int val;
void *pointer = NULL;
int stride;
int count, id, type;
//int i;
/*创建screen上下文(关联设备的切入口)
* 获取screen上下文显示器设备
* 创建pixmap(像素图:屏幕当前显示的像素)
* 将pixmap关联到内存(screen_buffer_t)
* 获取内存的指针
* screen_read_display()
*/
/* Create the privileged context so that the display properties can be accessed. */
screen_create_context(&screen_ctx, SCREEN_DISPLAY_MANAGER_CONTEXT);
/* Get the number of supported displays with this context. */
count = 0;
screen_get_context_property_iv(screen_ctx, SCREEN_PROPERTY_DISPLAY_COUNT,
&count);
/* Get the displays for this context. */
if (count > 0) {
screen_displays = (screen_display_t*)calloc(count, sizeof(screen_display_t)); ////////////////change
screen_get_context_property_pv(screen_ctx, SCREEN_PROPERTY_DISPLAYS,
(void **)screen_displays);
/* If no display was specified, use the first supported display available for this context. */
if (!disp) {
screen_disp = screen_displays[0];
//printf("run here\n");
/* Otherwise, determine which display has been requested for the screen shot. */
} /*else {
printf("run here else\n");
if (isdigit(*disp)) {
id = strtoul(disp, 0, NULL);
for (i = 0; i < count; i++) {
screen_get_display_property_iv(screen_displays[i], SCREEN_PROPERTY_ID,
&val);
if (val == id) {
screen_disp = screen_displays[i];
break;
}
}
} else {
if (!strcmp(disp, "internal")) {
type = SCREEN_DISPLAY_TYPE_INTERNAL;
} else if (!strcmp(disp, "rgb")) {
type = SCREEN_DISPLAY_TYPE_COMPONENT_RGB;
} else if (!strcmp(disp, "dvi")) {
type = SCREEN_DISPLAY_TYPE_DVI;
} else if (!strcmp(disp, "hdmi")) {
type = SCREEN_DISPLAY_TYPE_HDMI;
} else {
type = SCREEN_DISPLAY_TYPE_OTHER;
}
for (i = 0; i < count; i++) {
screen_get_display_property_iv(screen_displays[i], SCREEN_PROPERTY_TYPE,
&val);
if (val == type) {
screen_disp = screen_displays[i];
break;
}
}
}
}*/
free(screen_displays);
}
if (!screen_disp) {
fputs("no displays\n", stderr);
return 1;
}
/* Create pixmap for the screen shot. */
screen_create_pixmap(&screen_pix, screen_ctx);
/* Set usage flag. */
val = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_USAGE, &val);
/* Set format. 4 channel 32bit*/
val = SCREEN_FORMAT_RGBA8888;
screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_FORMAT, &val);
/* If size is not specified, get the size from the display. */
if (size[0] <= 0 || size[1] <= 0) {
screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, size);
}
/* Set the pixmap buffer size. */
screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_BUFFER_SIZE, size);
/* Create the pixmap buffer and get a handle to the buffer. */
screen_create_pixmap_buffer(screen_pix);
screen_get_pixmap_property_pv(screen_pix, SCREEN_PROPERTY_RENDER_BUFFERS,
(void **)&screen_buf);
/* Get the pointer to the buffer. */
screen_get_buffer_property_pv(screen_buf, SCREEN_PROPERTY_POINTER, &pointer);
/* Get the stride. */
screen_get_buffer_property_iv(screen_buf, SCREEN_PROPERTY_STRIDE, &stride);
/* Take the display screen shot. */
screen_read_display(screen_disp, screen_buf, 0, NULL, 0);
/* Write the screenshot buffer to a bitmap file*/
WriteBitmapFile(size, (const char *)pointer, stride, emFileNameIndex, bDetectScreen);
/* Perform necessary clean-up. */
screen_destroy_pixmap(screen_pix);
screen_destroy_context(screen_ctx);
return 0;
}