基于Directshow框架使用Windows渲染器VMR叠加水印
2023-09-27 14:27:58 时间
对于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;
for( int yPos = 0; yPos img.GetHeight(); yPos++)
{
LPBYTE lpBytes = lpBits + ( yPos * nPitch );
int width = img.GetWidth( ) * (bpp / 8);
for( int 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通道会丢失,达不到水印的完美呈现
最近在写WPF界面的时候遇到一个情况,由于界面已经由UI设计师用PS和AI软件画好了,在做UI的时候直接照着图做就行.
令人惊讶的是,您现在可以通过对Xamarin.Forms解决方案进行一些调整来运行本机macOS应用程序。 而我必须说“应用程序”,因为那是桌面,对吧?
正如我在上周的Xamarin.Forms 2.3.5预发布公告中所说的,XAMarin.Forms中的macOS支持现在已经在Preview中了。
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;
for( int yPos = 0; yPos img.GetHeight(); yPos++)
{
LPBYTE lpBytes = lpBits + ( yPos * nPitch );
int width = img.GetWidth( ) * (bpp / 8);
for( int 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通道会丢失,达不到水印的完美呈现
最近在写WPF界面的时候遇到一个情况,由于界面已经由UI设计师用PS和AI软件画好了,在做UI的时候直接照着图做就行.
令人惊讶的是,您现在可以通过对Xamarin.Forms解决方案进行一些调整来运行本机macOS应用程序。 而我必须说“应用程序”,因为那是桌面,对吧?
正如我在上周的Xamarin.Forms 2.3.5预发布公告中所说的,XAMarin.Forms中的macOS支持现在已经在Preview中了。
相关文章
- [Windows 驱动开发] 清内存强杀进程
- Windows PE 第八章 延迟加载导入表
- windows-CODE注入(远程线程注入)
- How to: Create a Windows Communication Foundation Client
- windows安装程序无法将windows配置为在此计算机的硬件上运行
- 基线管理与安全配置——Windows安全配置
- Windows-009-Win7 操作系统安装图文详解
- YII 框架在windows系统下的安装
- 微软拒绝联想继续在Skylake平台支持Windows 7/8.1的请求
- Windows下Hadoop的环境安装[转]
- windows nginx
- windows下配置git
- RDIFramework.NET框架SOA解(集Windows服务、WinForm形式和IIS发布形式)-分布式应用程序
- windows server 如要远程登录,你需要具有通过远程桌面服务进行登录的权限。
- 【cmd】windows cmd命令大全
- windows计划任务定时运行synctoy的坑
- Windows Azure下如何安装 MongoDb
- Linux虚拟机创建后如何进行登录(Windows Azure)
- 悲剧!数据显示Windows 10商用占比仍不如XP数量
- SQL Server windows身份验证和SQL Server身份验证的连接字符串
- windows下载安装ElasticSearch
- [转载]DLL劫持生成器 源码开放(纯WINDOWS SDK)+ 实例分析