C语言24bit的BMP转成8bit的达不到效果,求解

denganliang825 2012-06-10 10:45:03
下面是我写的将24bit转换为8bit的bmp,结果转换出错。
程序如下:

#include "stdio.h"
#include "stdlib.h"

bool RmwWrite8BitImg2BmpFile(BYTE *pImg,int width,int height,const char * filename)
{
//写8Bit灰度图像,文件格式为:bmp
//注意,当宽度不足4的倍数时自动添加成4的倍数
FILE *BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
int i,extend;
bool Suc=true;
BYTE p[4],*pCur;
//Create File
if((BinFile=fopen(filename,"w+b"))==NULL) { return false; };
//Fill the FileHeader
FileHeader.bfType=((WORD)('M'<<8)|'B');//bmp文件的默认的类别是"BM",而WORD类型存放的时候是先低后高的,所以存为MB了
FileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+256*4L;
FileHeader.bfSize=FileHeader.bfOffBits+width*height;
FileHeader.bfReserved1=0;
FileHeader.bfReserved2=0;
if(fwrite((void *)&FileHeader,1,sizeof(FileHeader),BinFile)!=sizeof(FileHeader)) Suc=false;
//Fill the ImgHeader
BmpHeader.biSize=40;
BmpHeader.biWidth=width;
BmpHeader.biHeight=height;
BmpHeader.biPlanes=1;
BmpHeader.biBitCount=8;
BmpHeader.biCompression=0;
BmpHeader.biSizeImage=0;
BmpHeader.biXPelsPerMeter=0;
BmpHeader.biYPelsPerMeter=0;
BmpHeader.biClrUsed=0;
BmpHeader.biClrImportant=0;
if(fwrite((void *)&BmpHeader,1,sizeof(BmpHeader),BinFile)!=sizeof(BmpHeader)) Suc=false;
//write Pallete
for (i=0,p[3]=0;i<256;i++)
{
p[3]=0;
p[0]=p[1]=p[2]=i;
if(fwrite((void *)p,1,4,BinFile)!=4) { Suc=false;break;};
}
//write image data
extend=(width+3)/4*4-width;//计算出要填充的部分
if(extend==0)
{
for(pCur=pImg+(height-1)*width;pCur>=pImg;pCur-=width)//注意这里是pCur-width
{
if(fwrite((void *)pCur,1,width,BinFile)!=(unsigned int)width) Suc=false;//真实的数据
}
}
else
{
for (pCur=pImg+(height-1)*width;pCur>=pImg;pCur-=width)
{
if(fwrite((void *)pCur,1,width,BinFile)!=(unsigned int)width) Suc=false;//真实的数据
for (i=0;i<extend;i++)
{
//此处是什么道理,没有明白,好像只填充了一个
if (fwrite((void *)(pCur+width-1),1,1,BinFile)!=1) Suc=false;
}
}
}
//return
fclose(BinFile);
return Suc;
}

BYTE *RmwRead24BitBmpFile2Img(const char * filename,int *width,int *height)
{
//读取24Bit灰度图像,文件格式是:bmp
FILE *BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
BYTE *pImg;
unsigned int size;
int Suc=1,w,h;//w,h是临时的变量,Suc是操作是否成功的

//Open File
*width=*height=0;
if((BinFile=fopen(filename,"rb"))==NULL) return NULL;
//Read Struct Info
if(fread((void *)&FileHeader,1,sizeof(FileHeader),BinFile)!=sizeof(FileHeader)) Suc=-1;
if(fread((void *)&BmpHeader,1,sizeof(BmpHeader),BinFile)!=sizeof(BmpHeader)) Suc=-1;
if(Suc==-1||(FileHeader.bfOffBits<sizeof(FileHeader)+sizeof(BmpHeader)))
{
fclose(BinFile);
return NULL;
}
//Read Image Data
*width=w=(BmpHeader.biWidth+3)/4*4;
*height=h=BmpHeader.biHeight;
size=(BmpHeader.biWidth+3)/4*4*BmpHeader.biHeight*3;
fseek(BinFile,FileHeader.bfOffBits,SEEK_SET);
if((pImg=new BYTE[size])!=NULL)
{
for(int i=0;i<h;i++) //0,1,2,3,4(5):400-499
{
if(fread(pImg+(h-1-i)*w,sizeof(BYTE)*3,w,BinFile)!=(unsigned int)w)
{
fclose(BinFile);
delete pImg;
pImg=NULL;
return NULL;
}
}
}
fclose(BinFile);
return pImg;
}

void dal24bitto8bit(BYTE *pImg,int width,int height,BYTE *pNewImg)
{
BYTE *pEnd,*pCur,*pNewCur;
BYTE r,g,b;
r=g=b=0;

for(pEnd=pImg+width*height*3,pCur=pImg,pNewCur=pNewImg;pCur<pEnd;)
{
*(pNewCur++)=*(pCur++);
pCur++;
pCur++;
}
return ;
}
int main()
{
//读取24bit图像
BYTE *pImg,*pNewImg;
int width,height;
char *filename="lena.bmp";
char *newfilename="lena8bit.bmp";
pImg=RmwRead24BitBmpFile2Img(filename,&width,&height);
pNewImg=(BYTE *)malloc(width*height*sizeof(BYTE));
dal24bitto8bit(pImg,width,height,pNewImg);
if(RmwWrite8BitImg2BmpFile(pNewImg,width,height,newfilename)==true)
printf("file %s created !\n",newfilename);
return 0;
}


转换后只能看到一部分,我自己推测可能是读取24bitBMP和进行转换操作时候出错了,其中进行转换的操作单独列在下面:
void dal24bitto8bit(BYTE *pImg,int width,int height,BYTE *pNewImg)
{
BYTE *pEnd,*pCur,*pNewCur;
BYTE r,g,b;
r=g=b=0;

for(pEnd=pImg+width*height*3,pCur=pImg,pNewCur=pNewImg;pCur<pEnd;)
{
*(pNewCur++)=*(pCur++);
pCur++;
pCur++;
}
return ;
}


大家能不能帮忙看看,把main函数中的filename改一下就可以测试,这里贴不了图片!
...全文
316 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2012-06-10
  • 打赏
  • 举报
回复
好的,谢谢你,我也学习学习你的代码,分都给你吧!
[Quote=引用 1 楼 的回复:]

参考我的:‘24to8Colors.zip’ 0分
http://download.csdn.net/detail/schlafenhamster/3992785
[/Quote]
「已注销」 2012-06-10
  • 打赏
  • 举报
回复
问题我自己解决了,原来是我读取24bit的BMP的时候求width求错了,我写成了:
*width=(BmpHeader.biWidth+3)/4*4;

这是8bit的BMP的求宽度的求法,24bit的应该是: *width=(BmpHeader.biWidth*3+3)/4*4;

然后我修改了相关的语句就正确了,代码如下:


#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
#include "stdio.h"
#include "stdlib.h"

bool RmwWrite8BitImg2BmpFile(BYTE *pImg,int width,int height,const char * filename)
{
//写8Bit灰度图像,文件格式为:bmp
//注意,当宽度不足4的倍数时自动添加成4的倍数
FILE *BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
int i,extend;
bool Suc=true;
BYTE p[4],*pCur;
//Create File
if((BinFile=fopen(filename,"w+b"))==NULL) { return false; };
//Fill the FileHeader
FileHeader.bfType=((WORD)('M'<<8)|'B');//bmp文件的默认的类别是"BM",而WORD类型存放的时候是先低后高的,所以存为MB了
FileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+256*4L;
FileHeader.bfSize=FileHeader.bfOffBits+width*height;
FileHeader.bfReserved1=0;
FileHeader.bfReserved2=0;
if(fwrite((void *)&FileHeader,1,sizeof(FileHeader),BinFile)!=sizeof(FileHeader)) Suc=false;
//Fill the ImgHeader
BmpHeader.biSize=40;
BmpHeader.biWidth=width;
BmpHeader.biHeight=height;
BmpHeader.biPlanes=1;
BmpHeader.biBitCount=8;
BmpHeader.biCompression=0;
BmpHeader.biSizeImage=0;
BmpHeader.biXPelsPerMeter=0;
BmpHeader.biYPelsPerMeter=0;
BmpHeader.biClrUsed=0;
BmpHeader.biClrImportant=0;
if(fwrite((void *)&BmpHeader,1,sizeof(BmpHeader),BinFile)!=sizeof(BmpHeader)) Suc=false;
//write Pallete
for (i=0,p[3]=0;i<256;i++)
{
p[3]=0;
p[0]=p[1]=p[2]=i;
if(fwrite((void *)p,1,4,BinFile)!=4) { Suc=false;break;};
}
//write image data
extend=(width+3)/4*4-width;//计算出要填充的部分
if(extend==0)
{
for(pCur=pImg+(height-1)*width;pCur>=pImg;pCur-=width)//注意这里是pCur-width
{
if(fwrite((void *)pCur,1,width,BinFile)!=(unsigned int)width) Suc=false;//真实的数据
}
}
else
{
for (pCur=pImg+(height-1)*width;pCur>=pImg;pCur-=width)
{
if(fwrite((void *)pCur,1,width,BinFile)!=(unsigned int)width) Suc=false;//真实的数据
for (i=0;i<extend;i++)
{
//此处是什么道理,没有明白,好像只填充了一个
if (fwrite((void *)(pCur+width-1),1,1,BinFile)!=1) Suc=false;
}
}
}
//return
fclose(BinFile);
return Suc;
}


BYTE *RmwRead24BitBmpFile2Img(const char * filename,int *width,int *height,int *ww)
{
//读取24Bit灰度图像,文件格式是:bmp
FILE *BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
BYTE *pImg;
unsigned int size;
int Suc=1,w,h;//w,h是临时的变量,Suc是操作是否成功的

//Open File
*width=*height=0;
if((BinFile=fopen(filename,"rb"))==NULL) return NULL;
//Read Struct Info
if(fread((void *)&FileHeader,1,sizeof(FileHeader),BinFile)!=sizeof(FileHeader)) Suc=-1;
if(fread((void *)&BmpHeader,1,sizeof(BmpHeader),BinFile)!=sizeof(BmpHeader)) Suc=-1;
if(Suc==-1||(FileHeader.bfOffBits<sizeof(FileHeader)+sizeof(BmpHeader)))
{
fclose(BinFile);
return NULL;
}
//Read Image Data
*width=w=(BmpHeader.biWidth*3+3)/4*4;
*ww=(BmpHeader.biWidth+3)/4*4;
*height=h=BmpHeader.biHeight;
size=w*h;
fseek(BinFile,FileHeader.bfOffBits,SEEK_SET);
if((pImg=new BYTE[size])!=NULL)
{
for(int i=0;i<h;i++) //0,1,2,3,4(5):400-499
{
if(fread(pImg+(h-1-i)*w,sizeof(BYTE),w,BinFile)!=(unsigned int)w)
{
fclose(BinFile);
delete pImg;
pImg=NULL;
return NULL;
}
}
}
fclose(BinFile);
return pImg;
}

void dal24bitto8bit(BYTE *pImg,int width,int height,BYTE *pNewImg)
{
BYTE *pEnd,*pCur,*pNewCur;
for(pEnd=pImg+width*height,pCur=pImg,pNewCur=pNewImg;pCur<pEnd;)
{
*(pNewCur++)=((*(pCur++))+(*(pCur++))+(*(pCur++)))/3;
}
return ;
}
int main()
{
//读取24bit图像
BYTE *pImg,*pNewImg;
int width,height,ww;
char *filename="lena.bmp";
char *newfilename="lena8bit.bmp";
pImg=RmwRead24BitBmpFile2Img(filename,&width,&height,&ww);
pNewImg=(BYTE *)malloc(ww*height*sizeof(BYTE));
dal24bitto8bit(pImg,width,height,pNewImg);
if(RmwWrite8BitImg2BmpFile(pNewImg,ww,height,newfilename)==true)
printf("file %s created !\n",newfilename);
return 0;
}
schlafenhamster 2012-06-10
  • 打赏
  • 举报
回复
参考我的:‘24to8Colors.zip’ 0分
http://download.csdn.net/detail/schlafenhamster/3992785

19,468

社区成员

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

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