C++: Convert text file of integers into a bitmap image file in BMP format

后端 未结 5 2145
我在风中等你
我在风中等你 2020-12-09 13:29

I have a text file being saved by a matrix library containing a 2D matrix as such:

1 0 0 
6 0 4
0 1 1

Where each number is represented with

5条回答
  •  孤街浪徒
    2020-12-09 13:48

    I've rewritten and commented the answer from https://stackoverflow.com/a/2654860/586784. I hope you find it clear enough.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    ///Just a tiny struct to bundle three values in range [0-255].
    struct Color{
      Color(unsigned char red, unsigned char green, unsigned char blue)
        : red(red),green(green),blue(blue)
      {}
    
      ///Defualt constructed Color() is black.
      Color()
        : red(0),green(0),blue(0)
      {}
    
      ///Each color is represented by a combination of red, green, and blue.
      unsigned char red,green,blue;
    };
    
    
    int main(int argc,char**argv)
    {
    
      ///The width of the image. Replace with your own.
      std::size_t w = 7;
      ///The height of the image. Replace with your own
      std::size_t h = 8;
    
      ///http://arma.sourceforge.net/docs.html#Mat
      ///The Armadillo Linear Algebra Library Mat constructor is of the following
      /// signature: mat(n_rows, n_cols).
      arma::Mat intmatrix(h,w);
    
      ///Fill out matrix, replace this with your own.
      {
    
        ///Zero fill matrix
        for(std::size_t i=0; i int2color;
    
      ///Fill out the color associations. Replace this with your own associations.
      {
        ///When we see 0 in the matrix, we will use this color (red-ish).
        int2color[0] = Color(255,0,0);
        ///When we see 0 in the matrix, we will use this color (green-ish).
        int2color[1] = Color(0,255,0);
        ///When we see 0 in the matrix, we will use this color (blue-ish).
        int2color[4] = Color(0,0,255);
        ///When we see 0 in the matrix, we will use this color (grey-ish).
        int2color[6] = Color(60,60,60);
      }
    
    
      ///The file size will consist of w*h pixels, each pixel will have an RGB,
      /// where each color R,G,B is 1 byte, making the data part of the file to
      /// be of size 3*w*h. In addition there is a header to the file which will
      /// take of 54 bytes as we will see.
      std::size_t filesize = 54 + 3*w*h;
    
    
      ///We make an array of 14 bytes to represent one part of the header.
      ///It is filled out with some default values, and we will fill in the
      ///rest momentarily.
      unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0};
    
      ///The second part of the header is 40 bytes; again we fill it with some
      ///default values, and will fill in the rest soon.
      unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0};
    
    
    
      ///We will now store the filesize,w,h into the header.
      ///We can't just write them to the file directly, because different platforms
      ///encode their integers in different ways. This is called "endianness"
      ///or "byte order". So we chop our integers up into bytes, and put them into
      ///the header byte-by-byte in the way we need to.
    
    
      ///Encode the least significant 8 bits of filesize into this byte.
      ///Because sizeof(unsigned char) is one byte, and one byte is eight bits,
      ///when filesize is casted to (unsigned char) only the least significant
      ///8 bits are kept and stored into the byte.
      bmpfileheader[ 2] = (unsigned char)(filesize    );
      ///... Now we shift filesize to the right 1 byte, meaning and trunctate
      ///that to its least significant 8 bits. This gets stored in the next
      ///byte.
      bmpfileheader[ 3] = (unsigned char)(filesize>> 8);
      ///...
      bmpfileheader[ 4] = (unsigned char)(filesize>>16);
      ///Encodes the most significant 8 bits of filesize into this byte.
      bmpfileheader[ 5] = (unsigned char)(filesize>>24);
    
      ///Now we will store w (the width of the image) in the same way,
      /// but into the byte [5-8] in bmpinfoheader.
      bmpinfoheader[ 4] = (unsigned char)(       w    );
      bmpinfoheader[ 5] = (unsigned char)(       w>> 8);
      bmpinfoheader[ 6] = (unsigned char)(       w>>16);
      bmpinfoheader[ 7] = (unsigned char)(       w>>24);
    
    
    
      ///Now we will store h (the width of the image) in the same way,
      /// but into the byte [9-12] in bmpinfoheader.
      bmpinfoheader[ 8] = (unsigned char)(       h    );
      bmpinfoheader[ 9] = (unsigned char)(       h>> 8);
      bmpinfoheader[10] = (unsigned char)(       h>>16);
      bmpinfoheader[11] = (unsigned char)(       h>>24);
    
      ///Now we open the output file
      FILE* f = fopen("img.bmp","wb");
    
      ///First write the bmpfileheader to the file. It is 14 bytes.
      ///The 1 means we are writing 14 elements of size 1.
      ///Remember, bmpfileheader is an array which is basically
      ///the same thing as saying it is a pointer to the first element
      ///in an array of contiguous elements. We can thus say:
      ///write 14 bytes, starting from the spot where bmpfileheader points
      ///to.
      fwrite(bmpfileheader,1,14,f);
      ///Then write the bmpinfoheader, which is 40 bytes, in the same way.
      fwrite(bmpinfoheader,1,40,f);
    
      ///Now we write the data.
      ///For each row (there are h rows), starting from the last, going
      ///up to the first.
      ///We iterate through the rows in reverse order here,
      ///apparently in the BMP format, the image
      ///is stored upside down.
      for(std::size_t i=h-1; i != std::size_t(-1); --i)
      {
        ///For each column in the row,
        for(std::size_t j=0; j

提交回复
热议问题