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

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

基于Directshow框架使用Windows渲染器VMR叠加水印 if (FAILED(lpDDraw7->SetCooperativeLevel(m_hShowWin, DDSCL_NORMAL)))
基于Directshow框架使用Windows渲染器VMR叠加水印 {
基于Directshow框架使用Windows渲染器VMR叠加水印  return ;
基于Directshow框架使用Windows渲染器VMR叠加水印 }

基于Directshow框架使用Windows渲染器VMR叠加水印 
基于Directshow框架使用Windows渲染器VMR叠加水印 DDSURFACEDESC2 ddsd;
基于Directshow框架使用Windows渲染器VMR叠加水印 ZeroMemory(&ddsd, sizeof(ddsd));
基于Directshow框架使用Windows渲染器VMR叠加水印   ddsd.dwSize = sizeof(ddsd);
基于Directshow框架使用Windows渲染器VMR叠加水印   ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
基于Directshow框架使用Windows渲染器VMR叠加水印   ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
基于Directshow框架使用Windows渲染器VMR叠加水印   ddsd.dwWidth = xs;
基于Directshow框架使用Windows渲染器VMR叠加水印 ddsd.dwHeight = ys;
基于Directshow框架使用Windows渲染器VMR叠加水印  ddsd.ddpfPixelFormat.dwSize =sizeof(DDPIXELFORMAT);
基于Directshow框架使用Windows渲染器VMR叠加水印  ddsd.ddpfPixelFormat.dwFlags =DDPF_RGB | DDPF_ALPHAPIXELS;
基于Directshow框架使用Windows渲染器VMR叠加水印  ddsd.ddpfPixelFormat.dwRGBBitCount =32;
基于Directshow框架使用Windows渲染器VMR叠加水印   ddsd.ddpfPixelFormat.dwRBitMask=0x00ff0000;
基于Directshow框架使用Windows渲染器VMR叠加水印   ddsd.ddpfPixelFormat.dwGBitMask=0x0000ff00;
基于Directshow框架使用Windows渲染器VMR叠加水印   ddsd.ddpfPixelFormat.dwBBitMask=0x000000ff;
基于Directshow框架使用Windows渲染器VMR叠加水印 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask=0xff000000;
基于Directshow框架使用Windows渲染器VMR叠加水印  if(FAILED(lpDDraw7->CreateSurface(&ddsd, lpSource, NULL)))
基于Directshow框架使用Windows渲染器VMR叠加水印 {
基于Directshow框架使用Windows渲染器VMR叠加水印  return ;
基于Directshow框架使用Windows渲染器VMR叠加水印 }

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

基于Directshow框架使用Windows渲染器VMR叠加水印    else if(bpp == 32)
基于Directshow框架使用Windows渲染器VMR叠加水印    {
基于Directshow框架使用Windows渲染器VMR叠加水印     *dest++ = lpBytes[xPos];
基于Directshow框架使用Windows渲染器VMR叠加水印     xPos ++;
基于Directshow框架使用Windows渲染器VMR叠加水印    }

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

基于Directshow框架使用Windows渲染器VMR叠加水印 
基于Directshow框架使用Windows渲染器VMR叠加水印   dest += dds.lPitch - width;
基于Directshow框架使用Windows渲染器VMR叠加水印  }

基于Directshow框架使用Windows渲染器VMR叠加水印  lpSurface->Unlock(NULL);
静态图片的数据赋给离屏表面,上面代码采用的是操作内存的方式,如果采用
lpSurface->GetDc(&hdc)的方式,然后通过BitBlt方式绘制的话,alpha通道会丢失,达不到水印的完美呈现
上一篇:uniapp 扩展组件抽屉的使用


下一篇:input(type="file")+Handler(一般处理程序)上传文件简单Demo