纯C++代码实现将像素矩阵保存为bmp图片

由于工作需要,时常需要将像素矩阵保存图片显示观看。为此,特地总结了三种使用纯C++代码生成bmp图片的方法。分别是使用自定义数据、从外界导入的txt和csv以及从图片中导入的数据。

  1. 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

     

  1. 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

     

  2. 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

     

  3. 4.参考文献

    https://blog.csdn.net/sinat_33718563/article/details/79424981
    https://blog.csdn.net/zzwtyds/article/details/75095698

 

posted @ 2020-04-22 21:29  只因有你pi  阅读(5376)  评论(0编辑  收藏  举报