• DirectDraw 显示 YUV


    在网上找了一段代码,能工作,但是颜色不对,红的变成蓝色的,黄的变青色了,有时间找找问题。

    这个问题在我初学DirectX是困惑了我很久,贴出来为初学者提供一个参考。

    #include "ddraw.h"
    #pragma comment(lib,"ddraw.lib")

    #define FILE_HEIGHT            288
    #define FILE_WIDTH            352

    #define DRAW_TOP            0
    #define DRAW_LEFT            0
    #define DRAW_HEIGHT            288
    #define DRAW_WIDHT            352

    BOOL DrawYV12(HWND hWnd)
    {
        LPDIRECTDRAW            lpDD;                // DirectDraw 对象指针
        LPDIRECTDRAWSURFACE     lpDDSPrimary;        // DirectDraw 主表面指针
        LPDIRECTDRAWSURFACE     lpDDSOffScr;        // DirectDraw 离屏表面指针
        DDSURFACEDESC            ddsd;                // DirectDraw 表面描述
        RECT                    rctDest;            // 目标区域
        RECT                    rctSour;            // 源区域
        HRESULT                    ddRval;                // DirectDraw 函数返回值

        // 创建DirectCraw对象
        if (DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK) 
            return FALSE;
        // 设置协作层
        if (lpDD->SetCooperativeLevel(hWnd,
                DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES) != DD_OK)
            return FALSE;
        // 创建主表面
        ZeroMemory(&ddsd, sizeof(ddsd));
        ddsd.dwSize = sizeof(ddsd);
        ddsd.dwFlags = DDSD_CAPS;
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
        if (lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL) != DD_OK)
            return FALSE;
        // 创建离屏表面对象
        ZeroMemory(&ddsd, sizeof(ddsd));
        ddsd.dwSize = sizeof(ddsd);
        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; //DDSCAPS_OVERLAY

    DDSCAPS_OFFSCREENPLAIN;
        ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
        ddsd.dwWidth = DRAW_WIDHT;
        ddsd.dwHeight = DRAW_HEIGHT;
        ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
        ddsd.ddpfPixelFormat.dwFlags  = DDPF_FOURCC | DDPF_YUV ;
        ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','V','1','2');
        ddsd.ddpfPixelFormat.dwYUVBitCount = 8;
        if (lpDD->CreateSurface(&ddsd, &lpDDSOffScr, NULL) != DD_OK)
            return FALSE;

        // 加载yv12图像文件
        FILE * f = fopen("test.yv12","rb");
        LPBYTE lpYV12 = new BYTE[FILE_WIDTH * FILE_HEIGHT * 3 / 2];
        UINT iLen = fread(lpYV12, 1, FILE_WIDTH * FILE_HEIGHT * 3 / 2, f);
        fclose(f);
        LPBYTE lpY = lpYV12;
        LPBYTE lpV = lpYV12 + FILE_WIDTH * FILE_HEIGHT;
        LPBYTE lpU = lpYV12 + FILE_WIDTH * FILE_HEIGHT * 5 / 4;
        ddRval = lpDDSOffScr->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_WRITEONLY,NULL);
        while(ddRval == DDERR_WASSTILLDRAWING);
        if(ddRval != DD_OK)
            return FALSE;
        LPBYTE lpSurf = (LPBYTE)ddsd.lpSurface;
        LPBYTE lpY1 = lpSurf;
        LPBYTE lpV1 = lpSurf + ddsd.lPitch * FILE_HEIGHT;
        LPBYTE lpU1 = lpV1 + ddsd.lPitch  * FILE_HEIGHT / 4;
        int nOffset = DRAW_TOP*FILE_WIDTH+DRAW_LEFT;
        // 填充离屏表面
        if(lpSurf)
        {
            int i = 0;
            // fill Y data
            lpY += nOffset;
            for(i=0; i<ddsd.dwHeight; i++)
            {
                memcpy(lpSurf, lpY, ddsd.dwWidth);
                lpY += FILE_WIDTH;
                lpSurf += ddsd.lPitch;
            }
            // fill V data
            lpV += DRAW_TOP * FILE_WIDTH / 4 + DRAW_LEFT / 2;
            for(i=0; i<ddsd.dwHeight/2; i++)
            {
                memcpy(lpSurf, lpV, ddsd.dwWidth / 2);
                lpV += FILE_WIDTH / 2;
                lpSurf += ddsd.lPitch / 2;
            }
            // fill U data
            lpU += DRAW_TOP * FILE_WIDTH / 4 + DRAW_LEFT / 2;
            for(i=0; i<ddsd.dwHeight/2; i++)
            {
                memcpy(lpSurf, lpU, ddsd.dwWidth / 2);
                lpU += FILE_WIDTH / 2;
                lpSurf += ddsd.lPitch / 2;
            }
        }
        lpDDSOffScr->Unlock(NULL);
        delete lpYV12;

        // Blt到主表面上
        rctSour.left = 0;
        rctSour.top = 0;
        rctSour.right = ddsd.dwWidth;
        rctSour.bottom = ddsd.dwHeight;
        GetClientRect(hWnd,&rctDest);
        ClientToScreen(hWnd, (LPPOINT)&rctDest.left);
        ClientToScreen(hWnd, (LPPOINT)&rctDest.right);

        ddRval = lpDDSPrimary->Blt(&rctDest, lpDDSOffScr, &rctSour, DDBLT_WAIT, NULL);
        while(ddRval == DDERR_WASSTILLDRAWING);
        if(ddRval != DD_OK)
            return FALSE;
        // 释放DirectDraw对象
        if(lpDD != NULL)
        {
            if(lpDDSPrimary != NULL)
            {
                lpDDSPrimary->Release();
                lpDDSPrimary = NULL;
            }
            if(lpDDSOffScr != NULL)
            {
                lpDDSOffScr->Release();
                lpDDSOffScr = NULL;
            }
            lpDD->Release();
            lpDD = NULL;
        }
        return TRUE;
    }

  • 相关阅读:
    rsync 配置
    DNS主从服务,子域授权,view视图,日志系统,压力测试
    ubuntu VNC server 黑屏 yum源更新(ubuntu16.04)
    HTTPD服务 openssl的https服务机制
    vmware Esxi 更换管理网卡IP
    httpd 虚拟主机建立之访问机制及其日志定义
    pxe kickstart 配置+TFTP+NFS多版本系统部署
    Linux nohup不输出日志文件的方法
    Tomcat部署时war和war exploded区别
    vim编辑超大文件
  • 原文地址:https://www.cnblogs.com/lidabo/p/2800933.html
Copyright © 2020-2023  润新知