[使用][DirectDraw][显示]如何使用DirectDraw 显示图象序列

09月 17th, 2008 by admin
Posted in VC/MFC | No Comments »

我正做一个图象序列显示程序,图象序列是352*288分辨率的,是用directshow捕获的,用StretchDIBits   定时显示图象序列,但是如果要在上面添加文字什么的,闪烁感比较强,所以想采用DirectDraw来实现,我看了CSDN上老的帖子,http://topic.csdn.net/t/20020522/17/744153.html   上面xzhangjie(飞天狐狸)发了一个类
#include       "DDraw.h "          
    class       CDDraw              
    {      
    public:      
    void       CleanUp();      
    void       DrawDIB(BITMAPINFOHEADER*       pBI,char*       pData,RECT*rt);      
    BOOL       Init(HWND       hWnd,int       nWidth,int       nHeight);      
    CDDraw();      
    virtual       ~CDDraw();      
       
    private:      
    HWND       m_hDrawWnd;      
    LPDIRECTDRAW       lpDD;       //       DirectDraw       对象      
    LPDIRECTDRAWSURFACE       lpDDSPrimary;       //       DirectDraw       主页面      
    LPDIRECTDRAWSURFACE       lpBackdds;      
    LPDIRECTDRAWCLIPPER       lpClipperBack;      
    };      
       
       
    CDDraw::CDDraw()      
    {      
    lpDD=NULL;      
    lpDDSPrimary=NULL;      
    lpBackdds=NULL;      
    lpClipperBack=NULL;      
    }      
       
    CDDraw::~CDDraw()      
    {      
    if(lpDD!=NULL)CleanUp();      
    }      
       
    BOOL       CDDraw::Init(HWND       hWnd,int       nWidth,int       nHeight)      
    {      
    if(hWnd==NULL)       return       FALSE;      
       
    m_hDrawWnd=hWnd;      
       
    if(DirectDrawCreate(NULL,&lpDD,NULL)!=DD_OK)return       FALSE;      
       
    lpDD-> SetCooperativeLevel(hWnd,       DDSCL_NORMAL);      
       
    DDSURFACEDESC       ddsd;      
    ddsd.dwSize       =       sizeof(       ddsd       );       //结构的大小      
    ddsd.dwFlags       =       DDSD_CAPS;       //指定DDSURFACEDESC结构的ddsCaps成员为可用      
    ddsd.ddsCaps.dwCaps       =       DDSCAPS_PRIMARYSURFACE;       //指定要创建的是主页面      
       
    //创建主页面对象      
    if       (       lpDD-> CreateSurface(       &ddsd,       &lpDDSPrimary,       NULL       )       !=       DD_OK)       return       FALSE;      
       
    if(lpDD-> CreateClipper(NULL,&lpClipperBack,NULL)!=DD_OK)       return       FALSE;      
       
    lpClipperBack-> SetHWnd(0,hWnd);      
       
    lpDDSPrimary-> SetClipper(lpClipperBack);      
       
    lpClipperBack-> Release();      
    lpClipperBack=NULL;      
       
    ddsd.dwFlags       =       DDSD_CAPS       |       DDSD_HEIGHT       |       DDSD_WIDTH;          
    ddsd.ddsCaps.dwCaps       =       DDSCAPS_OFFSCREENPLAIN;          
    ddsd.dwHeight       =       nHeight;          
    ddsd.dwWidth       =       nWidth;          
    if(lpDD-> CreateSurface(&ddsd,       &lpBackdds,       NULL)!=DD_OK)       return       FALSE;      
       
    return       TRUE;      
    }      
       
    void       CDDraw::DrawDIB(BITMAPINFOHEADER       *pBI,       char       *pData,       RECT       *rt)      
    {      
    RECT       srt;      
    srt.left=0;      
    srt.top=0;      
    srt.right=pBI-> biWidth;      
    srt.bottom=pBI-> biHeight;      
       
    HDC       hDC;      
    lpBackdds-> GetDC(&hDC);      
       
    SetDIBitsToDevice(      
    hDC,      
    0,      
    0,      
    pBI-> biWidth,                                                   //       source       rectangle       width      
    pBI-> biHeight,                                               //       source       rectangle       height      
    0,                                                                       //       x-coord       of       source       lower-left       corner      
    0,                                       //       y-coord       of       source       lower-left       corner      
    0,                                                                                               //       first       scan       line       in       array      
    pBI-> biHeight,                                           //       number       of       scan       lines      
    pData,                       //       array       of       DIB       bits      
    (const       struct       tagBITMAPINFO*)pBI,       //       bitmap       information      
    DIB_RGB_COLORS                                           //       RGB       or       palette       indexes      
    );      
       
    lpBackdds-> ReleaseDC(hDC);      
       
    lpDDSPrimary-> Blt(rt,lpBackdds,&srt,0,NULL);      
    }      
       
    void       CDDraw::CleanUp()      
    {      
    if(lpDD!=NULL)      
    {      
    if(lpClipperBack!=NULL)      
    {      
    lpClipperBack-> Release();      
    lpClipperBack=NULL;      
    }      
       
    if(lpDDSPrimary!=NULL)      
    {      
    lpDDSPrimary-> Release();      
    lpDDSPrimary=NULL;      
    }      
       
    if(lpBackdds!=NULL)      
    {      
    lpBackdds-> Release();      
    lpBackdds=NULL;      
    }      
       
    lpDD-> Release();      
    lpDD=NULL;      
    }      
    }      
但是无法显示图象序列,序列已从32位转成24位RGB    
 
哪位大哥能告诉我原因啊?谢谢了      

我的邮箱:jiaqicx@163.com

大家帮帮忙啊   谢谢了

自己顶

Tags: , , ,

[DirectDraw][编程][基础]DirectDraw 编程的基础问题StretchDIBits 速度好慢

08月 30th, 2008 by admin
Posted in VC/MFC | No Comments »

我想在屏幕上输出   pOriY   里的图片,用   StretchDIBits   速度好慢,请问有什么办法可以加快速度?能否绕开   StretchDIBits   ?
for(i   =   0;   i   <   iWidth;   i++)
    for(j   =   0;   j   <   iHeight;   j++)
        pOriY[i   +   iWidth   *   j]   =   RGB[0,   0,   255];

BITMAPINFOHEADER bi;
BYTE   *pic   =   (BYTE*)pOriY;

bi.biSize                               =   sizeof(   BITMAPINFOHEADER   );
bi.biWidth                             =   320;
bi.biHeight                           =   240;
bi.biPlanes                           =   1;
bi.biBitCount                       =   32;
bi.biCompression                 =   BI_RGB;
bi.biSizeImage                     =   320   *   240   *   4   ;
bi.biXPelsPerMeter             =   0;
bi.biYPelsPerMeter             =   0;
bi.biClrUsed                         =   0;
bi.biClrImportant               =   0;

HDC     hdc;
lpDDSBack-> GetDC(&hdc);
SetStretchBltMode(hdc,   STRETCH_HALFTONE);

StretchDIBits(   hdc   ,                                                                         //hDC
0,                                                                         //DestX
0,//DestY
320,                                                                       //DestWidth
240,                                                                       //DestHeight
0   ,                                                                           //SrcX
0   ,                                                                         //SrcY
320   ,                                                                         //SrcWidth
240   ,                                                                         //SrcHeight
pic,                                                                   //lpBits
(LPBITMAPINFO)&bi,                                       //lpBitsInfo
DIB_RGB_COLORS   ,                                               //wUsage
SRCCOPY);

lpDDSBack-> ReleaseDC(   hdc   );
lpDDSPrimary-> BltFast(r.left   +   1,   r.top   +   1,   lpDDSBack,   NULL,   0);
lpDDSBack-> Restore();

如果原图绘制没必要用STRETCH_HALFTONE参数,StretchDIBits速度还行吧。
有缩放的话,用DrawDibDraw,速度没得说。

既然用到DirectDraw,那就加载到纹理。不要用GDI函数。

我现在直接用   CopyMemory   将   pOriY   的数据拷贝到   lpDDSBack   里,然后   Blt   到主表面。速度比以前快多了,呵呵。

Tags: , , ,

[DirectDraw][窗口][模式]请教关于DirectDraw窗口模式的一些常用方法

08月 2nd, 2008 by admin
Posted in VC/MFC | No Comments »

小弟对DirectDraw了解很浅,现在要弄一个窗口模式的DirectDraw应用程序,本来一切都OK了,却突然发现一个巨大的BUG,那就是改变屏幕分辨率后一切黑屏。
我使用的方法是将所有图元存放在各个离屏表面中,然后在各个表面之间做Blt,最终显示出画面。
经过调试发现,当屏幕分辨率发生改变时,所有的表面都失效了,->Restore根本不起作用。
请教各位前辈,做DirectDraw窗口程序,一般采用什么来存放图元,是自定义的结构体还是DirectDraw表面,如果是前者又如何利用DirectDraw的高效性,如果是后者又如何避免表面的丢失呢?
另外附带一个问题,在两个离屏表面之间作Blt可以利用硬件特性么?

我的DIRECTDRAWSURFACE在按下“Ctrl+Alt+Del”调出系统登录界面后也会丢失,并且用Restore也不能恢复。
后来多Lock几次,成功了,表面就可用了。

从1400×1050改变为1024×768时(未改变色深),所有表面都失效了(包括离屏表面),症状是Blt失败,Lock也失败。

我再把症状描述的详细一点吧:
1、从1400×1050改变为1024×768时,Restore后,Blt还是失败,错误号887601C2(DDERR_INVALIDRECT)???
2、从1400×1050改变为1024×768时,再改变回1400×1050,Blt成功,返回DD_OK,但是画面花屏。

2先不管,1肯定是要解决的,如果改变分辨后,DirectDraw就会失效,那岂不是只能把数据存在自定义结构体里面,需要的时候再创建一下表面了?
所以才来请教一下各位前辈一般是怎么处理这类应用的?

我也碰到了同样的问题,改变分辨率,离屏页面lock失败,返回0×887601c2,盼高手指点!

关注

关注

引用 5 楼 thinkelse 的回复:
我也碰到了同样的问题,改变分辨率,离屏页面lock失败,返回0×887601c2,盼高手指点!

分配到系统内存可以防止表面丢失,不过这样就无法利用硬件的性能了。
想不通了!?DirectDraw要是只能这样,那岂不是很废?

就是这么设计的,现在连restore都成了专门的学问.
一般来说这种情况都是把这些重新载入一次,可以看到很多游戏都是这样,在这种时候请观测指示灯,硬盘在读

引用 9 楼 Amuro1987218 的回复:
就是这么设计的,现在连restore都成了专门的学问.
一般来说这种情况都是把这些重新载入一次,可以看到很多游戏都是这样,在这种时候请观测指示灯,硬盘在读

那岂不是不能将中间产物常驻保存了???因为这东西没法简单复原啊!
我试过写一个Backup类备份图元数据,虽然可以工作,但是备份时要从显存读数据,而这速度实在不是人类可以忍受的。

另外由于某些图片有alpha通道,我将所有离屏表面都设为32位,后来发现某些老式的显卡结合98系统,无法直接将32位表面Blt到16位的Primary表面。
如果通过GetDC结合GDI的方式写入倒是可以,不过却要涉及2次图形拷贝:
1、由于表面和DIB的图形存放顺序不同,所以需要生成一个HBITMAP作中间变量,这里是一次拷贝。
2、如果直接将1中的HBITMAP画到HDC上,会发现CLIPPER失效,比如让记事本在DirectDraw窗口上面移动,记事本无法覆盖住它的绘图;
  所以需要再创建一个与Primary表面相同色深的中间表面过渡,最后还是利用Blt绘制,这里是二次拷贝。
这样的代价是不是大了一点?

Tags: , , ,