基于Directshow框架使用Windows渲染器VMR叠加水印

简介:
对于windows系统,EVR/VMR9/VMR渲染器均提供了叠加静态图片的接口:
SetAlphaBitmap();
 
此接口支持静态图片的资源使用方式,一种是HDC,一种是SURFACE;
使用发现,如果静态图片不规则,是有Alpha通道的不同取值形成,
则通过HDC叠加的会有黑边存在;
 
对于EVR/VMR9可采用SURFACE,使用D3D创建,完美水印效果相对容易实现,略过;
对于VMR渲染器,SURFACE需要基于DirectDraw创建离屏表面;
 
离屏表面创建后,静态图片数据使用决定着是否能完美呈现水印效果;
一种是通过离屏表面获取HDC,操作HDC,把静态图片附加给离屏表面,
一种是通过直接操作离屏表面的内存数据地址;
 
经过几天的摸索,实现了比较完美的水印效果,代码如下:
LPDIRECTDRAW7 lpDDraw7;
 
   if(FAILED(DirectDrawCreateEx(NULL, (LPVOID *)&lpDDraw7, IID_IDirectDraw7, NULL)))
   {
   return ;
  }

  if (FAILED(lpDDraw7->SetCooperativeLevel(m_hShowWin, DDSCL_NORMAL)))
  {
  return ;
 }

 
 DDSURFACEDESC2 ddsd;
 ZeroMemory(&ddsd,  sizeof(ddsd));
   ddsd.dwSize =  sizeof(ddsd);
   ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
   ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
   ddsd.dwWidth = xs;
 ddsd.dwHeight = ys;
  ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  ddsd.ddpfPixelFormat.dwFlags =DDPF_RGB | DDPF_ALPHAPIXELS;
  ddsd.ddpfPixelFormat.dwRGBBitCount =32;
   ddsd.ddpfPixelFormat.dwRBitMask=0x00ff0000;
   ddsd.ddpfPixelFormat.dwGBitMask=0x0000ff00;
   ddsd.ddpfPixelFormat.dwBBitMask=0x000000ff;
 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask=0xff000000;
   if(FAILED(lpDDraw7->CreateSurface(&ddsd, lpSource, NULL)))
  {
  return ;
 }

 
 
lpSurface->Restore();
  CImage img;
  HRESULT result;
  result = img.Load(_bstr_t(path));
   if(!SUCCEEDED(result))
    return ;
  LPBYTE lpBits = (LPBYTE)img.GetBits();
   int nPitch = img.GetPitch();
   int imgWidth = img.GetWidth();
   int bpp = img.GetBPP();
   if(bpp != 24 && bpp != 32)
    return ;
 
  DDSURFACEDESC2 dds;
  ZeroMemory(&dds,0, sizeof(dds));
  dds.dwSize   =    sizeof(dds);
   if(DD_OK != lpSurface->Lock(NULL, &dds, DDLOCK_WAIT, NULL))
    return;
 
  LPBYTE dest = (LPBYTE)dds.lpSurface;
   forint yPos = 0; yPos < img.GetHeight(); yPos++)
   {
   LPBYTE lpBytes = lpBits + ( yPos * nPitch );
   int width = img.GetWidth( ) * (bpp / 8);
 
   forint xPos = 0; xPos < width; )
   {
    if(bpp == 24)
    {
 
     *dest++ = lpBytes[xPos ];
     *dest++ = lpBytes[xPos + 1];
     *dest++ = lpBytes[xPos + 2];
     *dest++ = 0xff;
 
     xPos += 3 ;
    }

    else if(bpp == 32)
    {
     *dest++ = lpBytes[xPos];
     xPos ++;
    }

   }

 
   dest += dds.lPitch - width;
  }

  lpSurface->Unlock(NULL);
静态图片的数据赋给离屏表面,上面代码采用的是操作内存的方式,如果采用
lpSurface->GetDc(&hdc)的方式,然后通过BitBlt方式绘制的话,alpha通道会丢失,达不到水印的完美呈现
目录
相关文章
震惊!Windows Service服务和定时任务框架quartz之间原来是这种关系……(上)
震惊!Windows Service服务和定时任务框架quartz之间原来是这种关系……
|
调度 C# Windows
震惊!Windows Service服务和定时任务框架quartz之间原来是这种关系……(下)
震惊!Windows Service服务和定时任务框架quartz之间原来是这种关系……(下)
|
25天前
|
Linux C# iOS开发
开源GTKSystem.Windows.Forms框架让C# Winform支持跨平台运行
开源GTKSystem.Windows.Forms框架让C# Winform支持跨平台运行
53 12
|
1月前
|
安全 Ubuntu Linux
Metasploit Pro 4.22.6-2024111901 (Linux, Windows) - 专业渗透测试框架
Metasploit Pro 4.22.6-2024111901 (Linux, Windows) - 专业渗透测试框架
51 9
Metasploit Pro 4.22.6-2024111901 (Linux, Windows) - 专业渗透测试框架
|
3月前
|
资源调度 编译器 Linux
Windows10系统安装Truffle框架,安装失败,提示:error An unexpected error occurred: “https://xxxxx
Windows10系统安装Truffle框架,安装失败,提示:error An unexpected error occurred: “https://xxxxx
118 0
|
5月前
|
Python Windows 内存技术
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
|
Dart 前端开发 Java
用Jetpack Compose Desktop极简配置做一个Windows桌面时间显示器(compose框架入门向)
compose的模板配置多少有些臃肿,如果只做单一平台多少是会简单一些的。但几乎没怎么见过配置很简单的例子,都是套那些模板,我觉得没必要搞那么复杂,那么本文就做一个非常简单的只有几行代码的小例子
2061 0
|
网络安全 Windows
基于fastapi实现6个接口(token拦截, 2个业务流程,接口参数依赖校验)已经通过postman测试,记录部署服务器和windows,用于pytest接口自动化框架的接口测试对象
基于fastapi实现6个接口(token拦截, 2个业务流程,接口参数依赖校验)已经通过postman测试,记录部署服务器和windows,用于pytest接口自动化框架的接口测试对象
|
Java jenkins 持续交付
pytest自动化框架集成jenkins+gitee+allure,使用git下拉代码和本地代码实现,基于windows
pytest自动化框架集成jenkins+gitee+allure,使用git下拉代码和本地代码实现,基于windows
|
Linux PHP Docker
Windows下PHP微服务框架Hyperf Swoole开发部署(Docker方式)
Windows下PHP微服务框架Hyperf Swoole开发部署(Docker方式)
880 0
Windows下PHP微服务框架Hyperf Swoole开发部署(Docker方式)