解决方案 »
- 在MAPX中如何移动 图元(即部件) 的位置
- 如何让复选项框响应EN_CHANGE事件?
- OCX在网页显示的问题,很麻烦!
- 如何注册ChartFX
- 一个小问题
- 发个求救贴,类QQ界面的问题
- 我写一个控制台程序,用_beginthread和_beginthreadex开一个线程,出现了一个奇快的问题,般赐教!!!高分!!!
- 调用com时候的CoInitialize(0)究竟做了什么?为什么我的一个指针里面的字符串没了?
- socket在64位机器上提示“套接字类型”错误:10044
- VC++6.0用TeeChart绘制曲线,怎么把栅格线去掉
- MFC Slider进度条美化的问题
- 对话框程序,读取位置时发生访问冲突
OpenCV一个函数就搞定
http://blog.csdn.net/hemmingway/article/details/8909662
// BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath)
// 功能:保存图片为8位的灰度图像
// 参数: pszPath要保存的文件名
BOOL GDIPlusImage::SaveToFileWith8pp(TCHAR *pszPath)
{
Bitmap *ima = this->m_pBitmap; // GDIPlusImage的Bitmap对象 if (!ima || !pszPath || !*pszPath)
{
return FALSE;
} int width = m_pBitmap->GetWidth();
int height = m_pBitmap->GetHeight();
int bitcount = 8; //1, 4, 8, 24, 32 //////////////////////////////////////////////////////////////////////////
//Build bitmap header
BITMAPFILEHEADER bitmapFileHeader;
BITMAPINFOHEADER bitmapInfoHeader;
BYTE rgbquad[4]; // RGBQUAD
int index = 0; DWORD stride = ((bitcount*width + 31)/32)*4; //每行都是4的倍数,或者说是DWORD大小的倍数 switch(bitcount) {
case 1:
index = 2;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*4);
break;
case 4:
index = 16;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16*4);
break;
case 8:
index = 256;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD));
break;
case 24:
case 32:
index = 0;
bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
break;
default:
break;
} //构造Bitmap文件头BITMAPFILEHEADER
bitmapFileHeader.bfType = 0x4d42; // 很重要的标志位 BM 标识
bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * stride); //bmp文件长度
bitmapFileHeader.bfReserved1 = 0;
bitmapFileHeader.bfReserved2 = 0; //构造Bitmap文件信息头BITMAPINFOHEADER
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = width;
bitmapInfoHeader.biHeight = height;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = bitcount;
bitmapInfoHeader.biCompression = BI_RGB; // 未压缩
bitmapInfoHeader.biSizeImage = height * stride;
bitmapInfoHeader.biXPelsPerMeter = 3780;
bitmapInfoHeader.biYPelsPerMeter = 3780;
bitmapInfoHeader.biClrUsed = 0;
bitmapInfoHeader.biClrImportant = 0; //创建BMP内存映像,写入位图头部
BYTE *pMyBmp = new BYTE[bitmapFileHeader.bfSize]; // 我的位图pMyBmp
BYTE *curr = pMyBmp; // curr指针指示pMyBmp的位置
memset(curr, 0, bitmapFileHeader.bfSize); //写入头信息
memcpy(curr, &bitmapFileHeader,sizeof(BITMAPFILEHEADER));
curr = pMyBmp + sizeof(BITMAPFILEHEADER);
memcpy(curr, &bitmapInfoHeader,sizeof(BITMAPINFOHEADER));
curr += sizeof(BITMAPINFOHEADER); //构造调色板
if(8 == bitcount)
{
rgbquad[3] = 0; //rgbReserved
for(int i = 0; i < 256; i++)
{
rgbquad[0] = rgbquad[1] = rgbquad[2] = i;
memcpy(curr, rgbquad, sizeof(RGBQUAD));
curr += sizeof(RGBQUAD);
}
}else if (4 == bitcount)
{
rgbquad[3] = 0;
for (int i = 0; i < 16; i++)
{
rgbquad[0] = rgbquad[1] = rgbquad[2] = i;
memcpy(curr, rgbquad, sizeof(RGBQUAD));
curr += sizeof(RGBQUAD);
}
}
else if(1 == bitcount)
{
rgbquad[3] = 0; //rgbReserved
for(int i = 0; i < 2; i++)
{
rgbquad[0] = rgbquad[1] = rgbquad[2] = (256 - i)%256;
memcpy(curr, rgbquad, sizeof(RGBQUAD));
curr += sizeof(RGBQUAD);
}
} //用GDI+加载数据源,也可以是其他的,写入文件数据
Rect rect(0,0,width,height); // Gdiplus+
BitmapData bmData;
Status iSucess = ima->LockBits(
&rect,
ImageLockModeRead,
ima->GetPixelFormat() ,
&bmData); BYTE *_pixels = (BYTE*)bmData.Scan0; //原图rect区域内存位置的起始指针,以BYTE作为单元类型
BYTE *_pColEnd, *_pRow;
int _strideoff8 = stride - width; //前面计算的索引图像的stride
BYTE _grey; // build pixles, GDI+ 有个很操蛋的毛病,自定义存放数据需要水平加垂直镜像,要从数据的末尾读取数据
switch(ima->GetPixelFormat())
{
case PixelFormat24bppRGB:
{
// 灰度化
for (int i=height; i > 0; i--)
{
_pRow = _pixels + i*bmData.Stride; // 当前的行
_pColEnd = _pRow + 3*width; // width是像素单位,而一个像素占三个字节,所以要乘以3
for (int j=width; j > 0; j--)
{
BYTE* _pixels_b; //b
BYTE* _pixels_g; //g
BYTE* _pixels_r; //r
_pixels_b = _pColEnd--; //blue
_pixels_g = _pColEnd--; //green
_pixels_r = _pColEnd--; //red _grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b); *curr = _grey; //根据红绿蓝求出此像素的灰度值
curr++;
}
curr += _strideoff8;
}
}
break; case PixelFormat32bppARGB:
{
// 灰度化
for (int i=height;i>0;i--)
{
_pRow = _pixels + i*bmData.Stride;
_pColEnd = _pRow + 4*width; // 跳到当前行的末尾去
for (int j=width;j>0;j--)
{
BYTE* _pixels_b;
BYTE* _pixels_g;
BYTE* _pixels_r; _pixels_b = _pColEnd--; //blue
_pixels_g = _pColEnd--; //green
_pixels_r = _pColEnd--; //red
_pColEnd--; _grey = GREY(*_pixels_r, *_pixels_g, *_pixels_b); *curr = _grey;
curr++;
}
curr += _strideoff8;
}
}
break;
case PixelFormat8bppIndexed: // Gdi+只能保存成24位真彩色的图像
{
// 不能直接用memcpy复制,需要水平镜像,memcpy(curr, _pixels, height * stride);
for (int i=height; i > 0; i--)
{
_pRow = _pixels + i*stride; // width是像素单位,而一个像素占三个字节,所以要乘以3
_pColEnd = _pRow + width;
for (int j=width;j > 0;j--)
{
_grey = *_pColEnd--;
*curr = _grey; //根据红绿蓝求出此像素的灰度值
curr++;
}
curr += _strideoff8;
}
}
break;
default:
break;
} // 保存图像 pMyBmp 到文件
try
{
CFile f(pszPath, CFile::modeCreate | CFile::modeWrite );
f.Write(pMyBmp, bitmapFileHeader.bfSize);
f.Close();
}
catch( CFileException* e )
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255); CString msg;
msg.Format(_T("file error: %s, m_cause:%d\n"),szCause, e->m_cause); TRACE1("%s",msg);
AfxMessageBox(msg);
e->Delete();
} //clean:
ima->UnlockBits(&bmData);
delete[] pMyBmp; return FALSE;
}