一、运行环境介绍
Linux系统: Redhat6.3 (32位)
gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
二、功能介绍
创建一张BMP图片,将图片当做画板,在在图片的指定位置绘制中文。
三、核心代码
可以传入任意尺寸的图片进行生成绘制。
#include <stdio.h> #include <string.h> #include <stdlib.h> #pragma pack(1) //强制1个字节对齐 //BMP的文件头 struct _BMP_HEAD { char type[2]; //图片的类型 "BM" unsigned int size; //文件大小 unsigned short r1; //保留1 unsigned short r2; //保留2 unsigned int seek; //数据偏移字节(真实像素点数据) }; //BMP的参数信息 struct _BMP_INFO { unsigned int size; //当前结构体大小 unsigned int w; //宽度 unsigned int h; //高度 unsigned short flag; //固定为1 unsigned short bit; //像素点的位数 unsigned int r1; //压缩方式 0 unsigned int r2; //水平分辨率 unsigned int r3; //垂直分辨率 unsigned int r4; //垂直分辨率 unsigned int r5; //引用色彩 unsigned int r6; //关键色彩 }; /* 函数功能: 显示像素点 */ void Display_Point(char *head,int w,int x,int y,int c) { unsigned char *p=(unsigned char *)(head+w*3*y+x*3); *(p+0)=(c>>0)&0xFF; *(p+1)=(c>>8)&0xFF; *(p+2)=(c>>16)&0xFF; } /* 函数功能: 显示一个数据 函数参数: char *font 取模数据的首地址 (横向取模--高位在前) int w 取模字体的宽度 int h 取模字体的高度 */ void Display_Data(char *font,int w,int h,char *image_head,int image_w,int x,int y) { int i,j; int x0=x; unsigned char data; for(i=0;i<w/8*h;i++) { data=font[i]; for(j=0;j<8;j++) { if(data&0x80) //画前景色 { Display_Point(image_head,image_w,x0,y,0xFF0033); } else //画背景色 { //Display_Point(image_head,image_w,x0,y,0x0066FF); } x0++; data<<=1; } if(x0-x==w) //换行 { x0=x; y++; } } } unsigned char font[]= { /*-- 文字: 钱 --*/ /*-- 宋体36; 此字体下对应的点阵为:宽x高=48x48 --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x3C, 0x00,0x00,0x00,0x78,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x3E,0x78,0x00,0x00,0xFC, 0x00,0x3C,0x3E,0x00,0x00,0xF8,0x00,0x3C,0x1F,0x80,0x00,0xF0,0x00,0x3C,0x0F,0x80, 0x00,0xF0,0x00,0x3C,0x07,0xC0,0x01,0xF0,0x70,0x3E,0x03,0x80,0x01,0xFF,0xF8,0x1E, 0x01,0x80,0x01,0xFF,0xFC,0x1E,0x03,0x00,0x03,0xC0,0x00,0x1E,0x07,0x80,0x03,0xC0, 0x00,0x1F,0xFF,0xC0,0x07,0x80,0x03,0xFF,0xFF,0x80,0x07,0x80,0x1F,0xFE,0x00,0x00, 0x07,0x01,0xCE,0x1E,0x00,0x00,0x0F,0xFF,0xE0,0x1E,0x00,0x00,0x0F,0xFF,0xF0,0x1E, 0x00,0x00,0x1C,0x3C,0x00,0x1F,0x00,0x70,0x38,0x3C,0x00,0x0F,0x00,0xF8,0x38,0x3C, 0x00,0x0F,0x3F,0xFC,0x70,0x3C,0x00,0x1F,0xFF,0xE0,0x20,0x3C,0x1F,0xFF,0xC0,0x00, 0x00,0x3C,0x1F,0xEF,0x01,0x80,0x00,0x3C,0x6C,0x0F,0x81,0xC0,0x1F,0xFF,0xF0,0x07, 0x83,0xE0,0x3F,0xFF,0xF8,0x07,0x87,0xF0,0x1E,0x3C,0x00,0x07,0x87,0xE0,0x00,0x3C, 0x00,0x07,0xCF,0x80,0x00,0x3C,0x00,0x03,0xDF,0x00,0x00,0x3C,0x00,0x03,0xFE,0x00, 0x00,0x3C,0x00,0x03,0xFC,0x00,0x00,0x3C,0x00,0x01,0xF8,0x0C,0x00,0x3C,0x18,0x01, 0xF0,0x0C,0x00,0x3C,0x78,0x03,0xF0,0x1C,0x00,0x3D,0xF0,0x0F,0xF8,0x1C,0x00,0x3F, 0xC0,0x1F,0x7C,0x1C,0x00,0x3F,0x80,0x3E,0x3E,0x3C,0x00,0x7F,0x00,0xFC,0x1F,0x3C, 0x00,0x7E,0x01,0xF0,0x0F,0xBC,0x00,0x7C,0x07,0xC0,0x07,0xFC,0x00,0x38,0x1F,0x00, 0x03,0xFC,0x00,0x10,0x7C,0x00,0x01,0xFC,0x00,0x00,0xE0,0x00,0x00,0xFC,0x00,0x00, 0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; int main(int argc,char **argv) { if(argc!=4) { printf("传入的参数格式: ./a.out <新图片宽度> <新图片高度> <新图片的名称>\n"); printf("例如: ./a.out 80 80 test.bmp"); printf("传入的宽度和高度需要>=48\n"); return 0; } /*1. 创建一张BMP图片*/ FILE *fp=fopen(argv[3],"wb"); if(fp==NULL) { printf("%s 文件创建失败.\n",argv[1]); return 0; } /*2. 创建BMP的文件头*/ int cnt; struct _BMP_HEAD bmp_head; memset(&bmp_head,0,sizeof(struct _BMP_HEAD)); //图片的类型 bmp_head.type[0]='B'; bmp_head.type[1]='M'; //文件大小 bmp_head.size=54+800*480*3; //数据偏移量 bmp_head.seek=54; //写文件头 cnt=fwrite(&bmp_head,1,sizeof(struct _BMP_HEAD),fp); printf("成功写入:%d 字节.\n",cnt); /*3. 写文件参数信息*/ struct _BMP_INFO bmp_info; memset(&bmp_info,0,sizeof(struct _BMP_INFO)); //当前结构体大小 bmp_info.size=sizeof(struct _BMP_INFO); //图片的宽度和高度 bmp_info.w=atoi(argv[1]); bmp_info.h=atoi(argv[2]); //图片的颜色位数 bmp_info.bit=24; //标志位 bmp_info.flag=1; //写入文件参数信息 cnt=fwrite(&bmp_info,1,sizeof(struct _BMP_INFO),fp); printf("成功写入:%d 字节.\n",cnt); /*4.添加水印: 制作图片的数据*/ int one_line_byte=bmp_info.w*3; //BMP图片一行的字节数 while(one_line_byte%4!=0) //补齐4的倍数 { one_line_byte++; } one_line_byte=one_line_byte-bmp_info.w*3; //得到需要补齐的字节数量 //申请一个存放图片颜色数据的缓冲区 char *head_p=malloc(bmp_info.w*3*bmp_info.h); //将缓冲区初始化 memset(head_p,0xFF,bmp_info.w*3*bmp_info.h); //绘制水印 Display_Data(font,48,48,head_p,bmp_info.w,10,10); /*5. 写入位图数据*/ int w,h; char *tmp_p; for(h=bmp_info.h-1;h>=0;h--) { tmp_p=head_p+h*bmp_info.w*3; //从缓冲区的最后一行开始读取 fwrite(tmp_p,1,bmp_info.w*3,fp); //写一行数据 if(one_line_byte) //判断是否需要补齐 fwrite(tmp_p,1,one_line_byte,fp); //写补齐的数据(占位而已--没有显示作用) } /*6. 关闭文件*/ fclose(fp); free(head_p); return 0; }
四、运行效果
[wbyq@wbyq linux_c]$ gcc app.c [wbyq@wbyq linux_c]$ ./a.out 81 81 1.bmp 成功写入:14 字节. 成功写入:40 字节. [wbyq@wbyq linux_c]$ eog 1.bmp