zoukankan      html  css  js  c++  java
  • 纯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
      ", 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("
      ");
      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
      ", 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	%.2f
      ", 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
      ", 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
      ", 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, "
      ");
      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("
      ");
      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
      ", 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
      ", 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
  • 相关阅读:
    第一次作业
    第五次作业
    第三次作业
    第六次作业
    第二次作业
    scikitlearn学习 决策树
    [阅读]Think Python CH3 Functions
    [阅读]Think Python CH2 Variables, Expressions, and Statements
    [阅读]Think Python CH1 The Way of the Program
    Hive操作符和函数
  • 原文地址:https://www.cnblogs.com/ipersevere/p/12756048.html
Copyright © 2011-2022 走看看