您的位置:首页 > 其它

把24位bmp位图按水平扫描和垂直扫描转为点阵数组

2011-01-07 18:39 267 查看
本来朋友有一个移动和联通的logo点阵,现在突然需要电信的logo,所以就跟他要来了,移动和电信的logo数据,试着显示出来,其实也就是每个字节有8个点,1为显示的点,0不显示!麻烦的就是有要水平扫描和垂直扫描!

所以就写了下面的程序,这个程序是未成品,我只弄了40*40的位图,而且是24位的bmp图片,其它的只要查看一下bmp文件格式,很容易就可以修改了!(生成的数据在文件里)

有兴趣你也可以试一下!

恢复样子:





电信logo文件:放在和程序的目录下(文件被我改后辍了,不然不能上传,把后面的“.jpg”去掉就好了)



代码入下:

#include "stdio.h"
#include "stdlib.h"
// 数据表 水平扫描
const unsigned char unicomLogo[] =
{
56,41,
0x00,0x00,0x0C,0x00,0x60,0x00,0x00,0x00,0x00,0x7F,0x81,0xFC,0x00,0x00,0x00,0x00,
0xFF,0xC3,0xFE,0x00,0x00,0x00,0x01,0xFF,0xE7,0xFF,0x00,0x00,0x00,0x01,0xF3,0xFF,
0xCF,0x00,0x00,0x00,0x03,0xE1,0xFF,0x07,0x80,0x00,0x00,0x03,0xC0,0xFE,0x07,0x80,
0x00,0x00,0x03,0xC0,0xFE,0x07,0x80,0x00,0x00,0x03,0xE1,0xFF,0x0F,0x80,0x00,0x00,
0x01,0xF3,0xFF,0x9F,0x00,0x00,0x00,0x01,0xF9,0xEF,0x3F,0x00,0x00,0x00,0x00,0xFC,
0xC6,0x7E,0x00,0x00,0x00,0x00,0x7E,0x00,0xFC,0x00,0x00,0x00,0x00,0x3F,0x01,0xF8,
0x00,0x00,0x07,0xC0,0x1F,0x83,0xF0,0x07,0xC0,0x1F,0xF0,0xCF,0xC7,0xE6,0x0F,0xF0,
0x3F,0xF9,0xE7,0xE7,0xCF,0x3F,0xF8,0x3F,0xFF,0xF3,0xFF,0x9F,0xFF,0xFC,0x7C,0x7F,
0xE1,0xFF,0x0F,0xFC,0x7C,0x78,0x1F,0xC0,0x7E,0x07,0xF8,0x3C,0x78,0x1F,0x80,0xFE,
0x03,0xF0,0x3C,0x78,0x3F,0xC0,0xFF,0x07,0xFC,0x3C,0x7C,0xFF,0xE1,0xFF,0x8F,0xFE,
0x7C,0x3F,0xFD,0xF3,0xEF,0xCF,0xBF,0xF8,0x1F,0xF0,0xE7,0xC7,0xE7,0x1F,0xF0,0x0F,
0xE0,0x4F,0x83,0xF2,0x0F,0xF0,0x03,0x80,0x1F,0x01,0xF0,0x03,0xC0,0x00,0x00,0x3E,
0x00,0xFC,0x00,0x00,0x00,0x00,0x7C,0xC6,0x7C,0x00,0x00,0x00,0x00,0xF8,0xC6,0x3E,
0x00,0x00,0x00,0x01,0xF3,0xFF,0x9F,0x00,0x00,0x00,0x01,0xF3,0xFF,0x8F,0x00,0x00,
0x00,0x03,0xE0,0xFE,0x0F,0x80,0x00,0x00,0x03,0xE0,0xFE,0x07,0x80,0x00,0x00,0x03,
0xE1,0xFF,0x07,0x80,0x00,0x00,0x03,0xF1,0xFF,0x8F,0x80,0x00,0x00,0x01,0xFF,0xEF,
0xFF,0x00,0x00,0x00,0x00,0xFF,0xC7,0xFF,0x00,0x00,0x00,0x00,0x7F,0x83,0xFC,0x00,
0x00,0x00,0x00,0x1F,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

// 数据表 垂直扫描
const unsigned char cmccLogo[] =
{
48,40,
0x00,0x00,0xff,0x00,0x00,0x00,0x00,0xe0,0xff,0x07,0x00,0x00,0x00,0xf8,0xff,0x1f,
0x00,0x00,0x00,0xfe,0xff,0x7f,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0xc0,0x3f,
0x63,0xfc,0x01,0x00,0xc0,0x1f,0xe7,0xf8,0x03,0x00,0xe0,0x0f,0xce,0xf1,0x07,0x00,
0xf0,0x07,0x9c,0xf1,0x0f,0x00,0xf8,0x07,0x39,0xe3,0x0f,0x00,0xf8,0x83,0x71,0xc6,
0x1f,0x00,0xfc,0xc1,0x71,0x8e,0x3f,0x00,0xfc,0xe0,0xe1,0x1c,0x3f,0x00,0x7e,0xf0,
0xc0,0x19,0x3f,0x00,0x3e,0x70,0x98,0x33,0x7e,0x00,0x3e,0x38,0x98,0x73,0x7c,0x00,
0x1f,0x1c,0x0c,0xe3,0x78,0x00,0x0f,0x0e,0x06,0xe3,0x78,0x00,0x0f,0x07,0x87,0xe1,
0x70,0x00,0x0f,0x87,0xc1,0xe1,0x70,0x00,0x8f,0xc3,0xe1,0x70,0x70,0x00,0x8f,0xc3,
0x70,0x38,0x78,0x00,0x8f,0x63,0x30,0x38,0x78,0x00,0x1e,0xe7,0x18,0x1c,0x7c,0x00,
0x3e,0xe7,0x0c,0x0e,0x7e,0x00,0x3e,0xce,0x01,0x07,0x3f,0x00,0x7c,0x9c,0x81,0x03,
0x3f,0x00,0xfc,0x98,0xc3,0x81,0x3f,0x00,0xfc,0x31,0xe7,0xc1,0x1f,0x00,0xf8,0x71,
0xce,0xe0,0x1f,0x00,0xf0,0xe3,0x1c,0xf0,0x0f,0x00,0xf0,0xc7,0x39,0xf8,0x07,0x00,
0xe0,0x8f,0x31,0xf8,0x07,0x00,0xc0,0x1f,0x63,0xfc,0x03,0x00,0x80,0x3f,0xe7,0xfe,
0x01,0x00,0x00,0xff,0xff,0x7f,0x00,0x00,0x00,0xfc,0xff,0x3f,0x00,0x00,0x00,0xf0,
0xff,0x0f,0x00,0x00,0x00,0x80,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

#define MAX_BACK_COLOR 180  //颜色值
#define BMP_W_H		   40   //准备转换的颜色的大小,也可以弄动态获取,但最近有点忙就不加上了
#define BUF_MAX_SIZE   10000
unsigned char bmpinf[BUF_MAX_SIZE];//保存整张图片,按16进制读取

int bmp_data_start = 0;  //图像的数据偏移位置,bmp的第10位开始,一共4位,低位在前,可参考bmp文件格式说明

int bmpInfLen = 0;		//bmpinf数组已用空间

//画水平logo的
int hexLogView_horizontal(const unsigned char loghex[],int size)
{
int w,h,pos,i,j;

if(loghex ==NULL)
return 1;
//获取宽高
w = loghex[0]/8;
h = loghex[1];

printf("/nsize of logo  =  %d/n",size);
printf("logo view: /n/t");

//从第三个开始,前两个为宽高
pos = 2;

//打印logo
while(pos < size)//查到是否还有数据
{
for(i = 0; i < w; i++)//这个宽为数据高,(因为一个数据有8位)
{
for(j = 7; j >0; j--)//数据,高位在左,所以从第8位(最高位)开始
{
if((loghex[pos+i]>>j)&0x1)//计算数据位置
printf("%c",64);//为1时,画@
else
printf("%c",32);//为0时,空格
}
}
printf("/n/t");
pos +=w;//下一行
}

return 0;
}

int hexLogView_vertical(const unsigned char loghex[],int size)
{
int w,h,pos,i,j,k;
if(loghex ==NULL)
return 1;

//获取宽高
w = loghex[0]/8;
h = loghex[1];

printf("/nsize of logo  =  %d/n",size);
printf("logo view: /n/t");

//从第三个开始,前两个为宽高
pos = 2;
//这里的数据第一行实际上是第一列
//而我们无法按一列一列来画,所以我们选择先每一列的第一个,然后第二个。。。
for(j = 0; j < w; j++)//每一列(这里把8位数据做为一大列)
{
for(k = 0 ; k < 8;k ++)//每一位
{
for(i = 0; i < h; i++)//每一行
{
//printf("%d-%d,",pos+j+5*i,k);
if( (loghex[pos+ j + w*i]>>k) & 0x01)//计算数据位置
printf("%c",64);//为1时,画@
else
printf("%c",32);//为0时,空格

}
printf("/n/t");
}
}
printf("/n");
return 0;
}

//把bmp的所有数据按16进制读出来
int bmpTohex(char *in_file, char * out_file,unsigned char bmpinf[])
{
int ch,i = 0,j = 0;
FILE * fi,*fo;
//打开文件
fi = fopen(in_file,"r");
fo = fopen(out_file,"w+");
if(fi == NULL ||fo == NULL)
{
printf("can't open file !/n");
exit(1);
}
fprintf(fo,"const unsigned char logoInfHex =/n{/n/t");

//一直读取,直到bmp文件结束(EOF)
//注意,在我读取时,有时16进制为“1A”时会被读成EOF,所以我用UltraEdit把“0A”改成了“0B”
while((ch = fgetc(fi)) != EOF)
{

fprintf(fo,"0x%02x,",ch);

bmpinf[j] =ch;//把图像同时保存在全局变量里

i++;
if(i == 16)//输出到文件时,16个数据为一行
{
fprintf(fo,"/n/t");
i = 0;
}
j++;
}
fprintf(fo,"/n};");
printf("bmp size : %d",j);
return j;//返回数据长度
}

//把bmp文件数据转换成数组,分别在hexLogo_horizontal.txt和hexLogo_vertical.txt两个文件中
//一个是水平扫描,一个垂直扫描
void bmpInfToArray(char bmpInf[])
{
int i,j,k,a;
char tmp[BUF_MAX_SIZE];
char bmp[BMP_W_H][BMP_W_H];
FILE *fo,*fo4;
fo =  fopen("hexLogo_horizontal.txt","w+");
fo4 =  fopen("hexLogo_vertical.txt","w+");

fprintf(fo,"/*hexLogo_horizontal*//n");
fprintf(fo,"const unsigned char horizontal_logo[] =/n{/n/t %d,%d,/n/t",BMP_W_H,BMP_W_H);

fprintf(fo4,"/*hexLogo_vertical*//n");
fprintf(fo4,"const unsigned char vertical_logo[] =/n{/n/t %d,%d,/n/t",BMP_W_H,BMP_W_H);

//计算偏移量,偏移量后面就是图像的具体数据
//bmp的格式太多,我这里用的是24位时的,其它的可以参考相关资料修改,不难
bmp_data_start = (bmpinf[13]<<24) + (bmpinf[12]<<16) +(bmpinf[11]<<8) + bmpinf[10];

k = -1;//数据到单色数组
for(i = bmp_data_start;i < bmpInfLen;)
{
k++;
tmp[k] = 0;//默认为0,无色块
for(j =0; j < 3; j++)
{
a = i+j;
if(bmpinf[a] < MAX_BACK_COLOR)//只要有任意一个颜色值小于MAX_BACK_COLOR,就把它当然有颜色的,(因为3个都为255时是白色)
{
tmp[k] = 1;	//
}
}
i += 3;//24位时,3个字节(3原色)为一个点
//bmp是按行存储的,并且是行序是倒过来的
//还有一点就是因为bmp每一行都要求是4的整数倍,所以其实图像大小时要记得做相关处理(我选取40*40,列数是40,无须处理)
//举个例子 ,3*3的位图
//每一行不是3*3字节,面是有4*3个字节,最后的3字节是无用的!
}

a = 0;
k = 0;
//水平扫描数据输出
//因为行序是倒序,所以我们倒着转存
for (i = BMP_W_H -1; i >= 0 ; i--)
{
for(j = 0 ; j < BMP_W_H; j++)
{
a = a*2 | tmp[i*40+j];//每8位为一个数据
k++;
if((j+1)% 8 == 0)//每8位为一个数据
{
fprintf(fo,"0x%02x,",a);a = 0;k = 0;//输出数据
}
}
if(i%2 == 0)
fprintf(fo,"/n/t");
}
fprintf(fo,"/n};");

//在这里先把图像,下面就比较文便处理了
for(i = 0; i < BMP_W_H; i++)
for(j = 0; j < BMP_W_H; j++)
{
bmp[i][j] = 0;
if(i > 1)
{
bmp[i][j] = tmp[(BMP_W_H -1 - i)*40+j];//下上反转过来
}
}

//垂直扫描数据输出
for (j = 0,a = 0; j < BMP_W_H; j++) //按列来保存
{
for(i = 0 ; i < BMP_W_H/8; i++)//每一列的的每个数据(8位)
{

a = a*2 | bmp[i*8 +7][j];//这里是高位在下(如果高位在中的话0到7倒置就好了)
a = a*2 | bmp[i*8 +6][j];
a = a*2 | bmp[i*8 +5][j];
a = a*2 | bmp[i*8 +4][j];
a = a*2 | bmp[i*8 +3][j];
a = a*2 | bmp[i*8 +2][j];
a = a*2 | bmp[i*8 +1][j];
a = a*2 | bmp[i*8 +0][j];
fprintf(fo4,"0x%02x,",a);//输出数据
a = 0;
}
fprintf(fo4,"/n/t");
}
fprintf(fo4,"/n};");
}

int main(void)
{

hexLogView_horizontal(unicomLogo,sizeof(unicomLogo)-1);//联通的logo,水平扫描的
hexLogView_vertical(cmccLogo,sizeof(cmccLogo));//移动的logo,垂直扫描的
bmpInfLen =  bmpTohex("logo.bmp","logo.txt",bmpinf);//把logo.bmp文件按16进制读取然后写入到文件logo.txt和全局数组bmpinf中
bmpInfToArray(bmpinf);//全局数组bmpinf中的数据按水平和垂直扫描方式转换成数组分别存到两个文件中
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: