把一个真彩图test.bmp转化为一个256阶灰度图1.bmp 执行过程没有报错 可1.bmp 打开不是一个正确的图片 大家帮我看看 谢谢

hacking 2003-01-16 10:25:14
把一个真彩图test.bmp转化为一个256阶灰度图1.bmp 执行过程没有报错 可1.bmp 打开不是一个正确的图片 大家帮我看看 谢谢
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"

typedef struct tagLongPointer
{
LPVOID lpImgData;
LONG biWidth;
LONG biHeight;
}LongPointer;

#define WIDTHBYTES(i) ((i+31)/32*4)

bool LoadGrayBmpFile (char *BmpFileName);

HGLOBAL hImgData=NULL;
LongPointer lpimg;
LPVOID lpgimg1;
LPVOID lpgimg2;

int main(int argc, char* argv[])
{
if (LoadGrayBmpFile("C:\\test.bmp") )
{
printf("OK!\n");
}

GlobalUnlock(hImgData);

return 0;
}

bool LoadGrayBmpFile (char *BmpFileName)
{
HANDLE hf,hpal,ghf,ghf1;
LPSTR lpg1,lpg2;
LPVOID lpPal,lpImgData;
LPSTR pal;
DWORD LineBytes,gLineBytes;
DWORD ImgSize,Gsize;
DWORD NumColors;
DWORD i;
unsigned char r,g,b;
float gy;
BITMAPFILEHEADER bf,gbf;
BITMAPINFOHEADER bi,gbi;


lpimg.lpImgData = NULL ;
lpimg.biWidth = 0 ;
lpimg.biHeight = 0 ;

hf=CreateFile(BmpFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL);

ReadFile(hf,&bf,sizeof(BITMAPFILEHEADER),&i,NULL);
ReadFile(hf,&bi,sizeof(BITMAPINFOHEADER),&i,NULL);

gbf=bf;
gbi=bi;

LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);
gLineBytes=(DWORD)WIDTHBYTES(bi.biWidth*8);
ImgSize=(DWORD)LineBytes*bi.biHeight;
Gsize=(DWORD)gLineBytes*bi.biHeight;

gbf.bfOffBits=(DWORD)(256*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
+sizeof(BITMAPINFOHEADER));
gbf.bfSize=(DWORD)(256*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
+sizeof(BITMAPINFOHEADER)+Gsize);
gbi.biBitCount=8;
gbi.biClrUsed=0;
gbi.biSizeImage=Gsize;

if(bi.biClrUsed!=0)

NumColors=(DWORD)bi.biClrUsed;

else

switch(bi.biBitCount){

case 1:

NumColors=2;

break;

case 4:

NumColors=16;

break;

case 8:

NumColors=256;

break;

case 24:

NumColors=0;

break;

default:

MessageBox(0,"Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION);

CloseHandle(hf);

return FALSE;

}

if(bi.biClrUsed!=0)
{

MessageBox(0,"The file is not a true color!","Error Message" ,MB_OK|MB_ICONEXCLAMATION);
CloseHandle(hf);
return FALSE;

}


if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)
+sizeof(BITMAPINFOHEADER)))

{

MessageBox(0,"Invalid color numbers!","Error Message" ,MB_OK|MB_ICONEXCLAMATION);
CloseHandle(hf);
return FALSE;

}

bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;

hImgData=GlobalAlloc(GPTR,(DWORD)(ImgSize+1000));
lpImgData=GlobalLock(hImgData);
hpal=GlobalAlloc(GPTR,(DWORD)(256*4));
lpPal=GlobalLock(hpal);
pal=(char *)lpPal;

for(int z=0;z<256;z++)
{
*(pal++)=(unsigned char)z;
*(pal++)=(unsigned char)z;
*(pal++)=(unsigned char)z;
*(pal++)=0;
}


ghf1=GlobalAlloc(GPTR,(DWORD)(Gsize+1000));
lpgimg1=GlobalLock(ghf1);

lpimg.lpImgData = lpImgData ;
lpimg.biHeight = bi.biHeight ;
lpimg.biWidth = bi.biWidth ;

SetFilePointer(hf,bf.bfOffBits,NULL,FILE_BEGIN);
ReadFile(hf,lpImgData,ImgSize,&i,NULL);

for(int y=0;y<lpimg.biHeight;y++)
{
lpg1=(char *)lpImgData+ImgSize-y*LineBytes;
lpg2=(char *)lpgimg1+Gsize-y*gLineBytes;

for(int x=0;x<lpimg.biWidth;x++)
{
b=(unsigned char)(*lpg1++);
g=(unsigned char)(*lpg1++);
r=(unsigned char)(*lpg1++);
gy=(float)(b*0.299+g*0.587+b*0.114);
*(lpg2++)=(unsigned char)gy;
}
}

lpgimg2=lpgimg1;

ghf=CreateFile("C:\\1.bmp",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,
CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL);
WriteFile(ghf,(char *)&gbi,sizeof(BITMAPFILEHEADER),&i,NULL);
WriteFile(ghf,(char *)&gbf,sizeof(BITMAPINFOHEADER),&i,NULL);
WriteFile(ghf,(char *)lpPal,256*4,&i,NULL);
WriteFile(ghf,(char *)lpgimg1,Gsize,&i,NULL);

CloseHandle(hf);
CloseHandle(ghf);
return TRUE;
}
...全文
73 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuga 2003-01-17
  • 打赏
  • 举报
回复
/*
//功能如下:
1. 8位位图仍然保存为8位位图
2. 16位位图将被保存为24位位图.16位位图只用于16位增强显示模式, 不在不同的系统间进行传递.
3. 24位位图仍然被保存为24位位图.
4. 32位Ddb位图将被保存为24位位图.
5. 对于16色即4位位图, 不作处理.
*/
//将Ddb位图保存成Dib位图:被保存的区域由, x, y, nWidth, nHeight来定义

int CDisplayModeView::SaveBmp(char *lpFilePath,int nWidth,int nHeight,int nType)
{
CDisplayModeDoc* pDoc = GetDocument();
CDisplayModeApp *app=(CDisplayModeApp *)AfxGetApp();
ASSERT_VALID(pDoc);


if(m_nCountMathod<0)
return 0;
int i,j,nScanLine;


m_pBMI=new BITMAPINFO;

FILE *file = NULL;

file = fopen(lpFilePath, "wb");



if(file==NULL)
{
fclose(file);
delete []m_pBMI;

return -1;
}
if(m_bTmpSrcImg==NULL)
{
fclose(file);
delete []m_pBMI;
return -1;
}
switch(nType)
{
case 1://color
{
nScanLine=nWidth*4;
if(nScanLine & 3)
nScanLine=(nScanLine &~3) +4 ;

DWORD dwSaveWidthBytes ;//= CalcDibWidthBytes(w, m_nBitCount);

//每行字节数必须被4整除
if(pDoc->m_DIB.GetBitCount() ==8)
// dwSaveWidthBytes=((nWidth * 8 + 31) / 32) * 4;
dwSaveWidthBytes=((nWidth * 24 + 31) / 32) * 4;
else
dwSaveWidthBytes=((nWidth * 24 + 31) / 32) * 4;
//DIB位图数据大小, 以字节为单位
DWORD dwDibBitsSize = dwSaveWidthBytes * nHeight;
//计算整个Dib文件的大小dwFileSize
DWORD dwFileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwDibBitsSize;
if(pDoc->m_DIB.GetBitCount() == 8) dwFileSize += (256 * sizeof(RGBQUAD));

//计算位图信息到位图数据间的偏移量(字节)
DWORD dwOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//if(m_nBitCount == 8)
// if(pDoc->m_DIB.GetBitCount() ==8)
// dwOffBits += (256 * sizeof(RGBQUAD));


m_pBMI->bmiHeader.biBitCount=24;//位图的每个象素的为数,1位对应的颜色总数为2,4--16,8--256,24--16777216
m_pBMI->bmiHeader.biClrImportant=0;//指定对于显示该位图比较重要的颜色索引个数,若值为0,则所有的颜色都是重要的。
m_pBMI->bmiHeader.biClrImportant=0;//位图实际使用的颜色数
m_pBMI->bmiHeader.biCompression=0;//压宿方式
m_pBMI->bmiHeader.biClrUsed =0;
m_pBMI->bmiHeader.biHeight=nHeight;
m_pBMI->bmiHeader.biWidth=nWidth;
m_pBMI->bmiHeader.biPlanes=1;//表示目标设备的位平面数
m_pBMI->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
m_pBMI->bmiHeader.biXPelsPerMeter=0;//表示目标设备的水平分辨率
m_pBMI->bmiHeader.biYPelsPerMeter=0;//表示目标设备的垂直分辨率
m_pBMI->bmiHeader.biSizeImage =0;//nWidth*nHeight*4;

BITMAPFILEHEADER bmh;//位图文件头结构
LPBITMAPINFOHEADER lpBl;//指向位图信息结构的指针
RGBQUAD rgb[256];
DWORD dwDibSize;
lpBl=(LPBITMAPINFOHEADER)m_pBMI;

if(lpBl==NULL)
{
delete[] m_pBMI;
fclose(file);
return -2;

}
dwDibSize=*(LPDWORD)lpBl+256*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER);

DWORD dwBmBitsSize;//BMP文件信息结构所占的字节数
dwBmBitsSize=nScanLine*nHeight;// lpBl->biWidth*lpBl->biHeight*4;//存储时位图所有象素所占的字节数

dwDibSize+=dwBmBitsSize;
lpBl->biSizeImage=dwBmBitsSize;//位图所有象素所占的字节总数

//填充BITMAPFILEHEADER结构
bmh.bfType=0x4d42;
bmh.bfSize=dwFileSize;//+sizeof(BITMAPFILEHEADER);//文件总长度

bmh.bfReserved1=0;
bmh.bfReserved2=0;
bmh.bfOffBits=dwOffBits;//(DWORD)sizeof(BITMAPFILEHEADER)+lpBl->biSize +256*sizeof(RGBQUAD);//

//填充BITMAPINFOHEADER结构:8位仍然保存为8位, 其它均被保存为24位.最低显示模式为8位.



long dbWidth;
dbWidth=((nWidth * 32 + 15) / 16) * 2;
//palette
for(i=0;i<256;i++)
{
rgb[i].rgbBlue=i;
rgb[i].rgbGreen=i;
rgb[i].rgbRed=i;
rgb[i].rgbReserved =0;
}
//对于16位和32位位图, 由于数据需要重组, 所以需要重新分配内存

//指向Dib实际像素数据的指针,
BYTE* pbyDibBits = new BYTE[dwDibBitsSize];
if (pbyDibBits == NULL) return -1;
//数据索引基数
DWORD dwBaseIndex =0;// y * m_nDdbWidthBytes + ((m_nBitCount == 16) ? (x + x) : (4 * x));
DWORD dwIndexDib = (nHeight - 1) * dwSaveWidthBytes;

for(i=0;i<nHeight;i++)
{
//指向Ddb内存数据的指针(行)
BYTE* pbyDdbData = m_bTmpSrcImg + dwBaseIndex;

//指向Dib内存数据的指针(行)
BYTE* pbyDibData = pbyDibBits + dwIndexDib;

for(j=0;j<nWidth;j++)
{
*pbyDibData++ = *pbyDdbData++; //蓝色
*pbyDibData++ = *pbyDdbData++; //绿色
*pbyDibData++ = *pbyDdbData++; //红色
pbyDdbData++;
}
dwBaseIndex += dbWidth;
dwIndexDib -= dwSaveWidthBytes;
}
fwrite((LPSTR)&bmh, sizeof(BITMAPFILEHEADER), 1, file);//文件头
fwrite(lpBl,sizeof(BITMAPINFOHEADER), 1, file);//信息头
//fwrite(rgb,sizeof(RGBQUAD)*256,1,file);//RGB
fwrite(pbyDibBits,(long)dwDibBitsSize, 1, file);//数据
fclose(file);
delete[] pbyDibBits;
delete[] m_pBMI;
break;
}
case 2://gray
{
int j,nScanLine;
nScanLine=nWidth*4;
if(nScanLine & 3)
nScanLine=(nScanLine &~3) +4 ;
//被保存位图每行的字节数
DWORD dwSaveWidthBytes ;//= CalcDibWidthBytes(w, m_nBitCount);

//每行字节数必须被4整除
//if(pDoc->m_DIB.GetBitCount() ==8)
// dwSaveWidthBytes=((nWidth * 8 + 31) / 32) * 4;
//else
// dwSaveWidthBytes=((nWidth * 24 + 31) / 32) * 4;
dwSaveWidthBytes=((nWidth * 8 + 31) / 32) * 4;
//DIB位图数据大小, 以字节为单位
DWORD dwDibBitsSize = dwSaveWidthBytes * nHeight;
//计算整个Dib文件的大小dwFileSize
DWORD dwFileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwDibBitsSize;
//if(pDoc->m_DIB.GetBitCount() == 8)
dwFileSize += (256 * sizeof(RGBQUAD));

//计算位图信息到位图数据间的偏移量(字节)
DWORD dwOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//if(m_nBitCount == 8)
//if(pDoc->m_DIB.GetBitCount() ==8)
dwOffBits += (256 * sizeof(RGBQUAD));
m_pBMI->bmiHeader.biBitCount=8;//位图的每个象素的为数,1位对应的颜色总数为2,4--16,8--256,24--16777216
m_pBMI->bmiHeader.biClrImportant=0;//指定对于显示该位图比较重要的颜色索引个数,若值为0,则所有的颜色都是重要的。
m_pBMI->bmiHeader.biClrImportant=0;//位图实际使用的颜色数
m_pBMI->bmiHeader.biCompression=BI_RGB;//压宿方式
m_pBMI->bmiHeader.biClrUsed =0;
m_pBMI->bmiHeader.biHeight=nHeight;
m_pBMI->bmiHeader.biWidth=nWidth;
m_pBMI->bmiHeader.biPlanes=1;//表示目标设备的位平面数
m_pBMI->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
m_pBMI->bmiHeader.biXPelsPerMeter=0;//表示目标设备的水平分辨率
m_pBMI->bmiHeader.biYPelsPerMeter=0;//表示目标设备的垂直分辨率
m_pBMI->bmiHeader.biSizeImage =0;//nWidth*nHeight;

BITMAPFILEHEADER bmh;//位图文件头结构
LPBITMAPINFOHEADER lpBl;//指向位图信息结构的指针
RGBQUAD rgb[256];
DWORD dwDibSize;
lpBl=(LPBITMAPINFOHEADER)m_pBMI;

if(lpBl==NULL)
{
delete[] m_pBMI;
fclose(file);
return -2;

}
dwDibSize=*(LPDWORD)lpBl+256*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER);

DWORD dwBmBitsSize;//BMP文件信息结构所占的字节数
dwBmBitsSize=dwSaveWidthBytes*nHeight;// lpBl->biWidth*lpBl->biHeight*4;//存储时位图所有象素所占

dwDibSize+=dwBmBitsSize;
lpBl->biSizeImage=dwBmBitsSize;//位图所有象素所占的字节总数

bmh.bfType=0x4d42;
bmh.bfSize=dwFileSize;//dwDibSize;//+sizeof(BITMAPFILEHEADER);//文件总长度

bmh.bfReserved1=0;
bmh.bfReserved2=0;
bmh.bfOffBits=dwOffBits;//sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); ;//(DWORD)sizeof(BITMAPFILEHEADER)+lpBl->biSize +256*sizeof(RGBQUAD);//
//palette
for(int i=0;i<256;i++)
{
rgb[i].rgbBlue=i;
rgb[i].rgbGreen=i;
rgb[i].rgbRed=i;
rgb[i].rgbReserved =0;
}


LPBYTE lpNew;//,lp1;//,lp2,
lpNew=(LPBYTE)malloc((long)nWidth*nHeight);
for (i=0;i<nHeight;i++)
for (j=0;j<nWidth;j++)
{
*(lpNew+(long)i*nWidth+j)=*(m_bTmpSrcImg+(long)i*nScanLine+j*4);
}

hfqian 2003-01-16
  • 打赏
  • 举报
回复
将生成的文件和Windows下工具生成的文件进行二进制(十六进制)比较,很快你就会发现文件头不一致,对照程序就知道错误的位置了

19,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧