#include <iostream>
#include "myBMP.h"
#include <fstream>
using namespace std;
bool myBitmp::InitBMP(char *FileName)
{
bool ret=0;
hFile = ::CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if((int) hFile == -1)
{
/*//printf( "不能打开文件,请重新选择!\n "); */
return 0;
}
length=GetFileSize(hFile,NULL);
myBitmpBuffer=new char[length];
ReadFile(hFile,myBitmpBuffer,length,&dwWriteNum,NULL);
//cout<<myBitmpData+1;
Bmphaed= (BITMAPFILEHEADER *) myBitmpBuffer;
BmpInfohead =(BITMAPINFOHEADER*)( myBitmpBuffer+14);
BmpInfohead->biSizeImage=(BmpInfohead->biWidth*BmpInfohead->biBitCount+31)/32*4*BmpInfohead->biHeight;
Datalength=length-Bmphaed->bfOffBits;
myBitmpData=new char[length-Datalength];
myBitmpData=myBitmpBuffer+Bmphaed->bfOffBits;
if( BmpInfohead->biClrUsed==0 )
{
numofCorlorList=NumColorList( BmpInfohead->biBitCount);
}
else
{
numofCorlorList=BmpInfohead->biClrUsed;
}
if(length-Datalength!=numofCorlorList*4+54)
cout<<"lengherror"<<endl;
for(int i=0;i<numofCorlorList;i++)
{
RGBQUAD *temp;
temp=(RGBQUAD*)( myBitmpBuffer+54+4*i);
CorlorList.push_back(*temp);
}
strFileName=FileName;
CloseHandle( hFile );
return 1;
}
bool myBitmp::Convert(char *FileName,int bitcount) //转换 现在只支持8bit转1bit
{
if(BmpInfohead->biBitCount!=8)
{
cout<<"暂不支持";
return 0;
}
HANDLE hSaveFile = CreateFile( FileName, GENERIC_WRITE, FILE_SHARE_WRITE,NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if( !hSaveFile )
{
return FALSE;
}
/*ofstream file;
file.open("c://file.txt");*/
BITMAPFILEHEADER BFH= *Bmphaed; //创建临时文件头
BITMAPINFOHEADER IFO= *BmpInfohead; //创建临时文图文件头
vector <RGBQUAD> mycolorlist;
BFH.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+4*NumColorList( bitcount); //计算新的文件偏移量
IFO.biBitCount=bitcount; //计算新的文件颜色深度
IFO.biSizeImage=(IFO.biWidth*bitcount+31)/32*4*IFO.biHeight; //计算新的位图数据大小
BFH.bfSize=IFO.biSizeImage+BFH.bfOffBits; //计算新的位图大小
char *Databuffer =new char[IFO.biSizeImage]; //创建一个buffer存储新的位图数据
int linelenth=BmpInfohead->biWidth; //原位图实际每行的长度
int remain=4-linelenth%4; //原位图实际每行冗余数据的长度
if(remain==4)
remain=0;
for(int i=0;i<IFO.biSizeImage;++i) //buffer清零
*(Databuffer+i)=0;
int offset=0; //新位图数据偏移量
int numberofline=1; //临时变量存储现在处理的行数
int count=0; //记录当前处理目标图像元素的位置
for(int i=0;i< BmpInfohead->biSizeImage;i++) //开始处理
{
if(i>=numberofline*(linelenth+remain)) //判断是不是该处理新的一行
{
numberofline++;
}
//printf("%d:%x:",i,*(myBitmpData+i));
// //file<<dec<<i<<":"<<hex<<*(myBitmpData+i);
if(*(myBitmpData+i)<0) //如果原图数据小于0即偏白色,因为数据存储是无符号的,转成有符号第一位就变成了符号位,偏白色第一位是1所以就会是负数
{
int num=i-(numberofline-1)*(linelenth+remain);
//printf(" 左移位数为:%d\n", (7-(num%8)));
//file<<" 左移位数为:"<< (7-(num%8))<<endl;
*(Databuffer+offset)|=0x01<<(7-(num%8)); // 1位深度的位图是1bit表示一像素,11111111表示连续8个白色(最右边最高位是第一个数据),所以要将01偏移7-(i%8)个位置
}
//printf(" %x: 地址为:%x\n", *(Databuffer+offset),(Databuffer+offset));
// cout<<hex<<*(Databuffer+offset)<<" 地址为:"<< (Databuffer+offset)<<endl;
//file<<hex<<*(Databuffer+offset)<<" 地址为:"<< (Databuffer+offset)<<endl;
// if((i+8)%8==7) //处理完最后一位,偏移量+1处理新的一字节
if((count+8)%8==7)
{
offset++;
*(Databuffer+offset)=0; // 新的一字节初始化0
//printf(" 新地址 %x: 初始化?:%x\n",(Databuffer+offset), *(Databuffer+offset));
//file<<" 新地址"<<hex<<(Databuffer+offset)<<" 初始化?:"<< *(Databuffer+offset)<<endl;
count=0; //新的一行 记录初始化
/*if(i==255)
system("pause");*/
}
else{
count++;
}
if((numberofline)*(linelenth+remain)-i-1<=remain) // 如果程序运行到原图每行数据的冗余区,比如每行宽度是29,则30,31是冗余区,而且要图像换行了
{
//count--;
int remain2=4-(linelenth%4); // 因为要换行,计算目标位图,一行数据要多少冗余区填充
if(remain2==4)
remain2=0;
for(int u=0;u<remain2;u++)
{
offset++;
//printf(" wode地址为:%x\n", (Databuffer+offset));
////file<<" wode地址为:"<<hex<<(Databuffer+offset)<<endl;
*(Databuffer+offset)=0; // 冗余区填充为0xff
}
if(remain2!=0)
offset++;
i=(numberofline)*(linelenth+remain)-1; // 修改i的值,直接跳转下一行
count=0;
}
/* int num=*(Databuffer+5);
if(!num<0) */
// system("pause");
}
// file.close();
WriteFile( hSaveFile, &BFH, sizeof(BITMAPFILEHEADER), &dwWriteNum, NULL); //写文件头
WriteFile( hSaveFile, &IFO, sizeof(BITMAPINFOHEADER), &dwWriteNum, NULL); //写位图文件头
mycolorlist=ConvertColorList(bitcount);
for(int i=0;i<mycolorlist.size();++i)
WriteFile( hSaveFile, &mycolorlist[i], 4*bitcount, &dwWriteNum, NULL); //写位图颜色表
WriteFile( hSaveFile, Databuffer, IFO.biSizeImage, &dwWriteNum, NULL); //写位图数据
int num=*(Databuffer+256);
if(!num<0)
system("pause");
CloseHandle( hSaveFile );
// delete []Databuffer;
return 1;
}
std::vector <RGBQUAD> myBitmp::ConvertColorList(int bitcount) //计算位图的颜色表,现只能计算1位的位图,返回一个颜色表容器
{
RGBQUAD templist;
vector <RGBQUAD> mycolorlist;
int number=NumColorList( bitcount);
for (int i=0;i<number;++i)
{
templist.rgbBlue=i;
templist.rgbGreen=i;
templist.rgbRed=i;
templist.rgbReserved=0;
if(i==1)
{
templist.rgbBlue=255;
templist.rgbGreen=255;
templist.rgbRed=255;
}
mycolorlist.push_back(templist);
}
return mycolorlist;
}
int myBitmp::NumColorList(int bitcount) //计算位图的颜色表数量
{
switch(bitcount)
{
case 1:
return 2;
break;
case 4:
return 128;
break;
case 8:
return 256;
break;
case 24:
return 0;
break;
}
}
- 1
- 2
前往页