第1个回答 2010-01-23
// 调试通过,1~32位色都可以。
// OutImageData.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
// 从位图文件装入,将位图数据写入文本文件
// 支持调色板位图,和RGB图像数据位图。
// 注:crt 的_tscanf有bug,无法输入正确的中文字符,故工程采用多字节字符集。
void WriteIndexColorBmpData( HBITMAP hbmp, HANDLE hTextFile);
void WriteColorValueBmpData( HBITMAP hbmp, HANDLE hTextFile);
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR the2Para[256];
int nPathlen= 0;
if ( argc> 1)
{
_tcscpy( the2Para, argv[1]);
nPathlen= (int) _tcslen( the2Para);
}
if ( 0== nPathlen)
{
// 在命令行输入bmp路径
_tprintf(_T("<请输入位图文件路径>:>") );
nPathlen= _tscanf( _T("%250s"), the2Para);
}
// 再次判断字符串长度
nPathlen= (int) _tcslen( the2Para);
if ( nPathlen<= 0 )
return 0;
// 开始装入图像文件。
HBITMAP hBmp= ( HBITMAP) LoadImage( NULL, the2Para, IMAGE_BITMAP, 0, 0
, LR_CREATEDIBSECTION| LR_LOADFROMFILE);
if ( NULL== hBmp)
{
MessageBox( NULL, _T("装入文件错误!"), _T("提升"), MB_OK);
return 0;
}
BITMAP bmpinfo;
if ( GetObject( hBmp, sizeof(bmpinfo), &bmpinfo)<= 0 || NULL== bmpinfo.bmBits)
{
DeleteObject( hBmp);
MessageBox( NULL, _T("读取位图文件数据错误!"), _T("提升"), MB_OK);
return 0;
}
// 新txt文件名称(直接追加.txt。还可以使用strchr 搜索.bmp。这儿为了省事)
the2Para[nPathlen++]= '.';
the2Para[nPathlen++]= 't';
the2Para[nPathlen++]= 'x';
the2Para[nPathlen++]= 't';
the2Para[nPathlen]= 0;
HANDLE hTextFile= CreateFile( the2Para, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL, NULL);
if ( NULL== hTextFile)
{
DeleteObject( hBmp);
MessageBox( NULL, _T("新建文本文件出错!"), _T("提示"), MB_OK);
return 0;
}
// 开始向文件写入数据
if ( bmpinfo.bmBitsPixel> 8)
WriteColorValueBmpData( hBmp, hTextFile);
else
WriteIndexColorBmpData( hBmp, hTextFile);
// 关闭对象句柄,返回。
CloseHandle( hTextFile);
DeleteObject( hBmp);
return 0;
}
// 写入带调色板的位图数据。<= 8 BPP
// 一般灰度图像就使用的调色板位图。可以直接写索引ID,也可以写索引的灰度RGB颜色
// 直接使用 GetPixel ,GetNearestPaletteIndex 。虽然速度有点慢,但是代码简单点。
// 也可以直接读取DIB的缓冲区来获取每个像素的索引,在查调色板获取颜色。也一样
void WriteIndexColorBmpData( HBITMAP hbmp, HANDLE hTextFile)
{
BITMAP bmpinfo;
GetObject( hbmp, sizeof(bmpinfo), &bmpinfo);
//
TCHAR writeBuffer[16];
int nwriteLen= 0;
DWORD dwHaveWrite;
TCHAR*newrowStr= _T("\r\n");
// 创建临时dc
HDC hcomdc= GetDC( NULL);
SelectObject( hcomdc, hbmp);
HPALETTE hPal= ( HPALETTE) GetCurrentObject( hcomdc, OBJ_PAL);
for ( int i = 0 ; i < bmpinfo.bmHeight; i ++ )
{
for ( int j = 0 ; j < bmpinfo.bmWidth; j ++ )
{
COLORREF clrValue= GetPixel( hcomdc, j, i);
UINT nColorIndex= GetNearestPaletteIndex( hPal, clrValue);
// 转换为字符串。如果要写灰度数据的索引(1~255),可以转换nColorIndex。
// 不过 GetNearestPaletteIndex 获得的数据不太准确。
// 可以使用类似 WriteColorValueBmpData 函数的方法,直接从图像缓冲区读取
// 每个像素的颜色索引值就可以了。
nwriteLen= _stprintf( writeBuffer, _T("%d "), clrValue);
WriteFile( hTextFile, writeBuffer, nwriteLen, &dwHaveWrite, NULL);
}
// 写换行符号
WriteFile( hTextFile, newrowStr, 2, &dwHaveWrite, NULL);
}
ReleaseDC( NULL, hcomdc);
}
// 写入不带调色板的位图数据。> 8 BPP
// 写入格式为ABGR 的顺序(A最高位)。可以根据需要转换格式。
void WriteColorValueBmpData( HBITMAP hbmp, HANDLE hTextFile)
{
BITMAP bmpinfo;
GetObject( hbmp, sizeof(bmpinfo), &bmpinfo);
int nPixelStep= bmpinfo.bmBitsPixel/ 8;
if ( nPixelStep< 0)
return;
TCHAR writeBuffer[16];
int nwriteLen= 0;
DWORD dwHaveWrite;
TCHAR*newrowStr= _T("\r\n");
BYTE* BmpBufferStart= (BYTE*)bmpinfo.bmBits+ ( bmpinfo.bmHeight-1) * bmpinfo.bmWidthBytes;
for ( int i = 0; i < bmpinfo.bmHeight; i ++ )
{
BYTE* RowBuffer= BmpBufferStart;
for ( int j = 0 ; j < bmpinfo.bmWidth; j ++ )
{
DWORD dwValue= *((DWORD*)RowBuffer);
if ( 2== nPixelStep) // 16 位一般565格式
{
dwValue= dwValue&0x0FFFF;
}
else if ( 3== nPixelStep) // 24 位
{
dwValue= dwValue&0x0FFFFFF;
}
// 转换为字符串
nwriteLen= _stprintf( writeBuffer, _T("%d "), dwValue);
WriteFile( hTextFile, writeBuffer, nwriteLen, &dwHaveWrite, NULL);
// 像素步进
RowBuffer+= nPixelStep;
}
// 行步进
BmpBufferStart-= bmpinfo.bmWidthBytes;
// 写换行符号
WriteFile( hTextFile, newrowStr, 2, &dwHaveWrite, NULL);
}
}
第2个回答 2010-01-23
代码:
int Read24Bmp(unsigned char ** pImage, int * iXSize, int * iYSize,int *iLineWidth, char *filename)
{
FILE *fp;
if ( !(fp = fopen(filename, "rb")) )
{
return -1;
}
//读取宽度和高度,颜色数
unsigned char FileHeader[54];
fread(FileHeader, sizeof(unsigned char), 54, fp);
if (FileHeader[0] != 0x42 && FileHeader[1] != 0x4d)
{
printf("not bmp file!\n");
fclose(fp);
return 0;
}
unsigned long lValue = 0;
*iXSize = *iYSize = 0;
//文件大小
unsigned long lFileSize = 0;
lFileSize = FileHeader[2];
(lValue = FileHeader[3]);lValue=lValue<<8;
lFileSize |= (lValue & 0x0000ff00);
(lValue = FileHeader[4]);lValue=lValue<<16;
lFileSize |= (lValue & 0x00ff0000);
(lValue = FileHeader[5]);lValue=lValue<<24;
lFileSize |= (lValue & 0xff000000);
//文件宽度
*iXSize = FileHeader[18];
(lValue = FileHeader[19]);lValue=lValue<<8;
*iXSize |= (lValue & 0x0000ff00);
(lValue = FileHeader[20]);lValue=lValue<<16;
*iXSize |= (lValue & 0x00ff0000);
(lValue = FileHeader[21]);lValue=lValue<<24;
*iXSize |= (lValue & 0xff000000);
//文件高度
*iYSize = FileHeader[22];
(lValue = FileHeader[23]);lValue=lValue<<8;
*iYSize |= (lValue & 0x0000ff00);
(lValue = FileHeader[24]);lValue=lValue<<16;
*iYSize |= (lValue & 0x00ff0000);
(lValue = FileHeader[25]);lValue=lValue<<24;
*iYSize |= (lValue & 0xff000000);
//是否是24位位图
int iBitCounts = 0;
iBitCounts = FileHeader[28];
(lValue = FileHeader[29]);lValue=lValue<<8;
iBitCounts |= (lValue & 0x0000ff00);
if (iBitCounts != 24)
{
printf("only for 24-bit bitmap!\n");
getchar();
return 0;
}
*iLineWidth = lFileSize / (*iYSize);
*pImage = (unsigned char *)malloc(lFileSize);
fread(*pImage, sizeof(unsigned char), lFileSize, fp);
fclose(fp);
return 0;
}
int WriteClr2Txt(unsigned char * pImage, int iXSize, int iYSize, int iLineWidth, char * filename)
{
FILE *fp;
if (!(fp = fopen(filename, "wb")))
return -1;
int i,j,k;
for (i= 0; i < iYSize; i++)
{
for (j = 0; j < iXSize; j++)
{
fprintf(fp, "%d ", pImage[(iYSize-1-i)*iLineWidth + j*3+2]);//r
fprintf(fp, "%d ", pImage[(iYSize-1-i)*iLineWidth + j*3+1]);//g
fprintf(fp, "%d", pImage[(iYSize-1-i)*iLineWidth + j*3+0]); //b
fprintf(fp, "\r\n");
}
}
fclose(fp);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (argc != 2)
{
printf("only need one parameter!\n");
getchar();
return 0;
}
char * FileName = "C:\\123.bmp";
char * FileName1 = "C:\\123.txt";
unsigned char ** pImage = (unsigned char **)malloc(sizeof(unsigned char *));
int iX = 0;
int iY = 0;
int iLineWidth = 0;
Read24Bmp(pImage, &iX, &iY, &iLineWidth, W2A(argv[1]));
WriteClr2Txt(*pImage, iX,iY, iLineWidth, FileName1);
free(pImage);
return 0;
}