You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复MFC中使用VFW时图像左右反转的问题

解决MFC+VFW视频图像左右反转问题

针对你遇到的VFW采集图像左右反转问题,提供两种直接可行的修复方案,结合你的现有代码给出具体修改点:

方法一:在像素处理阶段反转每行像素

你已经在遍历像素做灰度/彩色转换,直接修改x坐标的索引逻辑即可实现左右翻转,无需额外GDI操作,逻辑更直观:

修改像素遍历循环部分:

for (int y = 0; y < image_height; y++)
{
    for (int x = 0; x < image_width; x++)
    {
        // 原图像的像素索引(从左到右)
        int src_index = ((y * image_width) + x) * 4;
        // 反转后的目标索引(从右到左)
        int dest_index = ((y * image_width) + (image_width - 1 - x)) * 4;
        
        if (iFlagGray == 1) // 灰度模式
        {
            int grayblue = arrImage1[src_index] * 0.11;
            int graygreen = arrImage1[src_index + 1] * 0.59;
            int grayred = arrImage1[src_index + 2] * 0.30;
            int grayall = grayblue + graygreen + grayred;
            arrImage2[dest_index] = grayall;
            arrImage2[dest_index + 1] = grayall;
            arrImage2[dest_index + 2] = grayall;
            arrImage2[dest_index + 3] = 0;
        }
        else // 彩色模式
        {
            arrImage2[dest_index] = arrImage1[src_index];
            arrImage2[dest_index + 1] = arrImage1[src_index + 1];
            arrImage2[dest_index + 2] = arrImage1[src_index + 2];
            arrImage2[dest_index + 3] = 0;
        }
    }
}

方法二:用BitBlt实现水平翻转

你之前尝试的BitBlt参数有误,正确的水平翻转写法需要将目标矩形宽度设为负数,同时目标起始x坐标设为图像宽度,GDI会自动从右向左绘制图像:

替换代码中原有的capture_dc.BitBlt(0, 0, image_width, image_height, &dc, 0, 0, SRCCOPY);为:

// 替换原正常复制代码,实现水平翻转
capture_dc.BitBlt(image_width, 0, -image_width, image_height, &dc, 0, 0, SRCCOPY);

方案说明

  • 方法一适合需要对像素数据做额外处理的场景,直接在数据层面修正,后续操作无需调整;
  • 方法二更简洁,适合仅需要翻转显示、不需要修改像素数据的场景。

原问题代码(供参考)

{
    // TODO: 
    if (nIDEvent == 1)
    {
        capGrabFrame(hWindow);
    }

    RECT rect;
    m_picture2.GetClientRect(&rect); 
    int window_width = rect.right;
    int window_height = rect.bottom;
    int image_width = window_width;
    int image_height = window_height;

    int b = 4;

    arrImage1 = new unsigned char[b * image_width * image_height];
    arrImage2 = new unsigned char[b * image_width * image_height];
    BITMAPINFO bmpinfo;
    bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpinfo.bmiHeader.biWidth = image_width;
    bmpinfo.bmiHeader.biHeight = -image_height;

    bmpinfo.bmiHeader.biPlanes = 1;
    bmpinfo.bmiHeader.biBitCount = 32;
    bmpinfo.bmiHeader.biCompression = BI_RGB;
    bmpinfo.bmiHeader.biSizeImage = 0;
    bmpinfo.bmiHeader.biXPelsPerMeter = 0;
    bmpinfo.bmiHeader.biYPelsPerMeter = 0;
    bmpinfo.bmiHeader.biClrUsed = 0;
    bmpinfo.bmiHeader.biClrImportant = 0;

    
    CDC dc;
    HDC hdc = ::GetDC(m_picture1.m_hWnd);
    dc.Attach(hdc);
    CDC    capture_dc;

    if (iBitmapFlag == 0)
    {
        capture_map.CreateCompatibleBitmap(&dc, image_width, image_height);
        iBitmapFlag = 1;
    }

    capture_dc.CreateCompatibleDC(&dc);
    capture_dc.SelectObject(&capture_map);
    // 原BitBlt代码,替换为方法二的翻转代码即可
    capture_dc.BitBlt(0, 0, image_width, image_height, &dc, 0, 0, SRCCOPY);

    //capture_dc.BitBlt(image_width, 0, image_width, image_height, &dc, 0, 0, SRCCOPY); 
    //capture_dc.BitBlt(0, 0, -image_width, image_height, &dc, 0, 0, SRCCOPY); 
    //capture_dc.BitBlt(image_width, 0, image_width, image_height, &dc, 0, 0, SRCCOPY); 
    //capture_dc.BitBlt(image_width, 0, -image_width, image_height, &dc, 0, 0, SRCCOPY);
    ///it didn't work using this gray scale


    LPBYTE lpBits = arrImage1;
    int err;
    int ret = GetDIBits(capture_dc, capture_map, 0, image_height, lpBits, &bmpinfo, DIB_RGB_COLORS);
    
    if (ret == 0)  err = GetLastError();
    capture_dc.DeleteDC();
    ReleaseDC(&dc);

    int iFlagGray = 1;

    for (int y = 0; y < image_height; y++)
    {
        for (int x = 0; x < image_width; x++)
        {
            int index1 = ((y * image_width) + x);
            index1 *= 4;
            if (iFlagGray == 1) //grayscale
            {
                
                int grayblue = arrImage1[index1] * 0.11;       // 11%
                int graygreen = arrImage1[index1 + 1] * 0.59;  // 59%
                int grayred = arrImage1[index1 + 2] * 0.30;    // 30%
                int grayall = grayblue + graygreen + grayred;
                arrImage2[index1] = grayall;    // blue
                arrImage2[index1 + 1] = grayall;    // green
                arrImage2[index1 + 2] = grayall;    // red
                arrImage2[index1 + 3] = 0;         // this byte is not used
            }
            else //color
            {
                arrImage2[index1] = arrImage1[index1];    //blue
                arrImage2[index1 + 1] = arrImage1[index1 + 1]; //green
                arrImage2[index1 + 2] = arrImage1[index1 + 2]; //red
                arrImage2[index1 + 3] = 0;
            }
        }
    }

    int bpp = 32;
    CImage cimage_mfc;
    cimage_mfc.Create(window_width, window_height, 32);
    BITMAPINFO* bitInfo = (BITMAPINFO*)malloc(sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD));
    bitInfo->bmiHeader.biBitCount = bpp;
    bitInfo->bmiHeader.biWidth = window_width;
    bitInfo->bmiHeader.biHeight = -window_height;
    bitInfo->bmiHeader.biPlanes = 1;
    bitInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitInfo->bmiHeader.biCompression = BI_RGB;
    bitInfo->bmiHeader.biClrImportant = 0;
    bitInfo->bmiHeader.biClrUsed = 0;
    bitInfo->bmiHeader.biSizeImage = 0;
    bitInfo->bmiHeader.biXPelsPerMeter = 0;
    bitInfo->bmiHeader.biYPelsPerMeter = 0;

    /*
    if (bpp == 8) 
    {
        RGBQUAD* palette = bitInfo->bmiColors; 
        for (int i = 0; i < 256; i++)
        {
            palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i; 
            palette[i].rgbReserved = 0;
        }
    }
    */


    if (image_width == window_width && image_height == window_height)
    {
        SetDIBitsToDevice(cimage_mfc.GetDC(), 0, 0, window_width, window_height, 0, 0, 0, image_height, arrImage2, bitInfo, DIB_RGB_COLORS);
    }
    else
    {
        int destx = 0, desty = 0;
        int destw = window_width;
        int desth = window_height;
        int imgx = 0, imgy = 0;
        int imgWidth = image_width;
        int imgHeight = image_height;
        StretchDIBits(cimage_mfc.GetDC(), destx, desty, destw, desth, imgx, imgy, imgWidth, imgHeight, arrImage2, bitInfo, DIB_RGB_COLORS, SRCCOPY);
    }

    HDC dc2 = ::GetDC(m_picture2.m_hWnd);
    cimage_mfc.BitBlt(dc2, 0, 0);
    ::ReleaseDC(m_picture2.m_hWnd, dc2);
    cimage_mfc.ReleaseDC();
    cimage_mfc.Destroy();
    delete arrImage1;
    delete arrImage2;

    CDialogEx::OnTimer(nIDEvent);
}

内容的提问来源于stack exchange,提问作者seounggue kang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:55:10