2019-07-10

                                                                                                     工作日志: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;

}

你可能感兴趣的:(2019-07-10)