zoukankan      html  css  js  c++  java
  • C++实现红外Fir谱图文件转BMP图片文件

    1、红外图谱文件由文件头和温度数据两部分组成,其中文件头 64 个字节,其余字节为温度数据。每个像素用两个字节表示温度(16 位有符号短整数),低字节在前,高字节在后,温度数据单位为 0.1℃,温度数据共 w× h× 2 字节。文件头定义 如下:

      从文件的25-26、27-28位可以获取谱图的高度和宽度,进而可以获取温度数据。

    2、BMP文件由

    • bmp文件头(bmp file header):共14字节;
    • 位图信息头(bitmap information):共40字节;
    • 调色板(color palette):可选;
    • 位图数据;
    • 结束符:共2个字节;

    为了便于理解,可用photoshop工具生成一个只有一个像素且为白色的bmp文件,用EditPlus等工具以16进制方式打开,内容如下:

    42 4D 3C 00 00 00 00 00   00 00 36 00 00 00 28 00

    00 00 01 00 00 00 01 00    00 00 01 00 18 00 00 00

    00 00 06 00 00 00 12 0B    00 00 12 0B 00 00 00 00

    00 00 00 00 00 00 FF FF   FF 00 00 00

    内容解释

    42 4D :BM字母
    3C 00 00 00 :整个文件大小 60
    00 00 00 00:保留,必须为0
    36 00 00 00 :从文件开始到位图数据开始之间的数据之间的偏移量 54

    28 00 00 00 :位图信息头的长度 40
    01 00 00 00 :以像素为单位说明图像的宽度
    01 00 00 00 :以像素为单位说明图像的高度,同时如果为正,说明位图倒立(即数据表示从图像的左下角到右上角),如果为负说明正向
    01 00 :为目标设备说明颜色平面数,总被设置为1
    18 00 :说明比特数/像素数,值有1、2、4、8、16、24、32 (x018=24)
    00 00 00 00 :说明图像的压缩类型,最常用的就是0(BI_RGB),表示不压缩
    06 00 00 00 :说明位图数据的大小,当用BI_RGB格式时,可以设置为0(6个字节)
    12 0B 00 00 :表示水平分辨率,单位是像素/米,有符号整数
    12 0B 00 00 :表示垂直分辨率,单位是像素/米,有符号整数
    00 00 00 00 :说明位图使用的调色板中的颜色索引数,为0说明使用所有
    00 00 00 00 :说明对图像显示有重要影响的颜色索引数,为0说明都重要

    FF FF FF 00 :位图数据,最后一个00为4字节对齐补0
    00 00

    这样就可以定义一个结构体表示一个BMP文件,定义如下:

    typedef struct _BMPFILE
    {
      //bmp文件头
      char bfType[2]; //文件类型0x4D42
      char bfSize[4]; //文件大小
      char bfReserved1[2]; //保留,必须设置为0
      char bfReserved2[2]; //保留,必须设置为0
      char bfOffBits[4]; //从头到位图数据的偏移54
      //位图信息头
      char biSize[4]; //位图信息头的长度 40
      char biWidth[4]; //以像素为单位说明图像的宽度
      char biHeight[4]; //以像素为单位说明图像的高度,同时如果为正,说明位图倒立(即数据表示从图像的左下角到右上角),如果为负说明正向
      char biPlanes[2]; //为目标设备说明颜色平面数,总被设置为1
      char biBitCount[2]; //说明比特数/像素数,值有1、2、4、8、16、24、32 (x018=24)
      char biCompression[4]; //说明图像的压缩类型,最常用的就是0(BI_RGB),表示不压缩
      char biSizeImages[4]; //说明位图数据的大小,当用BI_RGB格式时,可以设置为0(6个字节)
      char biXPelsPerMeter[4];//表示水平分辨率,单位是像素/米,有符号整数
      char biYPelsPerMeter[4];//表示垂直分辨率,单位是像素/米,有符号整数
      char biClrUsed[4]; //说明位图使用的调色板中的颜色索引数,为0说明使用所有
      char biClrImportant[4]; //说明对图像显示有重要影响的颜色索引数,为0说明都重要
      //位图数据
      char* biDataImage; //数据数组
      //结束标志
      char biFinish[2]; //结束标志

      _BMPFILE()
      {
        bfType[0] = 'B';
        bfType[1] = 'M';

        bfReserved1[0] = 0x00;
        bfReserved1[1] = 0x00;

        bfReserved2[0] = 0x00;
        bfReserved2[1] = 0x00;

        bfOffBits[0] = 0x36;
        bfOffBits[1] = 0x00;
        bfOffBits[2] = 0x00;
        bfOffBits[3] = 0x00;

        biSize[0] = 0x28;
        biSize[1] = 0x00;
        biSize[2] = 0x00;
        biSize[3] = 0x00;

        biPlanes[0] = 0x01;
        biPlanes[1] = 0x00;

        biBitCount[0] = 0x18;
        biBitCount[1] = 0x00;

        biCompression[0] = 0x00;
        biCompression[1] = 0x00;
        biCompression[2] = 0x00;
        biCompression[3] = 0x00;

        biSizeImages[0] = 0x00;
        biSizeImages[1] = 0x00;
        biSizeImages[2] = 0x00;
        biSizeImages[3] = 0x00;

        biXPelsPerMeter[0]= 0x12;
        biXPelsPerMeter[1]= 0x0B;
        biXPelsPerMeter[2]= 0x00;
        biXPelsPerMeter[3]= 0x00;

        biYPelsPerMeter[0]= 0x12;
        biYPelsPerMeter[1]= 0x0B;
        biYPelsPerMeter[2]= 0x00;
        biYPelsPerMeter[3]= 0x00;

        biClrUsed[0] = 0x00;
        biClrUsed[1] = 0x00;
        biClrUsed[2] = 0x00;
        biClrUsed[3] = 0x00;

        biClrImportant[0] = 0x00;
        biClrImportant[1] = 0x00;
        biClrImportant[2] = 0x00;
        biClrImportant[3] = 0x00;

        biFinish[0] = 0x00;
        biFinish[1] = 0x00;

        biDataImage = NULL;
      }
      _BMPFILE(int size,int width,int height,int datasize)
      {
        bfType[0] = 'B';
        bfType[1] = 'M';

        bfSize[0] = (size & 0x000000FF);
        bfSize[1] = (size & 0x0000FF00)>>8;
        bfSize[2] = (size & 0x00FF0000)>>16;
        bfSize[3] = (size & 0xFF000000)>>24;

        bfReserved1[0] = 0x00;
        bfReserved1[1] = 0x00;

        bfReserved2[0] = 0x00;
        bfReserved2[1] = 0x00;

        bfOffBits[0] = 0x36;
        bfOffBits[1] = 0x00;
        bfOffBits[2] = 0x00;
        bfOffBits[3] = 0x00;

        biSize[0] = 0x28;
        biSize[1] = 0x00;
        biSize[2] = 0x00;
        biSize[3] = 0x00;

        biWidth[0] = (width & 0x000000FF);
        biWidth[1] = (width & 0x0000FF00)>>8;
        biWidth[2] = (width & 0x00FF0000)>>16;
        biWidth[3] = (width & 0xFF000000)>>24;

        biHeight[0] = (height & 0x000000FF);
        biHeight[1] = (height & 0x0000FF00)>>8;
        biHeight[2] = (height & 0x00FF0000)>>16;
        biHeight[3] = (height & 0xFF000000)>>24;

        biPlanes[0] = 0x01;
        biPlanes[1] = 0x00;

        biBitCount[0] = 0x18;
        biBitCount[1] = 0x00;

        biCompression[0] = 0x00;
        biCompression[1] = 0x00;
        biCompression[2] = 0x00;
        biCompression[3] = 0x00;

        biSizeImages[0] = 0x00;
        biSizeImages[1] = 0x00;
        biSizeImages[2] = 0x00;
        biSizeImages[3] = 0x00;

        biXPelsPerMeter[0]= 0x12;
        biXPelsPerMeter[1]= 0x0B;
        biXPelsPerMeter[2]= 0x00;
        biXPelsPerMeter[3]= 0x00;

        biYPelsPerMeter[0]= 0x12;
        biYPelsPerMeter[1]= 0x0B;
        biYPelsPerMeter[2]= 0x00;
        biYPelsPerMeter[3]= 0x00;

        biClrUsed[0] = 0x00;
        biClrUsed[1] = 0x00;
        biClrUsed[2] = 0x00;
        biClrUsed[3] = 0x00;

        biClrImportant[0] = 0x00;
        biClrImportant[1] = 0x00;
        biClrImportant[2] = 0x00;
        biClrImportant[3] = 0x00;

        biFinish[0] = 0x00;
        biFinish[1] = 0x00;

        biDataImage = new char[datasize];
        memset(biDataImage,0,datasize);
      }
      ~_BMPFILE()
      {
      if(biDataImage != NULL)
      {
        delete biDataImage;
        biDataImage = NULL;
      }
    }

    }BMPFILE,*pBMPFILE;

    3、颜色与温度对照表

    struct BASECOLOR
    {
    uchar Blue;
    uchar Green;
    uchar Red;
    };

    struct BASECOLOR BaseColor[256] =
    {
    {0x5E,0x00,0x05},
    {0x60,0x01,0x07},
    {0x63,0x01,0x0A},
    {0x67,0x01,0x0E},
    {0x6A,0x01,0x11},
    {0x6B,0x01,0x13},
    {0x6E,0x01,0x16},
    {0x71,0x00,0x1A},
    {0x74,0x00,0x1D},
    {0x75,0x00,0x1F},
    {0x78,0x00,0x22},
    {0x7B,0x00,0x25},
    {0x7D,0x00,0x29},
    {0x7E,0x01,0x2B},
    {0x80,0x01,0x2F},
    {0x82,0x01,0x32},
    {0x84,0x01,0x35},
    {0x85,0x01,0x38},
    {0x87,0x01,0x3B},
    {0x89,0x01,0x3E},
    {0x8A,0x01,0x42},
    {0x8C,0x01,0x46},
    {0x8C,0x01,0x47},
    {0x8D,0x01,0x4B},
    {0x8E,0x00,0x4E},
    {0x8F,0x00,0x51},
    {0x90,0x00,0x53},
    {0x91,0x00,0x56},
    {0x92,0x00,0x59},
    {0x93,0x00,0x5C},
    {0x93,0x00,0x5E},
    {0x95,0x00,0x60},
    {0x95,0x00,0x64},
    {0x96,0x00,0x67},
    {0x96,0x00,0x68},
    {0x97,0x00,0x6B},
    {0x97,0x00,0x6D},
    {0x98,0x01,0x70},
    {0x99,0x01,0x73},
    {0x99,0x01,0x74},
    {0x99,0x01,0x77},
    {0x9A,0x01,0x79},
    {0x9A,0x01,0x7C},
    {0x9A,0x01,0x7D},
    {0x9A,0x01,0x80},
    {0x9B,0x01,0x83},
    {0x9B,0x01,0x85},
    {0x9B,0x01,0x87},
    {0x9B,0x01,0x8A},
    {0x9B,0x00,0x8D},
    {0x9B,0x00,0x8F},
    {0x9B,0x00,0x91},
    {0x9B,0x00,0x94},
    {0x9B,0x00,0x97},
    {0x9B,0x00,0x9A},
    {0x9B,0x00,0x9D},
    {0x9B,0x00,0x9F},
    {0x9A,0x00,0xA2},
    {0x9A,0x00,0xA4},
    {0x9A,0x00,0xA7},
    {0x9A,0x00,0xA8},
    {0x99,0x00,0xAB},
    {0x99,0x01,0xAE},
    {0x99,0x01,0xB0},
    {0x98,0x01,0xB1},
    {0x98,0x02,0xB3},
    {0x97,0x02,0xB5},
    {0x96,0x02,0xB7},
    {0x96,0x03,0xB8},
    {0x95,0x03,0xB9},
    {0x95,0x04,0xBB},
    {0x93,0x05,0xBD},
    {0x92,0x06,0xBF},
    {0x92,0x06,0xBF},
    {0x91,0x07,0xC1},
    {0x8F,0x08,0xC3},
    {0x8E,0x09,0xC4},
    {0x8E,0x09,0xC5},
    {0x8C,0x0A,0xC6},
    {0x8A,0x0B,0xC8},
    {0x89,0x0D,0xC9},
    {0x88,0x0D,0xCA},
    {0x86,0x0E,0xCB},
    {0x84,0x0F,0xCD},
    {0x81,0x11,0xCE},
    {0x80,0x11,0xCE},
    {0x7D,0x13,0xD0},
    {0x7A,0x14,0xD1},
    {0x77,0x16,0xD2},
    {0x75,0x16,0xD2},
    {0x72,0x17,0xD3},
    {0x6F,0x19,0xD4},
    {0x6B,0x1B,0xD5},
    {0x67,0x1C,0xD6},
    {0x66,0x1D,0xD6},
    {0x62,0x1F,0xD7},
    {0x5E,0x20,0xD8},
    {0x5A,0x22,0xD9},
    {0x59,0x23,0xD9},
    {0x55,0x25,0xDA},
    {0x51,0x27,0xDB},
    {0x4D,0x29,0xDB},
    {0x4B,0x2A,0xDC},
    {0x48,0x2C,0xDD},
    {0x45,0x2E,0xDD},
    {0x41,0x30,0xDE},
    {0x40,0x31,0xDE},
    {0x3C,0x33,0xDF},
    {0x39,0x35,0xDF},
    {0x36,0x38,0xE0},
    {0x33,0x39,0xE1},
    {0x31,0x3A,0xE1},
    {0x2F,0x3D,0xE2},
    {0x2C,0x3E,0xE3},
    {0x29,0x41,0xE3},
    {0x28,0x41,0xE4},
    {0x25,0x44,0xE5},
    {0x23,0x45,0xE5},
    {0x21,0x47,0xE6},
    {0x1F,0x48,0xE6},
    {0x1D,0x4A,0xE7},
    {0x1B,0x4B,0xE8},
    {0x19,0x4D,0xE8},
    {0x18,0x4E,0xE9},
    {0x16,0x50,0xEA},
    {0x13,0x52,0xEA},
    {0x12,0x54,0xEB},
    {0x10,0x56,0xEC},
    {0x0F,0x57,0xEC},
    {0x0D,0x59,0xEC},
    {0x0B,0x5B,0xED},
    {0x0A,0x5C,0xEE},
    {0x09,0x5E,0xEE},
    {0x08,0x5F,0xEF},
    {0x07,0x61,0xEF},
    {0x06,0x63,0xF0},
    {0x05,0x64,0xF0},
    {0x05,0x66,0xF0},
    {0x03,0x67,0xF1},
    {0x03,0x69,0xF2},
    {0x02,0x6A,0xF2},
    {0x02,0x6C,0xF2},
    {0x01,0x6D,0xF3},
    {0x01,0x6F,0xF3},
    {0x01,0x71,0xF3},
    {0x01,0x72,0xF4},
    {0x00,0x74,0xF4},
    {0x00,0x76,0xF4},
    {0x00,0x78,0xF5},
    {0x00,0x79,0xF5},
    {0x00,0x7B,0xF6},
    {0x00,0x7D,0xF6},
    {0x00,0x7E,0xF6},
    {0x00,0x80,0xF7},
    {0x00,0x81,0xF7},
    {0x00,0x84,0xF7},
    {0x00,0x85,0xF8},
    {0x00,0x86,0xF8},
    {0x00,0x88,0xF8},
    {0x01,0x8A,0xF8},
    {0x01,0x8D,0xF9},
    {0x01,0x8E,0xF9},
    {0x01,0x8F,0xF9},
    {0x01,0x91,0xFA},
    {0x01,0x93,0xFA},
    {0x01,0x95,0xFA},
    {0x01,0x96,0xFA},
    {0x01,0x99,0xFA},
    {0x01,0x9A,0xFB},
    {0x01,0x9D,0xFB},
    {0x00,0x9D,0xFB},
    {0x00,0x9F,0xFB},
    {0x00,0xA1,0xFC},
    {0x00,0xA3,0xFC},
    {0x00,0xA4,0xFC},
    {0x00,0xA6,0xFC},
    {0x00,0xA8,0xFD},
    {0x00,0xAA,0xFD},
    {0x00,0xAB,0xFD},
    {0x00,0xAD,0xFD},
    {0x00,0xAF,0xFE},
    {0x00,0xB1,0xFE},
    {0x00,0xB3,0xFE},
    {0x01,0xB4,0xFF},
    {0x01,0xB6,0xFF},
    {0x01,0xB8,0xFF},
    {0x01,0xBA,0xFF},
    {0x01,0xBB,0xFF},
    {0x01,0xBD,0xFF},
    {0x01,0xBF,0xFF},
    {0x02,0xC1,0xFF},
    {0x02,0xC2,0xFF},
    {0x02,0xC4,0xFF},
    {0x03,0xC5,0xFF},
    {0x03,0xC7,0xFE},
    {0x03,0xC8,0xFE},
    {0x05,0xCA,0xFE},
    {0x05,0xCC,0xFE},
    {0x06,0xCD,0xFE},
    {0x07,0xCE,0xFE},
    {0x08,0xD0,0xFE},
    {0x0A,0xD1,0xFE},
    {0x0B,0xD2,0xFE},
    {0x0D,0xD4,0xFE},
    {0x0E,0xD5,0xFE},
    {0x10,0xD6,0xFE},
    {0x12,0xD7,0xFE},
    {0x15,0xD9,0xFF},
    {0x16,0xDA,0xFF},
    {0x1A,0xDB,0xFF},
    {0x1D,0xDD,0xFF},
    {0x20,0xDE,0xFF},
    {0x23,0xDF,0xFF},
    {0x27,0xE1,0xFF},
    {0x2B,0xE2,0xFF},
    {0x30,0xE3,0xFF},
    {0x35,0xE5,0xFF},
    {0x37,0xE6,0xFF},
    {0x3D,0xE7,0xFF},
    {0x42,0xE9,0xFF},
    {0x48,0xEA,0xFF},
    {0x4B,0xEB,0xFF},
    {0x51,0xEC,0xFF},
    {0x57,0xEE,0xFF},
    {0x5E,0xEF,0xFF},
    {0x61,0xF0,0xFF},
    {0x68,0xF1,0xFF},
    {0x6F,0xF2,0xFF},
    {0x75,0xF3,0xFF},
    {0x79,0xF3,0xFF},
    {0x80,0xF4,0xFF},
    {0x86,0xF4,0xFF},
    {0x8D,0xF4,0xFF},
    {0x93,0xF4,0xFF},
    {0x96,0xF4,0xFF},
    {0x9D,0xF4,0xFF},
    {0xA3,0xF5,0xFF},
    {0xA9,0xF6,0xFF},
    {0xAC,0xF6,0xFF},
    {0xB2,0xF7,0xFF},
    {0xB7,0xF7,0xFF},
    {0xBC,0xF8,0xFF},
    {0xBF,0xF8,0xFF},
    {0xC4,0xFA,0xFF},
    {0xC8,0xFA,0xFF},
    {0xCC,0xFB,0xFF},
    {0xCD,0xFC,0xFF},
    {0xD1,0xFC,0xFF},
    {0xD4,0xFD,0xFF},
    {0xD6,0xFE,0xFF},
    {0xD7,0xFF,0xFF},
    {0xD8,0xFF,0xFF},
    {0xD9,0xFF,0xFF},
    {0xD9,0xFF,0xFF},
    {0xFF,0xFF,0xFF},
    {0xFF,0xFF,0xFF}
    };

    4、代码实现

    QFile firfile(firfileName);
    if(firfile.exists() && firfile.open(QIODevice::ReadOnly))
    {
      QByteArray bytearray = firfile.readAll();

      if(bytearray.size() < 28) continue;

      ushort height = (uchar)bytearray[25]*256 + (uchar)bytearray[24];//图像高度
      ushort width = (uchar)bytearray[27]*256 + (uchar)bytearray[26];//图像宽度

      if(bytearray.size() < 64+2*height*width) continue;

      //计划最大最小值
      int max = (uchar)bytearray[65]*256 + (uchar)bytearray[64];
      int min = (uchar)bytearray[65]*256 + (uchar)bytearray[64];
      for(int row=0;row<height;row++)
      {
        for(int col=0;col<width;col++)
        {
          int index = 64 + 2*(row*width + col);
          int value = (uchar)bytearray[index+1]*256 + (uchar)bytearray[index];

          if(value > max) max = value;
          if(value < min) min = value;
        }
      }

      uint colSize = 4 * (24*width)/32 + (24*width%32 > 0 ? 4 : 0); //一行有多少字节(4字节对齐)
      uint biSize = colSize * height; //数据区总共字节
      uint bfSize = 14 + 40 + biSize + 2; //图像总共字节

      BMPFILE bmpFile(bfSize,width,height,biSize);

      //图片BGR赋值
      for(int i=0,row=height-1;row>=0;row--)
      {
        for(int col=0;col<width;col++)
        {
          int index = 64 + 2*(row*width + col);
          int value = (uchar)bytearray[index+1]*256 + (uchar)bytearray[index];
          int bgrIndex = (int)(256 * (value-min+1) / (max-min+1));

          bmpFile.biDataImage[i++] = BaseColor[bgrIndex].Blue;
          bmpFile.biDataImage[i++] = BaseColor[bgrIndex].Green;
          bmpFile.biDataImage[i++] = BaseColor[bgrIndex].Red;
        }
        //非4字节对齐时补0
        for(uint col=3*width;col<colSize;col++)
        {
          bmpFile.biDataImage[i++] = 0x00;
        }
      }

      //写bmp文件
      QString bmpfileName = firfileName.replace(".fir",".bmp");
      QFile bmpfile(bmpfileName);
      if(bmpfile.open(QIODevice::WriteOnly))
      {
        bmpfile.write(bmpFile.bfType, 2);
        bmpfile.write(bmpFile.bfSize, 4);
        bmpfile.write(bmpFile.bfReserved1, 2);
        bmpfile.write(bmpFile.bfReserved2, 2);
        bmpfile.write(bmpFile.bfOffBits, 4);
        bmpfile.write(bmpFile.biSize, 4);
        bmpfile.write(bmpFile.biWidth, 4);
        bmpfile.write(bmpFile.biHeight, 4);
        bmpfile.write(bmpFile.biPlanes, 2);
        bmpfile.write(bmpFile.biBitCount, 2);
        bmpfile.write(bmpFile.biCompression, 4);
        bmpfile.write(bmpFile.biSizeImages, 4);
        bmpfile.write(bmpFile.biXPelsPerMeter,4);
        bmpfile.write(bmpFile.biYPelsPerMeter,4);
        bmpfile.write(bmpFile.biClrUsed, 4);
        bmpfile.write(bmpFile.biClrImportant, 4);
        bmpfile.write(bmpFile.biDataImage,biSize);
        bmpfile.write(bmpFile.biFinish, 2);

        bmpfile.close();
      }

      firfile.close();

    }

     

  • 相关阅读:
    Linux命令比较文件内容
    Linux命令jobs小记
    权限控制框架
    Log4j2源码分析系列:(一)配置加载
    Callable和Supplier的区别
    排序算法之归并排序
    Spring boot整合Mybatis
    排序算法之堆排序
    排序算法之希尔排序
    排序算法之快速排序
  • 原文地址:https://www.cnblogs.com/zhangnianyong/p/15505481.html
Copyright © 2011-2022 走看看