由于工作需要,时常需要将像素矩阵保存图片显示观看。为此,特地总结了三种使用纯C++代码生成bmp图片的方法。分别是使用自定义数据、从外界导入的txt和csv以及从图片中导入的数据。
1.使用自定义数据保存为bmp图片
- 自定义数据可以是使用公式生成,或者是根据自己需求自己定义的数据,范围为0-255,分别对应从黑色到白色。代码生成过程如下:
1 #pragma warning(disable:4996)
2 #include<iostream>
3 #include<string>
4 using namespace std;
5
6 //#define FrameSize 960*960 //视频帧大小
7 int width = 120, height = 120;
8 #define FrameNum 300 //yuv帧数
9 static const double S_PI = 3.14159265358979323846;
10 #define scos(x) cos((double)(x))
11 #define stan(x) tan((double)(x))
12 #define ssqrt(x) sqrt((double)(x))
13 #define ET_SIZE 300
14 char errorText[ET_SIZE];
15
16 void errorMsg(const char *msg)
17 {
18 printf("error:%s\n", msg);
19 #ifdef _WIN32
20 system("pause");
21 #endif
22 exit(-1);
23 }
24
25 void readSequence(unsigned char *frames)
26 {
27 //Test start
28 for (int y = 0; y < height; y++)
29 {
30 for (int x = 0; x < width; x++)
31 {
32 //使用公式生成像素数据
33 float pu0 = (float)((2.0*(x + 0.5)) / width - 1.0);
34 float pv0 = (float)((2.0*(y + 0.5)) / height - 1.0);
35
36 double tu0 = stan(pu0*S_PI / 4.0);
37 double tv0 = stan(pv0*S_PI / 4.0);
38 double value= 1.0 / (scos(pu0*S_PI / 4.0)*scos(pu0*S_PI / 4.0)*scos(pv0*S_PI / 4.0)*scos(pv0*S_PI / 4.0) * (tu0*tu0 + tv0*tv0 + 1.0) * ssqrt(tu0*tu0 + tv0*tv0 + 1.0));
39
40 //将值从(0,1)放大到(0,255)
41 value= 255.0*value;
42 //将值从(128,255)放大到(0,255),增加图像对比度
43 frames[y*width + x] = 2.0*value- 255.0;
44 }
45 }
46 }
47
48 void write_bmpheader(unsigned char *bitmap, int offset, int bytes, int value)
49 {
50 int i;
51 for (i = 0; i < bytes; i++)
52 bitmap[offset + i] = (value >> (i << 3)) & 0xFF;
53 }
54
55 unsigned char *convertToBmp(unsigned char *inputImg, int width, int height, int *ouputSize)
56 {
57 /*create a bmp format file*/
58 int bitmap_x = (int)ceil((double)width * 3 / 4) * 4;
59 unsigned char *bitmap = (unsigned char*)malloc(sizeof(unsigned char)*height*bitmap_x + 54);
60
61 bitmap[0] = 'B';
62 bitmap[1] = 'M';
63 write_bmpheader(bitmap, 2, 4, height*bitmap_x + 54); //whole file size
64 write_bmpheader(bitmap, 0xA, 4, 54); //offset before bitmap raw data
65 write_bmpheader(bitmap, 0xE, 4, 40); //length of bitmap info header
66 write_bmpheader(bitmap, 0x12, 4, width); //width
67 write_bmpheader(bitmap, 0x16, 4, height); //height
68 write_bmpheader(bitmap, 0x1A, 2, 1);
69 write_bmpheader(bitmap, 0x1C, 2, 24); //bit per pixel
70 write_bmpheader(bitmap, 0x1E, 4, 0); //compression
71 write_bmpheader(bitmap, 0x22, 4, height*bitmap_x); //size of bitmap raw data
72
73 for (int i = 0x26; i < 0x36; i++)
74 bitmap[i] = 0;
75 int k = 54;
76 for (int i = height - 1; i >= 0; i--) {
77 int j;
78 for (j = 0; j < width; j++) {
79 int index = i*width + j;
80 for (int l = 0; l < 3; l++)
81 bitmap[k++] = inputImg[index];
82 }
83 j *= 3;
84 while (j < bitmap_x) {
85 bitmap[k++] = 0;
86 j++;
87 }
88 }
89 *ouputSize = k;
90 return bitmap;
91 }
92
93 void saveToBmp(unsigned char *inputImg, int width, int height, char *outputFileName)
94 {
95 int size;
96 unsigned char *bmp = convertToBmp(inputImg, width, height, &size);
97 FILE *fp = fopen(outputFileName, "wb+");
98 if (fp == NULL) {
99 sprintf(errorText, "Could not open file: %s", outputFileName);
100 errorMsg(errorText);
101 }
102 fwrite(bmp, 1, size, fp);
103 fclose(fp);
104 free(bmp);
105 }
106 int main()
107 {
108 unsigned char *oriFrames;
109 oriFrames = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
110 readSequence(oriFrames);
111
112 char imgName[30];
113 sprintf(imgName, "F:\\pictures\\Bitmap_Weight_Map_Convex2.bmp");
114 //矩阵oriFrames[i]可以是任何你想保存为图片的像素矩阵,这里是yuv视频图像每一帧的像素数据
115 saveToBmp(oriFrames, width, height, imgName);
116 //system("pause");
117 }
- View Code
2.从外界导入的txt和csv保存为bmp图片将数据导入txt中:
1 #pragma warning(disable:4996)
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 //文件写操作txt
7 FILE *fp;//文件指针
8 int i, d;
9 /*文件的打开*/
10 fp = fopen("E:\\VS_Test_Code\\data.txt", "w");//fopen打开文件,这个文件可以是当前不存在的。“w”以写入的形式打开,“r”以读的形式打开
11 if (fp == NULL) //判断如果文件指针为空
12 {
13 printf("File cannot open! ");
14 exit(0);//在以0的形式退出,必须在文件开头有#include <stdlib.h>,stdlib 头文件即standard library标准库头文件
15 }
16 //写入数据
17 for (i = 0; i < 10; i++)
18 {
19 scanf("%d", &d);//用户输入
20 fprintf(fp, "%d,", d);//写入指针fp,写入的东西就是刚才的用户输入的d,注意这里的fp和d没有引号
21 }
22 //关闭文件
23 fclose(fp);
24 }
- View Code
从txt中读取数据:
1 #pragma warning(disable:4996)
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 //文件读操作txt
7 FILE *fp;//文件指针
8 int i, d;
9 /*文件的打开*/
10 fp = fopen("E:\\VS_Test_Code\\data.txt", "r");//fopen打开文件,这个文件可以是当前不存在的。“w”以写入的形式打开,“r”以读的形式打开
11 if (fp == NULL) //判断如果文件指针为空
12 {
13 printf("File cannot open! ");
14 exit(0);//在以0的形式退出,必须在文件开头有#include <stdlib.h>,stdlib 头文件即standard library标准库头文件
15 }
16 int *array = (int*)malloc(sizeof(int) * 10);
17 //读取数据
18 for (i = 0; i < 10; i++)
19 {
20 fscanf(fp, "%d,", &array[i]);//从文件输入
21 printf("%d ", array[i]);//写入指针fp,写入的东西就是刚才的用户输入的d,注意这里的fp和d没有引号
22 }
23 printf("\n");
24 //关闭文件
25 fclose(fp);
26 system("pause");//使窗口保持不关闭
27 }
- View Code
将数据导入csv中:
1 #pragma warning(disable:4996)
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 //文件写操作csv
7 FILE *fp;//文件指针
8 int i, No;
9 double salary;
10 fp = fopen("E:\\VS_Test_Code\\data.csv", "w");//fopen打开文件,这个文件可以是当前不存在的。“w”以写入的形式打开,“r”以读的形式打开
11 if (fp == NULL) //判断如果文件指针为空
12 {
13 printf("File cannot open! ");
14 exit(0);//在以0的形式退出,必须在文件开头有#include <stdlib.h>,stdlib 头文件即standard library标准库头文件
15 }
16 //写入数据
17 for (i = 0; i < 5; i++)
18 {
19 scanf("%d %lf", &No, &salary);//用户输入,double一定要用%lf
20 fprintf(fp, "%d %.2f\n", No, salary);//写入指针fp,写入的东西就是刚才的用户输入的d,注意这里的fp和d没有引号
21 }
22 //关闭文件
23 fclose(fp);
24 }
- View Code
从csv中读取数据:
1 #pragma warning(disable:4996)
2 #include <stdio.h>
3 #include <stdlib.h>
4 int main()
5 {
6 //文件读操作csv
7 FILE *fp;//文件指针
8 int i, No;
9 double salary;
10 fp = fopen("E:\\VS_Test_Code\\data.csv", "r");//fopen打开文件,这个文件可以是当前不存在的。“w”以写入的形式打开,“r”以读的形式打开
11 if (fp == NULL) //判断如果文件指针为空
12 {
13 printf("File cannot open! ");
14 exit(0);//在以0的形式退出,必须在文件开头有#include <stdlib.h>,stdlib 头文件即standard library标准库头文件
15 }
16 //读取数据
17 for (i = 0; i < 5; i++)
18 {
19 fscanf(fp, "%d %lf", &No, &salary);//用户输入,double要用%lf
20 printf("%d\t%.2f\n", No, salary);//写入指针fp,写入的东西就是刚才的用户输入的d,注意这里的fp和d没有引号
21 }
22 //关闭文件
23 fclose(fp);
24 system("pause");
25 }
- View Code
将txt中的数据保存为bmp图片
1 #pragma warning(disable:4996)
2 #include<iostream>
3 #include<string>
4 using namespace std;
5
6 #define FrameSize 100*100 //视频帧大小
7 #define FrameNum 10 //yuv帧数
8 #define ET_SIZE 300
9 char errorText[ET_SIZE];
10
11 void errorMsg(const char *msg) {
12
13 printf("error:%s\n", msg);
14
15 #ifdef _WIN32
16
17 system("pause");
18
19 #endif
20
21 exit(-1);
22
23 }
24
25 void readSequence(char *fileName, unsigned char **frames)
26 {
27 FILE *fp = fopen(fileName, "rb");
28 if (fp == NULL)
29 {
30 sprintf(errorText, "File %s doesn't exist\n", fileName);
31 errorMsg(errorText);
32 }
33
34 int uvSize = FrameSize / 2; //H.264编解码获得的关键帧都是彩色序列,这里主要是提取亮度分量Y。
35 unsigned char *buf = (unsigned char *)malloc(sizeof(unsigned char) * uvSize);
36 for (int i = 0; i < FrameNum; i++) {
37 //read y
38 if (fread(frames[i], 1, FrameSize, fp) != FrameSize) { //每一个keyFrames[i]分配的是 (unsigned char) * FrameSize的大小,所以fread要读的每个数据项的字节数为1,可以表示每个像素点亮度范围0~255
39 sprintf(errorText, "Input sequence %s is not enough", fileName);
40 errorMsg(errorText);
41 }
42
43 //read u,v
44 fread(buf, 1, uvSize, fp);
45 }
46 free(buf);
47 fclose(fp);
48 }
49
50 void write_bmpheader(unsigned char *bitmap, int offset, int bytes, int value) {
51 int i;
52 for (i = 0; i < bytes; i++)
53 bitmap[offset + i] = (value >> (i << 3)) & 0xFF;
54 }
55
56 unsigned char *convertToBmp(unsigned char *inputImg, int width, int height, int *ouputSize) {
57
58 /*create a bmp format file*/
59 int bitmap_x = (int)ceil((double)width * 3 / 4) * 4;
60 unsigned char *bitmap = (unsigned char*)malloc(sizeof(unsigned char)*height*bitmap_x + 54);
61
62 bitmap[0] = 'B';
63 bitmap[1] = 'M';
64 write_bmpheader(bitmap, 2, 4, height*bitmap_x + 54); //whole file size
65 write_bmpheader(bitmap, 0xA, 4, 54); //offset before bitmap raw data
66 write_bmpheader(bitmap, 0xE, 4, 40); //length of bitmap info header
67 write_bmpheader(bitmap, 0x12, 4, width); //width
68 write_bmpheader(bitmap, 0x16, 4, height); //height
69 write_bmpheader(bitmap, 0x1A, 2, 1);
70 write_bmpheader(bitmap, 0x1C, 2, 24); //bit per pixel
71 write_bmpheader(bitmap, 0x1E, 4, 0); //compression
72 write_bmpheader(bitmap, 0x22, 4, height*bitmap_x); //size of bitmap raw data
73
74 for (int i = 0x26; i < 0x36; i++)
75 bitmap[i] = 0;
76
77 int k = 54;
78 for (int i = height - 1; i >= 0; i--) {
79 int j;
80 for (j = 0; j < width; j++) {
81 int index = i*width + j;
82 for (int l = 0; l < 3; l++)
83 bitmap[k++] = inputImg[index];
84 }
85 j *= 3;
86 while (j < bitmap_x) {
87 bitmap[k++] = 0;
88 j++;
89 }
90 }
91
92 *ouputSize = k;
93 return bitmap;
94 }
95
96 void saveToBmp(unsigned char *inputImg, int width, int height, char *outputFileName) {
97 int size;
98 unsigned char *bmp = convertToBmp(inputImg, width, height, &size);
99 FILE *fp = fopen(outputFileName, "wb+");
100 if (fp == NULL) {
101 sprintf(errorText, "Could not open file: %s", outputFileName);
102 errorMsg(errorText);
103
104 }
105 fwrite(bmp, 1, size, fp);
106 fclose(fp);
107 free(bmp);
108 }
109
110 int main() {
111 int width = 120, height = 120;
112
113 unsigned char **oriFrames;
114 oriFrames = (unsigned char**)malloc(sizeof(unsigned char*) * FrameNum);
115 for (int i = 0; i < FrameNum; i++) {
116 oriFrames[i] = (unsigned char*)malloc(sizeof(unsigned char) * FrameSize);
117 }
118
119 ////Test写入
120 //readSequence("E:\\Research\\YUV_Sequences\\2D\\BasketballPass_416x240_50\\BasketballPass_416x240_50.yuv", oriFrames);
121 //FILE *fp;
122 //fp = fopen("E:\\VS_Test_Code\\cnblogData.txt", "w");
123 //if (fp == NULL)
124 //{
125 // exit(0);
126 //}
127 //for (int i = 0; i < FrameNum; i++)
128 //{
129 // for (int j = 0; j < FrameSize; j++)
130 // {
131 // fprintf(fp, "%d,", oriFrames[i][j]);
132 // }
133 // fprintf(fp, "\n");
134 //}
135 ////Test写入
136
137 //Test读取
138 FILE *fp;
139 fp = fopen("E:\\VS_Test_Code\\cnblogData.txt", "r");
140 if (fp == NULL)
141 {
142 exit(0);
143 }
144 for (int i = 0; i < FrameNum; i++)
145 {
146 for (int j = 0; j < FrameSize; j++)
147 {
148 fscanf(fp, "%d,", &oriFrames[i][j]);//必须和fprintf格式保持一致
149 }
150 }
151 for (int i = 0; i < FrameNum; i++)
152 {
153 for (int j = 0; j < FrameSize; j++)
154 {
155 printf("%d ", oriFrames[i][j]);
156 }
157 printf("\n");
158 }
159 //Test读取
160
161 char imgName[30];
162 for (int i = 0; i < FrameNum; i++) {
163 sprintf(imgName, "F:\\pictures\\ReconsFrame%d.bmp", i);
164 //矩阵oriFrames[i]可以是任何你想保存为图片的像素矩阵,这里是yuv视频图像每一帧的像素数据
165 saveToBmp(oriFrames[i], width, height, imgName);
166 }
167 system("pause");
168 }
- View Code
3.从图片中导入的数据保存为bmp图片从图片中导入图像数据,将其存储为像素矩阵,像素值的范围是0-255,分别对应从黑色到白色,并将像素矩阵保存为bmp图片。代码如下所示:
1 #pragma warning(disable:4996)
2 #include<iostream>
3 #include<string>
4 using namespace std;
5
6 #define FrameSize 416*240 //视频帧大小
7 #define FrameNum 300 //yuv帧数
8 #define ET_SIZE 300
9 char errorText[ET_SIZE];
10
11 void errorMsg(const char *msg)
12 {
13 printf("error:%s\n", msg);
14 #ifdef _WIN32
15 system("pause");
16 #endif
17 exit(-1);
18
19 }
20
21 void readSequence(char *fileName, unsigned char **frames)
22 {
23 FILE *fp = fopen(fileName, "rb");
24 if (fp == NULL)
25 {
26 sprintf(errorText, "File %s doesn't exist\n", fileName);
27 errorMsg(errorText);
28 }
29 int uvSize = FrameSize / 2; //H.264编解码获得的关键帧都是彩色序列,这里主要是提取亮度分量Y。
30 unsigned char *buf = (unsigned char *)malloc(sizeof(unsigned char) * uvSize);
31 for (int i = 0; i < FrameNum; i++) {
32 //read y
33 if (fread(frames[i], 1, FrameSize, fp) != FrameSize) { //每一个keyFrames[i]分配的是 (unsigned char) * FrameSize的大小,所以fread要读的每个数据项的字节数为1,可以表示每个像素点亮度范围0~255
34 sprintf(errorText, "Input sequence %s is not enough", fileName);
35 errorMsg(errorText);
36 }
37 //read u,v
38 fread(buf, 1, uvSize, fp);
39 }
40 free(buf);
41 fclose(fp);
42 }
43
44
45
46 void write_bmpheader(unsigned char *bitmap, int offset, int bytes, int value)
47 {
48 int i;
49 for (i = 0; i < bytes; i++)
50 bitmap[offset + i] = (value >> (i << 3)) & 0xFF;
51 }
52
53 unsigned char *convertToBmp(unsigned char *inputImg, int width, int height, int *ouputSize)
54 {
55 /*create a bmp format file*/
56 int bitmap_x = (int)ceil((double)width * 3 / 4) * 4;
57 unsigned char *bitmap = (unsigned char*)malloc(sizeof(unsigned char)*height*bitmap_x + 54);
58
59 bitmap[0] = 'B';
60 bitmap[1] = 'M';
61 write_bmpheader(bitmap, 2, 4, height*bitmap_x + 54); //whole file size
62 write_bmpheader(bitmap, 0xA, 4, 54); //offset before bitmap raw data
63 write_bmpheader(bitmap, 0xE, 4, 40); //length of bitmap info header
64 write_bmpheader(bitmap, 0x12, 4, width); //width
65 write_bmpheader(bitmap, 0x16, 4, height); //height
66 write_bmpheader(bitmap, 0x1A, 2, 1);
67 write_bmpheader(bitmap, 0x1C, 2, 24); //bit per pixel
68 write_bmpheader(bitmap, 0x1E, 4, 0); //compression
69 write_bmpheader(bitmap, 0x22, 4, height*bitmap_x); //size of bitmap raw data
70
71 for (int i = 0x26; i < 0x36; i++)
72 bitmap[i] = 0;
73
74 int k = 54;
75 for (int i = height - 1; i >= 0; i--) {
76 int j;
77 for (j = 0; j < width; j++) {
78 int index = i*width + j;
79 for (int l = 0; l < 3; l++)
80 bitmap[k++] = inputImg[index];
81 }
82 j *= 3;
83 while (j < bitmap_x) {
84 bitmap[k++] = 0;
85 j++;
86 }
87 }
88
89 *ouputSize = k;
90 return bitmap;
91 }
92
93 void saveToBmp(unsigned char *inputImg, int width, int height, char *outputFileName)
94 {
95 int size;
96 unsigned char *bmp = convertToBmp(inputImg, width, height, &size);
97 FILE *fp = fopen(outputFileName, "wb+");
98 if (fp == NULL) {
99 sprintf(errorText, "Could not open file: %s", outputFileName);
100 errorMsg(errorText);
101
102 }
103 fwrite(bmp, 1, size, fp);
104 fclose(fp);
105 free(bmp);
106 }
107
108 int main()
109 {
110 int width = 416, height = 240;
111
112 unsigned char **oriFrames;
113 oriFrames = (unsigned char**)malloc(sizeof(unsigned char*) * FrameNum);
114 for (int i = 0; i < FrameNum; i++) {
115 oriFrames[i] = (unsigned char*)malloc(sizeof(unsigned char) * FrameSize);
116 }
117
118 //获取图像的数据
119 readSequence("E:\\Research\\YUV_Sequences\\2D\\BasketballPass_416x240_50\\BasketballPass_416x240_50.yuv", oriFrames);
120
121 char imgName[30];
122 for (int i = 0; i < 10 /*FrameNum*/; i++) {
123 sprintf(imgName, "F:\\pictures\\ReconsFrame%d.bmp", i);
124 //矩阵oriFrames[i]可以是任何你想保存为图片的像素矩阵,这里是yuv视频图像每一帧的像素数据
125 saveToBmp(oriFrames[i], width, height, imgName);
126 }
127 }
- View Code