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

0x4C43 2015-01-20 05:33:53
这是我在网上找的代码
#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;
}


图像转换结果是这样的


有个疑问: fread(rgb_buffer,2,nData,p); 读取的pic.txt文件中数据是二进制的还是十六进制?
...全文
1548 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
0x4C43 2015-01-21
  • 打赏
  • 举报
回复
引用 2 楼 fly_dragon_fly 的回复:
看起来象行4字节没对齐
那得怎么改呢?
0x4C43 2015-01-21
  • 打赏
  • 举报
回复
引用 3 楼 likfeng 的回复:
可能pic.txt的内容不对吧 BMP图像的内容肯定不是用文本表示的 这个pic.txt有嫌疑
我是把单片机读取的RGB565数据先存进pic.txt文件的,但我不知道fread(rgb_buffer,2,nData,p); 读取数据时的格式应该怎样
0x4C43 2015-01-21
  • 打赏
  • 举报
回复
引用 6 楼 likfeng 的回复:
[quote=引用 4 楼 swjtu100 的回复:] [quote=引用 3 楼 likfeng 的回复:] 可能pic.txt的内容不对吧 BMP图像的内容肯定不是用文本表示的 这个pic.txt有嫌疑
我是把单片机读取的RGB565数据先存进pic.txt文件的,但我不知道fread(rgb_buffer,2,nData,p); 读取数据时的格式应该怎样[/quote] fread读出来的是16进制! 存储到pic.txt时的时候是不是存储的16进制? 高低位没有反吧?[/quote]
引用 6 楼 likfeng 的回复:
[quote=引用 4 楼 swjtu100 的回复:] [quote=引用 3 楼 likfeng 的回复:] 可能pic.txt的内容不对吧 BMP图像的内容肯定不是用文本表示的 这个pic.txt有嫌疑
我是把单片机读取的RGB565数据先存进pic.txt文件的,但我不知道fread(rgb_buffer,2,nData,p); 读取数据时的格式应该怎样[/quote] fread读出来的是16进制! 存储到pic.txt时的时候是不是存储的16进制? 高低位没有反吧?[/quote] pic.txt存的就是16进制的数据,高低位也没反,可就是不行
likfeng 2015-01-21
  • 打赏
  • 举报
回复
引用 4 楼 swjtu100 的回复:
[quote=引用 3 楼 likfeng 的回复:] 可能pic.txt的内容不对吧 BMP图像的内容肯定不是用文本表示的 这个pic.txt有嫌疑
我是把单片机读取的RGB565数据先存进pic.txt文件的,但我不知道fread(rgb_buffer,2,nData,p); 读取数据时的格式应该怎样[/quote] fread读出来的是16进制! 存储到pic.txt时的时候是不是存储的16进制? 高低位没有反吧?
赵4老师 2015-01-21
  • 打赏
  • 举报
回复
推荐使用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);
}
0x4C43 2015-01-21
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
上帖第4行:fwrite(rgb_buffer+y*3*nWidth,1,fp1); 应改为:fwrite(rgb_buffer+y*3*nWidth,3*nWidth,1,fp1);
谢谢指导,不过还是不行
赵4老师 2015-01-21
  • 打赏
  • 举报
回复
上帖第4行:fwrite(rgb_buffer+y*3*nWidth,1,fp1); 应改为:fwrite(rgb_buffer+y*3*nWidth,3*nWidth,1,fp1);
赵4老师 2015-01-21
  • 打赏
  • 举报
回复
第134行:
fwrite(rgb_buffer,3*nWidth*nHeight,1,fp1);
需要改为
int y,bytes,i;
bytes=4-(3*nWidth%4);if (bytes==4) bytes=0;
for (y=0;y<nHeight;y++) {
 fwrite(rgb_buffer+y*3*nWidth,1,fp1);
 for (i=0;i<bytes;i++) fputc(0,fp1);
}
赵4老师 2015-01-21
  • 打赏
  • 举报
回复
引用 2 楼 fly_dragon_fly 的回复:
看起来象行4字节没对齐
英雄所见略同。
likfeng 2015-01-20
  • 打赏
  • 举报
回复
可能pic.txt的内容不对吧 BMP图像的内容肯定不是用文本表示的 这个pic.txt有嫌疑
fly_dragon_fly 2015-01-20
  • 打赏
  • 举报
回复
看起来象行4字节没对齐

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧