天天看点

基于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叠加水印
基于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叠加水印
基于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叠加水印
基于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叠加水印

  for( int 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叠加水印

   for( int 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通道会丢失,达不到水印的完美呈现

继续阅读