您的位置:首页 > 其它

EasyPlayerPro Windows播放器本地快照抓拍截图功能实现方法

2017-12-25 14:04 711 查看

背景描述

作为一个播放器,截图功能必不可少; 下面主要记录一下截图功能的实现;



实现流程

将解码后的帧进行格式转换(目标格式为RGB24);

采用独立的线程进行截图处理;

截图可保存为BMP或JPG两种格式;



代码实现

#define _WIDTHBYTES(c)  ((c+31)/32*4)   // c = width * bpp
int Snapshot2File(RENDER_FORMAT renderFormat, SNAPSHOT_IMAGE_T *pSnapshot, char *pbuf)
{
PBYTE   pDest = NULL, pDest16 = NULL;
INT     nBpp;
DWORD   dwW, dwH, dwWB;

int     ret = 0;

int image_format = pSnapshot->imageFormat;

if (renderFormat == RENDER_FORMAT_YUY2)             nBpp    =   16;
else if (renderFormat == RENDER_FORMAT_UYVY)        nBpp    =   16;
else if (renderFormat == RENDER_FORMAT_X8R8G8B8)    nBpp    =   32;     //ok
else if (renderFormat == RENDER_FORMAT_A8R8G8B8)    nBpp    =   32;     //ok
else if (renderFormat == RENDER_FORMAT_RGB565)      nBpp    =   16;     //ok
else if (renderFormat == RENDER_FORMAT_RGB555)      nBpp    =   16;     //ok
else if (renderFormat == RENDER_FORMAT_RGB24_GDI)   nBpp    =   24;
else    return -1;      //格式错误

dwW  = pSnapshot->width;
dwH  = pSnapshot->height;
dwWB = _WIDTHBYTES( dwW * nBpp );

if (image_format == 0x00)
{
//BMP
int iFilenameLen = (int)strlen(pSnapshot->filename);

if ( (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "bmp", 3)) &&
(0 != memcmp(pSnapshot->filename+iFilenameLen-3, "BMP", 3)) &&
(0 != memcmp(pSnapshot->filename+iFilenameLen-3, "Bmp", 3)) )
{
if (pSnapshot->filename[iFilenameLen-4] == '.')
{
for (int i=iFilenameLen-1; i>0; i--)
{
if (pSnapshot->filename[i] == '.')
{
pSnapshot->filename[i] = '\0';
break;
}
else
{
pSnapshot->filename[i] = '\0';
}
}
}
strcat(pSnapshot->filename, ".bmp");
}

HANDLE hFile = CreateFile( pSnapshot->filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,       CREATE_ALWAYS,  FILE_ATTRIBUTE_NORMAL,  NULL );
if( hFile == INVALID_HANDLE_VALUE ) return E_HANDLE;

// SaveFile to BMP
BITMAPFILEHEADER bfh = {0};
bfh.bfType      = 0x4D42;
bfh.bfSize      = 0;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
if( nBpp == 16 ) {
bfh.bfOffBits += sizeof(RGBQUAD) * 3;
}
else
if( nBpp == 24 ) {
bfh.bfOffBits += sizeof(RGBQUAD) * 1;
}
else
if( nBpp == 32 ) {
bfh.bfOffBits += sizeof(RGBQUAD) * 1;
}
DWORD dwWriteLength = sizeof(BITMAPFILEHEADER);
DWORD dwWrittenLength = 0;
WriteFile( hFile, (PVOID)&bfh, dwWriteLength, &dwWrittenLength, NULL );

BITMAPINFOHEADER    bih = {0};
bih.biSize      = sizeof(BITMAPINFOHEADER);
bih.biWidth     = dwW;
bih.biHeight    = -(INT)dwH;
bih.biPlanes    = 1;
bih.biBitCount  = nBpp;
bih.biCompression   = (nBpp == 16) ? BI_BITFIELDS : BI_RGB;
bih.biSizeImage     = dwWB * pSnapshot->height;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed       = 0;
bih.biClrImportant  = 0;

dwWriteLength = sizeof(BITMAPINFOHEADER);
WriteFile( hFile, (PVOID)&bih, dwWriteLength, &dwWrittenLength, NULL );

if( nBpp == 16 ) {

DWORD argbQuad[3] = {0};
if (renderFormat == RENDER_FORMAT_RGB565)
{
argbQuad[0] = 0x00F800;     // Red mask
argbQuad[1] = 0x0007E0;     // Green mask
argbQuad[2] = 0x00001F;     // Blue mask
}
else
{
argbQuad[0] = 0x007C00;     // Red mask
argbQuad[1] = 0x0003E0;     // Green mask
argbQuad[2] = 0x00001F;     // Blue mask
}
dwWriteLength = sizeof(argbQuad);
WriteFile( hFile, (PVOID)&argbQuad[0], dwWriteLength, &dwWrittenLength, NULL );
}
else
if( nBpp == 24 ) {
DWORD rgbQuad = 0;
dwWriteLength = sizeof(rgbQuad);
WriteFile( hFile, (PVOID)&rgbQuad, dwWriteLength, &dwWrittenLength, NULL );
}
else if( nBpp == 32 ) {
DWORD rgbQuad = 0;
dwWriteLength = sizeof(rgbQuad);
WriteFile( hFile, (PVOID)&rgbQuad, dwWriteLength, &dwWrittenLength, NULL );
}

dwWriteLength = dwWB * pSnapshot->height;
WriteFile( hFile, (PVOID)pbuf, dwWriteLength, &dwWrittenLength, NULL );
CloseHandle( hFile );

if (dwWrittenLength < 1)
{
DeleteFile(pSnapshot->filename);
}
}
else if (image_format == 0x01)
{
//JPG
int iFilenameLen = (int)strlen(pSnapshot->filename);

if ( (0 != memcmp(pSnapshot->filename+iFilenameLen-3, "jpg", 3)) &&
(0 != memcmp(pSnapshot->filename+iFilenameLen-3, "JPG", 3)) &&
(0 != memcmp(pSnapshot->filename+iFilenameLen-3, "Jpg", 3)) )
{
if (pSnapshot->filename[iFilenameLen-4] == '.')
{
for (int i=iFilenameLen-1; i>0; i--)
{
if (pSnapshot->filename[i] == '.')
{
pSnapshot->filename[i] = '\0';
break;
}
else
{
pSnapshot->filename[i] = '\0';
}
}
}
strcat(pSnapshot->filename, ".jpg");
}

BOOL bres = TRUE;
IJLERR jerr;
DWORD dibPadBytes;
JPEG_CORE_PROPERTIES jcprops;

__try
{
jerr = ijlInit(&jcprops);

if (IJL_OK != jerr)
{
bres = FALSE;
__leave;
}

dibPadBytes = IJL_DIB_PAD_BYTES(dwW, 3);

jcprops.DIBWidth = dwW;
jcprops.DIBHeight = dwH;
jcprops.DIBBytes = (unsigned char*)pbuf;//reinterpret_cast<BYTE *>(&pbi->bmiHeader) + sizeof(BITMAPINFOHEADER);

jcprops.DIBPadBytes = dibPadBytes;
jcprops.DIBChannels = 3;
jcprops.DIBColor = IJL_BGR;

jcprops.JPGFile = const_cast<LPSTR>(pSnapshot->filename);

jcprops.JPGWidth = dwW;
jcprops.JPGHeight = dwH;

jcprops.JPGChannels = 3;
jcprops.JPGColor = IJL_YCBCR;
jcprops.JPGSubsampling = IJL_411;
jcprops.jquality = 95;

jerr = ijlWrite(&jcprops, IJL_JFILE_WRITEWHOLEIMAGE);

if (IJL_OK != jerr)
{
if (IJL_FILE_ERROR == jerr)
{
}
ret = jerr;
bres = FALSE;

if (ret == -23)
{
DeleteFile(pSnapshot->filename);
}
}
}

__finally
{
ijlFree(&jcprops);
}

}

if (NULL != pDest)
{
delete []pDest;
pDest = NULL;
}

return ret;
}


关于EasyPlayerPro

EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP、RTMP、HTTP、HLS、UDP、RTP、File等多种流媒体协议播放、支持本地文件播放,支持本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等多种功能特性,核心基于ffmpeg,稳定、高效、可靠、可控,支持Windows、Android、iOS三个平台,目前在多家教育、安防、行业型公司,都得到的应用,广受好评!


EasyPlayerPro:https://github.com/EasyDSS/EasyPlayerPro

点击链接加入群【EasyPlayer & EasyPlayerPro】:544917793



获取更多信息

邮件:support@easydarwin.org

EasyDarwin开源流媒体服务器:www.EasyDarwin.org

EasyDSS商用流媒体解决方案:www.EasyDSS.com

EasyNVR无插件直播方案:www.EasyNVR.com

Copyright © EasyDarwin Team 2012-2017

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: