/******************************************************************************
技术宅的结界:http://www.0xAA55.com/
大家放心,我一定是按照最没有节操的方式编写的。相信这点难度是一定难不倒大家的。
我相信大家是一定能把它读懂的!
用法:
BMPGRAY 输入文件.BMP 输出文件.BMP
注意输入文件必须是8位256色的BMP位图。嗯,就这些。
为了能让这个程序兼容DOS、c4droid等,我只让它输出英文信息,而且不包含windows.h
******************************************************************************/#include<stdio.h>
#include<malloc.h>
typedefsignedlongLONG;typedefunsignedcharBYTE;typedefunsignedshortWORD;typedefunsignedlongDWORD;#pragma pack(push,1)
typedefstructtagBITMAPFILEHEADER{WORDbfType;DWORDbfSize;WORDbfReserved1;WORDbfReserved2;DWORDbfOffBits;}BITMAPFILEHEADER,*PBITMAPFILEHEADER;typedefstructtagBITMAPINFOHEADER{DWORDbiSize;LONGbiWidth;LONGbiHeight;WORDbiPlanes;WORDbiBitCount;DWORDbiCompression;DWORDbiSizeImage;LONGbiXPelsPerMeter;LONGbiYPelsPerMeter;DWORDbiClrUsed;DWORDbiClrImportant;}BITMAPINFOHEADER,*PBITMAPINFOHEADER;typedefstructtagRGBQUAD{BYTErgbBlue;BYTErgbGreen;BYTErgbRed;BYTErgbReserved;}RGBQUAD;#pragma pack(pop)
RGBQUADPALGray[256]={0};RGBQUADPALOrg[256]={0};staticcharszReadFail[]="Unable to read data from %s\n";staticcharszWriteFail[]="Write data to %s failed.\n";intmain(intargc,char**argv){if(argc>2){//参数个数必须是2个以上
FILE*fp1,*fp2;if(fp1=fopen(argv[1],"rb")){//打开来源文件
BITMAPFILEHEADERBMFH;BITMAPINFOHEADERBMIF;if(fread(&BMFH,1,sizeof(BMFH),fp1)==sizeof(BMFH)){//读取BMP文件头
if(BMFH.bfType==0x4D42){//文件头标记必须是"BM"
if(fread(&BMIF,1,sizeof(BMIF),fp1)==sizeof(BMIF)){//读取BMP信息头
if(BMIF.biSize==sizeof(BMIF)){//BMP信息头的大小必须是对的
if(BMIF.biBitCount==8){//BMP必须为256色8位
if(fread(PALOrg,1,sizeof(PALOrg),fp1)==sizeof(PALOrg)){//读取调色板
unsignedinti;WORDwAvr;for(i=0;i<256;i++){//将调色板黑白化
wAvr=(PALOrg[i].rgbRed+PALOrg[i].rgbGreen+PALOrg[i].rgbBlue)/3;//取得调色板灰度
PALOrg[i].rgbRed=PALOrg[i].rgbGreen=PALOrg[i].rgbBlue=(BYTE)wAvr;//然后赋值
}if(fp2=fopen(argv[2],"wb")){//打开目标文件准备写入
if(fwrite(&BMFH,1,sizeof(BMFH),fp2)==sizeof(BMFH)){//写入BMP文件头
if(fwrite(&BMIF,1,sizeof(BMIF),fp2)==sizeof(BMIF)){//写入BMP信息头
for(i=0;i<256;i++)PALGray[i].rgbRed=PALGray[i].rgbGreen=PALGray[i].rgbBlue=(BYTE)i;//建立灰度调色板
if(fwrite(PALGray,1,sizeof(PALGray),fp2)==sizeof(PALGray)){//写入调色板
DWORDdwPitch=((BMIF.biWidth-1)/4+1)*4;//原图、目标图每行字节数
BYTE*pBits=(BYTE*)malloc(dwPitch);//分配内存准备操作
if(pBits){//如果分配到了内存
if(BMIF.biHeight<0)//考虑到顶到下型位图
BMIF.biHeight=-BMIF.biHeight;for(i=0;i<BMIF.biHeight;i++){if(fread(pBits,1,dwPitch,fp1)==dwPitch){for(unsignedintx=0;x<BMIF.biWidth;x++)pBits[x]=PALOrg[pBits[x]].rgbRed;//根据亮度进行处理
if(fwrite(pBits,1,dwPitch,fp2)!=dwPitch){//保存一行。
printf(szWriteFail,argv[2]);free(pBits);fclose(fp2);fclose(fp1);return2;}}else{printf(szReadFail,argv[1]);free(pBits);fclose(fp2);fclose(fp1);return2;}}free(pBits);fclose(fp2);fclose(fp1);return0;}else{printf("No enough memory or %s is too wide.\n",argv[2]);fclose(fp2);fclose(fp1);return2;}}else{printf(szWriteFail,argv[2]);fclose(fp2);fclose(fp1);return2;}}else{printf(szWriteFail,argv[2]);fclose(fp2);fclose(fp1);return2;}}else{printf(szWriteFail,argv[2]);fclose(fp2);fclose(fp1);return2;}}else{printf(szWriteFail,argv[2]);fclose(fp1);return2;}}else{printf(szReadFail,argv[1]);fclose(fp1);return2;}}else{printf("%s is not a 8-bit BMP file.\n",argv[1]);fclose(fp1);return2;}}else{printf("%s is not a valid BMP file.(BITMAPINFOHEADER)\n",argv[1]);fclose(fp1);return2;}}else{printf(szReadFail,argv[1]);fclose(fp1);return2;}}else{printf("%s is not a valid BMP file.(BITMAPFILEHEADER)\n",argv[1]);fclose(fp1);return2;}}else{printf(szReadFail,argv[1]);fclose(fp1);return2;}}else{printf(szReadFail,argv[1]);return2;}}else{printf("USAGE:\n""BMPGRAY INPUT.BMP OUTPUT.BMP\n");return1;}}