由于工作需要,时常需要将像素矩阵保存图片显示观看。为此,特地总结了三种使用纯C++代码生成bmp图片的方法。分别是使用自定义数据、从外界导入的txt和csv以及从图片中导入的数据。
-
自定义数据可以是使用公式生成,或者是根据自己需求自己定义的数据,范围为0-255,分别对应从黑色到白色。代码生成过程如下:View Code
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 }