http://zhailang.blog.163.com/blog/static/20816711020097302340141/

[转]如何抓取视频画面和游戏画面(二)  

2009-08-30 14:03:40|  分类: 核心编程技术|举报|字号 订阅

 
 

转自:http://topic.csdn.net/t/20051106/11/4374651.html

23 楼ly_liuyang(Liu Yang LYSoft http://lysoft.7u7.net)回复于 2006-01-19 10:42:34 得分 0
最新研究,有了新的发现!!!!!

通过Hook   DDraw的DirectDrawCreate(RealOne用)同DirectDrawCreateEx(WMP用)
获得IDirectDraw(7)
再COM   Hook   CreateSurface,注意RealOne使用的是通过QueryInterface获得IDirectDraw2
WMP则是IDirectDraw7

Hook了CreateSurface后,就能获得OverlaySurface

所以必须在软件使用前,启动全局Hook,才有效


在需要截图的时候
Lock   Overlay   Surface,读取数据,马上Unlock,以免损失性能

解码读出来的数据,即可,但是由于获得的数据是显卡硬件VRAM的数据,一般是YUY2,YV12等格式,需要转换为RGB格式

现在原数据能获取了,就差格式转换,有空再弄,不同的显卡,支持的格式不一样,不同的工具所使用的格式也不一样的,所以这个是比较麻烦的

例如,在我的GF6600上,RealOne(RMVB)用的是YUY2,而WMP(AVI)用的是YV12,还与当前播放的文件格式有关

最简单的方法是,Hook   CreateSurface后,禁止创建Overlay那就普通的方法都能截图,呵呵

24 楼wealsh(工作狂人)回复于 2006-01-21 08:08:43 得分 0
抓视频可以用这个
DSPack   2.33
http://www.2ccc.com/article.asp?articleid=2843

里面带有Demo

25 楼ly_liuyang(Liu Yang LYSoft http://lysoft.7u7.net)回复于 2006-01-21 13:37:56 得分 0
楼上的,方法是不行的
截取别的程序的Overlay   Surface,不是一件容易的事情

现在YV12格式处理,已经做了,能满足普通的需要

视频连续看,觉得还行,但是截图下来的图片,质量就不那么好了

Overlay   Surface截图技术研究,算是告一段落了,成功解决了:)
Top

26 楼UC80862056(Alizee艾莉婕的粉丝)回复于 2006-01-22 17:37:50 得分 0
MV:   la   isla   bonita[Alizee(艾莉婕)]
http://www.mtvup.com/LIST/200553144641469.htm

图像格式转换是很折磨人。

等我仔细看看再问。谢谢了。

27 楼UC80862056(Alizee艾莉婕的粉丝)回复于 2006-02-01 10:31:34 得分 0
如何抓取半透明或指定色透明的窗体?如flashget悬浮窗!

本来打算开始写抓取视频画面的代码的,可是偶然发现用getdc(0),bitblt的方法无法抓取桌面上的半透明和指定色透明的窗体的图像,可是用PrintScreen键却能抓到!真是郁闷死了,不知道为什么?难道这种窗体也是使用了类似覆盖的方式来显示?但是我想这种效果应该是使用了GDI函数将他们与后面的图像合成而成的。不知道PrintScreen键是怎么实现抓取他们的,难道是遍历桌面上的所用窗体,检查他们的属性,找到有半透明和指定色透明属性的窗体然后再用特殊的画法将他们画到截取的桌面图像上?但是这样会不会太慢,而且还要判断窗体的排列顺序等等。总之,我没什么思路!郁闷!真是一步一个坎!

抓取视频和游戏画面的代码我还没开始写,但是我想应该是会遇到一些麻烦的,如:如何知道播放器使用的是什么图像格式?游戏使用的那个版本的DirectX对象等等。以后写的时候遇到具体问题再问其它的吧!

(要求不使用模拟PrintScreen键的方法,因为我已经实现了,但是感觉这种方法是投机取巧。并且模拟PrintScreen键后原来剪贴板中的内容会被覆盖掉,所以这是一种不好的方法。)

28 楼ly_liuyang(Liu Yang LYSoft http://lysoft.7u7.net)回复于 2006-02-03 12:56:31 得分 0
用DX的PRIMARYSURFACE方法就能处理
不要使用普通的GETDC

29 楼reborter(www.xqblog.net我的博客)回复于 2006-02-03 15:08:02 得分 0
学习一下,顶一下

30 楼UC80862056(Alizee艾莉婕的粉丝)回复于 2006-02-05 15:51:50 得分 0
to:ly_liuyang
还用COM钩子替换过程地址吗?还是自己建立主表面来抓屏幕?
能具体点吗?谢谢。
另:祝大家新年快乐!

31 楼ly_liuyang(Liu Yang LYSoft http://lysoft.7u7.net)回复于 2006-02-14 11:03:23 得分 0
情人节快乐~

提供效果程序下载
http://lysoft.lz169.com/projects/DXCapture.rar

支持WMP10,RealOne2,WinDVD6的Overlay   Surface覆盖表面截图

目前仅能转换YV12格式,截图后生成VRAM文件(包括描述文件和显存数据),要支持其他格式,就得另外做的

还有primary   Surface主表明截图,也包括的

暂没开放代码,仅作为技术可行性研究成果,其中的截图库可自由使用.

该贴,也是应该结的了:)

32 楼UC80862056(Alizee艾莉婕的粉丝)回复于 2006-02-14 18:32:39 得分 0
DXCapture运行出错!
Access   violation   at   address   00451341   in   module   'DXCapture.exe'.   Read   of   address   00000000.
==============================================================
主表面截图,这个方法还是无法抓取半透明的窗体,抓取时半透明的窗体会出现短暂时间的隐藏然后又显示出来(GetFrontBuffer执行时出现这种情况),在抓取的图像上没有这个半透明窗体的图像。怎没办?如何解决?

给你写信了。
程序的源文件和DX8.1的头文件在附件中。

再次感谢你的帮助!

33 楼ly_liuyang(Liu Yang LYSoft http://lysoft.7u7.net)回复于 2006-02-15 11:28:55 得分 0
可以截取layered窗口(包括透明窗口)的代码:

procedure   CaptureScreen(AFileName:   string);
const
      CAPTUREBLT   =   $40000000;
var
      hdcScreen:   HDC;
      hdcCompatible:   HDC;
      bmp:   TBitmap;
      hbmScreen:   HBITMAP;
begin
      hdcScreen   :=   CreateDC('DISPLAY',   nil,   nil,   nil);
      hdcCompatible   :=   CreateCompatibleDC(hdcScreen);
      hbmScreen   :=   CreateCompatibleBitmap(hdcScreen,
          GetDeviceCaps(hdcScreen,   HORZRES),
          GetDeviceCaps(hdcScreen,   VERTRES));
      SelectObject(hdcCompatible,   hbmScreen);
      bmp   :=   TBitmap.Create;
      bmp.Handle   :=   hbmScreen;
      BitBlt(hdcCompatible,
          0,   0,
          bmp.Width,   bmp.Height,
          hdcScreen,
          0,   0,
          SRCCOPY   or   CAPTUREBLT);

      bmp.SaveToFile(AFileName);
      bmp.Free;
      DeleteDC(hdcScreen);
      DeleteDC(hdcCompatible);
end;

顺便升级了http://lysoft.lz169.com/projects/DXCapture.rar
现在支持YV12,NV12,YUY2,UUVY   4个格式,并解决了点Bug

并无偿开放DX   Primary   Surface截图代码!包含DX8与DX9两个版本

...
interface

{$DEFINE   D3D9}

uses
      Windows,   Messages,   SysUtils,   Variants,   Classes,   Graphics,   Controls,   Forms,
      Dialogs,   StdCtrls,   Buttons,
{$IFDEF   D3D9}
      //   D3DX9,   //   use   D3D   to   save   surface
      Direct3D9
{$ELSE}
      //   D3DX8,   //   use   D3D   to   save   surface
      Direct3D8
{$ENDIF};
...
procedure   TForm1.BitBtn1Click(Sender:   TObject);
//   Capture   screen   through   D3D.
var
      BitsPerPixel:   Byte;
      {$IFDEF   D3D9}
      pD3D:   IDirect3D9;
      pSurface:   IDirect3DSurface9;
      g_pD3DDevice:   IDirect3DDevice9;
      {$ELSE}
      pD3D:   IDirect3D8;
      pSurface:   IDirect3DSurface8;
      g_pD3DDevice:   IDirect3DDevice8;
      {$ENDIF}
      D3DPP:   TD3DPresentParameters;
      ARect:   TRect;
      LockedRect:   TD3DLockedRect;
      BMP:   TBitmap;
      i,   p:   Integer;
begin
      BitsPerPixel   :=   GetDeviceCaps(Canvas.Handle,   BITSPIXEL);
      FillChar(d3dpp,   SizeOf(d3dpp),   0);
      D3DPP.Windowed   :=   True;
      D3DPP.Flags   :=   D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
      D3DPP.SwapEffect   :=   D3DSWAPEFFECT_DISCARD;
      D3DPP.BackBufferWidth   :=   Screen.Width;
      D3DPP.BackBufferHeight   :=   Screen.Height;
      D3DPP.BackBufferFormat   :=   D3DFMT_X8R8G8B8;
      {$IFDEF   D3D9}
      pD3D   :=   Direct3DCreate9(D3D_SDK_VERSION);
      pD3D.CreateDevice(D3DADAPTER_DEFAULT,   D3DDEVTYPE_HAL,   GetDesktopWindow,
          D3DCREATE_SOFTWARE_VERTEXPROCESSING,   @D3DPP,   g_pD3DDevice);
      g_pD3DDevice.CreateOffscreenPlainSurface(Screen.Width,   Screen.Height,   D3DFMT_A8R8G8B8,   D3DPOOL_SCRATCH,   pSurface,   nil);
      g_pD3DDevice.GetFrontBufferData(0,   pSurface);
      {$ELSE}
      pD3D   :=   Direct3DCreate8(D3D_SDK_VERSION);
      pD3D.CreateDevice(D3DADAPTER_DEFAULT,   D3DDEVTYPE_REF,   GetDesktopWindow,
          D3DCREATE_SOFTWARE_VERTEXPROCESSING,   D3DPP,   g_pD3DDevice);
      g_pD3DDevice.CreateImageSurface(Screen.Width,   Screen.Height,   D3DFMT_A8R8G8B8,   pSurface);
      g_pD3DDevice.GetFrontBuffer(pSurface);
      {$ENDIF}
      //   use   D3D   to   save   surface.   Notes:   D3DX%ab.dll   is   required!
//     D3DXSaveSurfaceToFile('Desktop.bmp',   D3DXIFF_BMP,   pSurface,   nil,     nil);
      //   use   Bitmap   to   save   surface
      ARect   :=   Screen.DesktopRect;
      pSurface.LockRect(LockedRect,   @ARect,   D3DLOCK_NO_DIRTY_UPDATE   or   D3DLOCK_NOSYSLOCK   or   D3DLOCK_READONLY);
      BMP   :=   TBitmap.Create;
      BMP.Width   :=   Screen.Width;
      BMP.Height   :=   Screen.Height;
      case   BitsPerPixel   of
          8:     BMP.PixelFormat   :=   pf8bit;
          16:   BMP.PixelFormat   :=   pf16bit;
          24:   BMP.PixelFormat   :=   pf24bit;
          32:   BMP.PixelFormat   :=   pf32bit;
      end;
      p   :=   Cardinal(LockedRect.pBits);
      for   i   :=   0   to   Screen.Height   -   1   do
          begin
              CopyMemory(BMP.ScanLine[i],   Ptr(p),   Screen.Width   *   BitsPerPixel   div   8);
              p   :=   p   +   LockedRect.Pitch;
          end;
      BMP.SaveToFile('Desktop.bmp');
      BMP.Free;
      pSurface.UnlockRect;
end;

以上DX截图代码,不需要额外的DLL支持,有DirectX   9.0即可

希望各位能支持一下LYSoft,常来LYSoft上看看

BTW:   这个问题揭帖后,请提交到FAQ吧

34 楼ly_liuyang(Liu Yang LYSoft http://lysoft.7u7.net)回复于 2006-02-15 11:30:53 得分 85
D3D截图代码也包括在http://lysoft.lz169.com/projects/DXCapture.rar

是时候揭帖啦~~

35 楼jilu_sun(Godfather)回复于 2006-02-15 14:56:53 得分 0
收藏

36 楼UC80862056(Alizee艾莉婕的粉丝)回复于 2006-02-15 17:34:18 得分 0
先结贴了。
欢迎讨论   bcfans@163.com

37 楼UC80862056(Alizee艾莉婕的粉丝)回复于 2006-02-17 18:25:40 得分 0
Alizee艾莉婕   la   isla   bonita
http://www.wair.cn/other/file/laislabonita.wmv

http://alizeefans.photo.163.com

38 楼UC80862056(Alizee艾莉婕的粉丝)回复于 2006-02-17 18:50:46 得分 0
Alizee艾莉婕   la   isla   bonita
http://www.wair.cn/other/file/laislabonita.wmv

http://alizeefans.photo.163.com

相关评论

作者:   qin5172     发布日期:   2005-1-08
说实话,我向来以为外国女人没好看的,可是这个这个。。。我看呆了。。。。。。
作者:   阿城℃     发布日期:   2005-1-08
同感啊......
强烈支持.
作者:   jinling889     发布日期:   2005-1-08
看不到   只听到
作者:   qin5172     发布日期:   2005-1-15
大家   来看啊,很美的人哦
作者:   jimmy     发布日期:   2005-1-15
唱歌可以唱得这么吸引人,这么媚态横生……

真是惊为天人啊!!!
作者:   jinling889     发布日期:   2005-1-15
不过她真的好靓~~~~~
作者:   米老鼠     发布日期:   2005-1-16
啊哈哈,真漂亮啊   !歌也不错啊
作者:   tachie     发布日期:   2005-1-17
确实很漂亮~~~~
应该说比麦当娜还要漂亮!!!!
作者:   anjisheng     发布日期:   2005-10-07
确实很漂亮~~~~   应该说比麦当娜还要漂亮!!!!
作者:   zhangliuzhen     发布日期:   2005-10-08
是啊。在个外国人好例外啊.