使用C生成bmp图片(pixel阵列方式)

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 
  6 typedef unsigned char byte;
  7 typedef unsigned short dbyte;
  8 typedef long int dword;
  9 typedef unsigned short word;
 10 
 11 
 12 /*******************************************
 13 *定义bmp文件的头部数据结构
 14 ********************************************/
 15 #pragma pack(push,2)  //保持2字节对齐
 16 
 17 
 18 struct tagBITMAPFILEHEADER {
 19     //bmp file header
 20     dbyte bfType;        //文件类型
 21     dword bfSize;            //文件大小,字节为单位
 22     word bfReserved1;   //保留,必须为0
 23     word bfReserved2;   //保留,必须为0
 24     dword bfOffBits;         //从文件头开始的偏移量
 25 
 26 
 27     //bmp info head
 28     dword  biSize;            //该结构的大小
 29     dword  biWidth;           //图像的宽度,以像素为单位
 30     dword  biHeight;          //图像的高度,以像素为单位
 31     word biPlanes;          //为目标设备说明位面数,其值总是设为1
 32     word biBitCount;        //说明比特数/像素
 33     dword biCompression;     //图像数据压缩类型
 34     dword biSizeImage;       //图像大小,以字节为单位
 35     dword biXPelsPerMeter;   //水平分辨率,像素/米
 36     dword biYPelsPerMeter;   //垂直分辨率,同上
 37     dword biClrUsed;         //位图实际使用的彩色表中的颜色索引数
 38     dword biClrImportant;    //对图像显示有重要影响的颜色索引的数目
 39       
 40     //bmp rgb quad
 41      //对于16位,24位,32位的位图不需要色彩表
 42     //unsigned char rgbBlue;    //指定蓝色强度
 43     //unsigned char rgbGreen;   //指定绿色强度
 44     //unsigned char rgbRed;     //指定红色强度
 45     //unsigned char rgbReserved; //保留,设置为0 
 46 }BMPFILEHEADER;
 47 #pragma pack(2)
 48 
 49 
 50 struct tagBITMAPFILEHEADER *bmp_p;  //定义bmp文件头结构体指针
 51 FILE *fd;    //定义一个文件类型的指针
 52 
 53 
 54 /*************************************************************
 55 *初始化bmp文件头部,设置bmp图片
 56 **************************************************************/
 57 
 58 // 计算每一行像素 4 字节对齐后的字节数
 59 int caculateLineBytes(int width)
 60 {
 61     //******* 四字节对齐 *******
 62     return (width*3 + 3)/4 *4;
 63     //******* 四字节对齐 *******
 64 }
 65 
 66 int main(void)
 67 {
 68     //防止中文乱码
 69     #ifdef _WIN32
 70     SetConsoleOutputCP (65001);
 71     #endif
 72 
 73     FILE *fpin=fopen("base.txt","r");  //数据文件
 74     static char *file_name =NULL;    //保存文件名的指针
 75     static long file_length;  //文件的大小(整个文件)
 76     unsigned char *file_p = NULL;       //写入数据指针
 77     unsigned char *file_p_tmp = NULL;    //写入数据临时指针
 78     unsigned char *byte_copy_p = NULL;   //文件头部传递指针
 79     unsigned char byte_copy = 0;        //文件头部数据拷贝变量
 80     int i, width;  
 81     printf("请新建文本文件并命名“base.txt”,再文件中分别输入分辨率x,y\n重复单元大小x,y,重复单元内容R,G,B;各项数据间以空格或者换行进行区分。\n程序只会取整进行计算,如果为浮点值,则舍去小数部分!\n");
 82 
 83     //bmp头信息
 84     bmp_p = &BMPFILEHEADER;
 85     bmp_p-> bfType = 0x4D42;    //文件类型
 86 
 87     bmp_p-> bfReserved1 = 0x0;   //保留,必须为0
 88     bmp_p-> bfReserved2 = 0x0;   //保留,必须为0
 89     bmp_p-> bfOffBits = 0x36;         //从文件头开始的偏移量
 90  
 91     //bmp info head
 92     bmp_p-> biSize = 40;            //该结构的大小
 93     bmp_p-> biPlanes = 1;    //为目标设备说明位面数,其值总是设为1
 94     bmp_p-> biBitCount = 24;        //说明比特数/像素
 95     bmp_p-> biCompression = 0;     //图像数据压缩类型(0为无压缩)
 96     fscanf(fpin, "%ld", &bmp_p->biWidth);//读取图像宽度
 97     width=caculateLineBytes(bmp_p->biWidth); //计算对齐后的实际图片宽度
 98     fscanf(fpin, "%ld", &bmp_p->biHeight);
 99     bmp_p->biHeight=-1*(bmp_p->biHeight);//读取图像高度,并转换读取方向
100     bmp_p-> biSizeImage=width*bmp_p->biHeight*(-1); //计算图像大小
101 
102     bmp_p-> biXPelsPerMeter = 10000;//0x60;   //水平分辨率,像素/米
103     bmp_p-> biYPelsPerMeter = 10000;   //垂直分辨率,同上
104     bmp_p-> biClrUsed = 0;         //位图实际使用的彩色表中的颜色索引数
105     bmp_p-> biClrImportant = 0;    //对图像显示有重要影响的颜色索引的数目
106     //读取重复单元内容
107     int numx,numy,Ux,Uy,lastp; //存储重复单元
108     fscanf(fpin,"%d %d",&Ux,&Uy);    //赋值数组
109     if(bmp_p->biWidth<Ux || -bmp_p->biHeight<Uy) //排除输入错误的情况
110 
111     {
112         printf("重复单元必须大于等于图像分辨率!");
113         getchar();
114         return 0;
115     }
116 
117     int Punit[Uy][Ux][3];  //定义unit数组
118 
119        for(int i=0;i<Uy;i  ++)
120     {
121         for(int j=0;j<Ux;j++)
122         {   
123             if(feof(fpin)!=0)
124             {
125                 printf("输入字符不够!请补充!");
126                 fclose(fpin);
127                 getchar();
128                 return 0;
129             }
130             fscanf(fpin,"%d,%d,%d",&Punit[i][j][0],&Punit[i][j][1],&Punit[i][j][2]);
131         }
132         
133     }
134 
135     numx=(bmp_p->biWidth)/Ux; //列数
136     numy=-1*(bmp_p->biHeight/Uy); //行数
137     fclose(fpin);
138 
139     file_name = "test1.bmp";
140     file_length=bmp_p->biSizeImage+54;
141     bmp_p->bfSize =file_length;//实际文件大小
142     file_p = (unsigned char *)malloc(sizeof(char)*file_length);   //申请一段内存
143     memset(file_p,0,sizeof(char)*file_length); //初始化为0
144     file_p_tmp = file_p;
145     int flag=width-Ux*numx*3,mi; //对行尾进行标记
146     //写入文件头和信息头
147     byte_copy_p = (unsigned char *)bmp_p;
148     file_p_tmp = file_p;
149     for(i = 0;i < 54;i++)
150     {
151         *file_p_tmp = *byte_copy_p; 
152         file_p_tmp++;
153         byte_copy_p++;
154     }
155     //写入图像具体数据
156     for(int j=0;j<numy;j++)//对行单元重复数量操作
157     {
158         for(int l=0;l<Uy;l++)//对行重复
159         {
160             for(int i=0;i<numx;i++)//对列单元重复数量操作
161             {
162                     for(int k=0;k<Ux;k++)//对列重复数量操作
163                     {
164                    
165                         *file_p_tmp=Punit[l][k][2]; //写入红色
166                         file_p_tmp++;
167                         *file_p_tmp=Punit[l][k][1]; //写入绿色
168                         file_p_tmp++;
169                         *file_p_tmp=Punit[l][k][0]; //写入蓝色
170                         file_p_tmp++;
171                         if (flag>0 && ((i*Ux+k+1)*3+flag==width))
172                         {
173                             for(mi=0;mi<flag;mi++)
174                             {
175                                 *file_p_tmp=0;
176                                 file_p_tmp++;
177                             }
178                         }   
179                         
180                     }
181                     
182             }
183         }
184     }
185 
186    fd = fopen(file_name, "w");
187    fwrite(file_p, file_length, 1,fd);
188    free(file_p);                        //释放申请的内存(重要)
189    fclose(fd); 
190    fclose(fpin);
191    printf("Done success!!!\n");
192    getchar();
193    return (0);
194 }

需要在同目录下设置base.txt文件,并输入数据;

使用vs code搭配minGW 64编译完成。

数组生成部分不规范,但是可以用minGW编译完成

posted @ 2021-10-27 17:39  color_bar  阅读(249)  评论(0)    收藏  举报