如何把从单片机采集的RGB565数据转换成BMP格式的图像

怎么把从单片机采集的RGB565数据转换成BMP格式的图像
本帖最后由 swjtu100 于 2015-01-20 17:34:59 编辑
这是我在网上找的代码
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef unsigned char  BYTE;
typedef unsigned short WORD;
// BMP图像各部分说明如下
/***********
    第一部分    位图文件头
该结构的长度是固定的,为14个字节,各个域的依次如下:
    2byte   :文件类型,必须是0x4d42,即字符串"BM"。
    4byte   :整个文件大小
    4byte   :保留字,为0
    4byte   :从文件头到实际的位图图像数据的偏移字节数。
*************/
typedef struct
{    long imageSize;
    long blank;
    long startPosition;
}BmpHead;
/*********************
/*********************
第二部分    位图信息头
该结构的长度也是固定的,为40个字节,各个域的依次说明如下:
    4byte   :本结构的长度,值为40
    4byte   :图像的宽度是多少象素。
    4byte   :图像的高度是多少象素。
    2Byte   :必须是1。
    2Byte   :表示颜色时用到的位数,常用的值为1(黑白二色图)、4(16色图)、8(256色图)、24(真彩色图)。
    4byte   :指定位图是否压缩,有效值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS。Windows位图可采用RLE4和RLE8的压缩格式,BI_RGB表示不压缩。
    4byte   :指定实际的位图图像数据占用的字节数,可用以下的公式计算出来:
     图像数据 = Width' * Height * 表示每个象素颜色占用的byte数(即颜色位数/8,24bit图为3,256色为1)
     要注意的是:上述公式中的biWidth'必须是4的整数倍(不是biWidth,而是大于或等于biWidth的最小4的整数倍)。
     如果biCompression为BI_RGB,则该项可能为0。
    4byte   :目标设备的水平分辨率。
    4byte   :目标设备的垂直分辨率。
    4byte   :本图像实际用到的颜色数,如果该值为0,则用到的颜色数为2的(颜色位数)次幂,如颜色位数为8,2^8=256,即256色的位图
    4byte   :指定本图像中重要的颜色数,如果该值为0,则认为所有的颜色都是重要的。
***********************************/
typedef struct

{
    long    Length;
    long    width;
    long    height;
    WORD    colorPlane;
    WORD    bitColor;
    long    zipFormat;
    long    realSize;
    long    xPels;
    long    yPels;
    long    colorUse;
    long    colorImportant;
  /*  void show()

    {     
        printf("infoHead Length:%dn",Length);
        printf("width&height:%d*%dn",width,height); 
        printf("colorPlane:%dn",colorPlane);
        printf("bitColor:%dn",bitColor);
        printf("Compression Format:%dn",zipFormat);
        printf("Image Real Size:%dn",realSize);
        printf("Pels(X,Y):(%d,%d)n",xPels,yPels);
        printf("colorUse:%dn",colorUse);     
        printf("Important Color:%dn",colorImportant);
    }*/
}InfoHead;
/***************************
/***************************
    第三部分    调色盘结构  颜色表
    对于256色BMP位图,颜色位数为8,需要2^8 = 256个调色盘;
    对于24bitBMP位图,各象素RGB值直接保存在图像数据区,不需要调色盘,不存在调色盘区
    rgbBlue:   该颜色的蓝色分量。
    rgbGreen:  该颜色的绿色分量。
    rgbRed:    该颜色的红色分量。
    rgbReserved:保留值。
************************/
typedef struct
{         BYTE   rgbBlue;
         BYTE   rgbGreen;
         BYTE   rgbRed;
         BYTE   rgbReserved;
      /*   void show(void)
         {
            printf("Mix Plate B,G,R:%d %d %dn",rgbBlue,rgbGreen,rgbRed);
         }*/
}RGBMixPlate;
/****************************
      RGB加上头部信息转换成BMP
      参数說明:
      rgb_buffer        :RGB数据文件中的信息
      nData             :RGB数据的长度
      nWidth            :图像宽度的像素数
      nHeight           :图像高度的像素数
      fp1               :所存放的文件
*****************************/
int RGB2BMP(unsigned char *rgb_buffer,int nWidth,int nHeight,FILE*fp1)
{
     BmpHead m_BMPHeader;        
     char bfType[2]={'B','M'};
     m_BMPHeader.imageSize=3*nWidth*nHeight+54;
     m_BMPHeader.blank=0;
     m_BMPHeader.startPosition=54;

     fwrite(bfType,1,sizeof(bfType),fp1);
     fwrite(&m_BMPHeader.imageSize,1,sizeof(m_BMPHeader.imageSize),fp1);
     fwrite(&m_BMPHeader.blank,1,sizeof(m_BMPHeader.blank),fp1);
     fwrite(&m_BMPHeader.startPosition,1,sizeof(m_BMPHeader.startPosition),fp1);

     InfoHead  m_BMPInfoHeader;
     m_BMPInfoHeader.Length=40; 
     m_BMPInfoHeader.width=nWidth;
     m_BMPInfoHeader.height=nHeight;
     m_BMPInfoHeader.colorPlane=1;
     m_BMPInfoHeader.bitColor=24;
     m_BMPInfoHeader.zipFormat=0;
     m_BMPInfoHeader.realSize=3*nWidth*nHeight;
     m_BMPInfoHeader.xPels=0;
     m_BMPInfoHeader.yPels=0;
     m_BMPInfoHeader.colorUse=0;
     m_BMPInfoHeader.colorImportant=0;

     fwrite(&m_BMPInfoHeader.Length,1,sizeof(m_BMPInfoHeader.Length),fp1);
     fwrite(&m_BMPInfoHeader.width,1,sizeof(m_BMPInfoHeader.width),fp1);
     fwrite(&m_BMPInfoHeader.height,1,sizeof(m_BMPInfoHeader.height),fp1);
     fwrite(&m_BMPInfoHeader.colorPlane,1,sizeof(m_BMPInfoHeader.colorPlane),fp1);
     fwrite(&m_BMPInfoHeader.bitColor,1,sizeof(m_BMPInfoHeader.bitColor),fp1);
     fwrite(&m_BMPInfoHeader.zipFormat,1,sizeof(m_BMPInfoHeader.zipFormat),fp1);
     fwrite(&m_BMPInfoHeader.realSize,1,sizeof(m_BMPInfoHeader.realSize),fp1);
     fwrite(&m_BMPInfoHeader.xPels,1,sizeof(m_BMPInfoHeader.xPels),fp1);
     fwrite(&m_BMPInfoHeader.yPels,1,sizeof(m_BMPInfoHeader.yPels),fp1);
     fwrite(&m_BMPInfoHeader.colorUse,1,sizeof(m_BMPInfoHeader.colorUse),fp1);
     fwrite(&m_BMPInfoHeader.colorImportant,1,sizeof(m_BMPInfoHeader.colorImportant),fp1);
     fwrite(rgb_buffer,3*nWidth*nHeight,1,fp1);
     return 0;
}

int  main()
{    FILE* p;
/***************  input data  ***********
    filename      :RGB数据文件名称
    nWidth        :所生成文件的水平像素
    nHeight       :所生成文件的垂直像素
    newFile       :最终生成文件的名称
***********************************************/
    char* filename = "pic.txt";
    int nWidth = 320;
    int nHeight = 240;
    char* newFile = "pic.bmp";
    p = fopen(filename,"rb");
    if (p == NULL)
    {
        printf("!!!file %s open failed.n", filename);
        return 0;
    }
    printf("file %s ope n success.n",filename);
/***********  read Image Data  **************/     
    long nData = nWidth*nHeight;
    unsigned short* rgb_buffer = (unsigned short*)malloc(nData*sizeof(short));    
    fread(rgb_buffer,2,nData,p);
    long total = nWidth*nHeight*3;
    unsigned char* pVisit =   (unsigned char*)malloc(total*sizeof(char));
unsigned char * tmp= pVisit;

    long i =0;
    unsigned char R,G,B;
    while(i<nData)
    {
R = *rgb_buffer&0x1f;
G = (*rgb_buffer>>5)&0x3f;
B = (*rgb_buffer>>11)&0x1f;
B = B<<3;
G = G<<2;
R = R<<3;
      *pVisit=R;pVisit++;
      *pVisit=G;pVisit++;
      *pVisit=B;pVisit++;
      rgb_buffer++;
      i++;  
     }
    printf("read file over.nData%ldn",nData);
/*****************************************************/
/***********  write file *******************/
    FILE *result = fopen(newFile,"wb");
    if (result == NULL)
    {
       printf("open new file failed.n");
       return -1;
    }
RGB2BMP(tmp,nWidth,nHeight,result);
    fclose(result);
    return 0;
}


图像转换结果是这样的
如何把从单片机采集的RGB565数据转换成BMP格式的图像

有个疑问:    fread(rgb_buffer,2,nData,p); 读取的pic.txt文件中数据是二进制的还是十六进制?
------解决思路----------------------
可能pic.txt的内容不对吧
BMP图像的内容肯定不是用文本表示的
这个pic.txt有嫌疑
------解决思路----------------------
推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址;
人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

#include <stdio.h>
#include <string.h>
#include <conio.h>
FILE *fi,*fo;
int r;
unsigned int n,c;
long offset;
//-------------------------------------------------------
void main(int argc,char *argv[])
{
    if (argc<3) {
        cprintf("Hex2Bin srcfile desfile");
        return;
    }
    if ((fi=fopen(argv[1],"rb"))==NULL) {
        cprintf("Can not find file %s",argv[1]);
        return;
    }
    if ((fo=fopen(argv[2],"wb"))==NULL) {
        fclose(fi);
        cprintf("Can not create file %s",argv[2]);
        return;
    }
    n=0;
    while (1) {
        offset=ftell(fi);
        r=fscanf(fi,"%2x",&c);
        if (EOF==r) break;//
        if (1==r) {
            fputc(c,fo);
            n++;
        } else {//0==r
            fseek(fi,offset,SEEK_SET);//因为VC6的Release版及其VC7,8,9,10,...版的fscanf未按约定保持offset不变,所以此处必须恢复offset
            r=fgetc(fi);
            if (EOF==r) break;//
        }
    }
    fcloseall();
    cprintf("OK to Hex2Bin %d bytes.",n);
}