8位索引格式Gdiplus::Bitmap转cv::Mat图像褪色问题求助
问题分析
你遇到的褪色问题核心原因是:8位索引位图(PixelFormat8bppIndexed)的像素值并非直接的灰度值,而是调色板的索引。你的代码直接将这些索引值当作灰度值存入cv::Mat,相当于使用了错误的颜色映射,导致图像颜色失真、褪色。
解决方案
要正确转换8位索引位图到cv::Mat,必须先获取位图的调色板,再将每个像素的索引值映射为调色板中对应的灰度值。以下是修正后的代码:
// Converting 8bpp indexed bitmap to cv::Mat correctly Gdiplus::PixelFormat format = m_Bitmap->GetPixelFormat(); if (format == PixelFormat8bppIndexed) { Gdiplus::BitmapData bitmapData; Gdiplus::Rect rect(0, 0, width, height); m_Bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead, format, &bitmapData); // 获取位图的调色板 Gdiplus::ColorPalette* palette = m_Bitmap->GetPalette(); if (!palette) { m_Bitmap->UnlockBits(&bitmapData); // 处理调色板获取失败的情况 return; } // 创建灰度查找表:将索引映射为对应的灰度值(取RGB的平均值或直接取R通道,因为是灰度图) uchar lut[256]; for (int i = 0; i < 256; ++i) { // 灰度图的调色板RGB分量相同,直接取R通道即可 lut[i] = palette->Entries[i].R; } // 先创建包含索引值的Mat cv::Mat indexMat(height, width, CV_8UC1, static_cast<unsigned char*>(bitmapData.Scan0), bitmapData.Stride); // 使用查找表转换为实际灰度图 cv::Mat nmat; cv::LUT(indexMat, cv::Mat(1, 256, CV_8UC1, lut), nmat); m_Bitmap->UnlockBits(&bitmapData); // 后续使用nmat即可 }
补充说明
- 你之前处理32bppARGB位图时正常,是因为该格式的每个像素直接存储了ARGB四个通道的实际颜色值,无需依赖调色板,直接转换为灰度图即可得到正确结果。
- 若你的8位索引位图确实是灰度图,调色板的RGB分量应该是相同的(比如索引255对应RGB(255,255,255),索引0对应RGB(0,0,0)),此时取R/G/B任意通道的数值作为灰度值都可以。如果是彩色索引图,需要根据需求转换为灰度(比如取RGB的加权平均值)。
内容的提问来源于stack exchange,提问作者Jishnu JK
相关产品推荐
相关产品推荐

