如何修复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
相关产品推荐
相关产品推荐

