linux 下将rgb24转化为rgb565的格式
最近正在致力于将LCD驱动迁移到appsboot环境中,并希望自行调整显示效果。原本打算在网络上查找相关转换程序,结果发现这些工具均不理想,于是决定自行编写相应的代码。
解释一下,在RGB24图片文件中所使用的格式是按照B、G、R三个子通道来组织数据的具体方式。具体来说,在每个像素中首先存储的是一个字节代表蓝色通道(Blue),接着是一个字节代表绿色通道(Green),最后是一个字节代表红色通道(Red)。由于RGB24文件中并未包含颜色表选项(Color Table),因此程序在处理时无需加载额外的颜色映射信息而直接省去了这一部分。
为做成能在appsboot中显示的数据,也要了解一下appsboot中的565的格式
格式如下:
第一个字节:G2,G1,G0,B4,B3,B2,B1,B0,
第二个字节:R4,R3,R2,R1,R0,G5,G4,G3,
如果这个字节的顺序不对,显示的效果会很差的.
我的主要目标是通过程序读取一个bmp24位的文件,并生成一个新的文件,该文件包含RGB565格式的数据。
0xff0xd6,0x780xb5,0x530xac,0xd10x6a,0x670x51,0xa3,
0xff0xd6,0x780xb5,0x530xac,0xd10x6a,0x670x51,0xa3
0xff0xd6,0x780xb5,0x530xac,0xd10x6a,0x670x51,0xa3
像这样的数据就可以直接放在appsboot中的数组中用来显示了.
以下是关于C语言编程的指导信息:由于长时间未进行C语言编程操作,我对这些相关函数的具体使用方法已经有些生疏,请您耐心指教。
fread返回的不是字节数,当且仅当下面这么用的时候,返回值才是字节数
char buff[size];
FILE *fp;
...
fread(buff, 1, size, fp);
...
如果是: fread(buff, size, 1, fp)
返回1表示读取了size字节,返回0表示读取数量不够size字节,究竟是多少不知道!!-----------------确实是这样的!
fread 的作用是按定长记录读取文件,返回的是记录数。
from <>
此函数malloc接收一个长整型参数NumBytes并返回一个空针(NULL),若成功则返回所分配的空间指针;若出现错误则返回空指针。
3.bmp文件的格式和相关结构体可在这里找到:
<>
4.rgb24和rgb565的转换在这里可以找到:
<>
但转换时还是要详细了解清楚.
程序如下:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
//#define DEBUG
//for 24 bit bmp data ,there is no RGBQUAD,so do not do it.
typedef struct
{
short int bfType; /* should"BM" (0x4D42)*/
int bfSize; /* file size */
short int bfReserved1; /* reserved 0 */
short int bfReserved2;
int bfOffBits; /* reserved 0*/
}attribute((packed)) BITMAPFILEHEADER;
typedef struct { // 长度40字节
int biSize; // 本结构所占用字节数,长度40字节
int biWidth; // 位图的宽度,以像素为单位
int biHeight; // 位图的高度,以像素为单位
short biPlanes; // 目标设备的级别,必须为1
short biBitCount; // 每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
该变量为整型类型,并表示位图压缩方式。该值必须属于以下类别:0表示无压缩操作;1代表基于运行长度编码(RLE)的生物数据压缩算法(BI-RLE8);2代表基于运行长度编码(RLE)的生物数据压缩算法(BI-RLE4)。该值仅能取这三个整数值之一。
int biSizeImage; // 位图的大小,以字节为单位
int biXPelsPerMeter; // 位图水平分辨率,每米像素数
int biYPelsPerMeter; // 位图垂直分辨率,每米像素数
int biClrUsed; // 位图实际使用的颜色表中的颜色数
int biClrImportant; // 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
BITMAPFILEHEADER FileHead={0};
BITMAPINFOHEADER InfoHead={0};
unsigned char *ImgData;
unsigned char *NewImgData;
int main ( int argc, char *argv[] )
{
char bmpfile[10]={0};
FILE *fp;
int rc;
int i=0;
strcpy(bmpfile,argv[1]);
fp = fopen( bmpfile, "rb" );
if (fp == NULL)
{
printf("open file %s error/n",bmpfile);
return( -1 );
}
rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp );
if ( rc != 1)
{
printf("read header error!/n");
fclose( fp );
return( -2 );
}
#ifdef DEBUG
printf("--------------------------BITMAPFILEHEADER---------/n");
printf("/tbftype=/t0x%x/n",FileHead.bfType);
printf("/tbfSize=/t%d/n",FileHead.bfSize);
printf("/tbfOffBits=/t%d/n",FileHead.bfOffBits);
#endif
rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
if ( rc != 1)
{
printf("read infoheader error!/n");
fclose( fp );
return( -4 );
}
#ifdef DEBUG
printf("--------------------------BITMAPINFOHEADER---------/n");
printf("/tbiSize=/t%d/n",InfoHead.biSize);
printf("/tbiWidth=/t%d/n",InfoHead.biWidth);
printf("/tbiHeight=/t%d/n",InfoHead.biHeight);
printf("/tbiPlanes=/t%d/n",InfoHead.biPlanes);
printf("/tbiBitCount=/t%d/n",InfoHead.biBitCount);
printf("/tbiCompression=/t%d/n",InfoHead.biCompression);
printf("/tbiSizeImage=/t%d/n",InfoHead.biSizeImage);
printf("/tbiXPelsPerMeter=/t%d/n",InfoHead.biXPelsPerMeter);
printf("/tbiYPelsPerMeter=/t%d/n",InfoHead.biYPelsPerMeter);
printf("/tbiClrUsed=/t%d/n",InfoHead.biClrUsed);
printf("/tbiClrImportant=/t%d/n",InfoHead.biClrImportant);
#endif
int ImgSize=InfoHead.biSizeImage;
#ifdef DEBUG
printf("/tImgSize=/t%d/n",ImgSize);
#endif
ImgData=(unsigned char *)malloc(ImgSize);
if(!ImgData)
{
printf("alloc data error/n");
fclose(fp);
return (-1);
}
rc = fread( ImgData, ImgSize,1, fp );
if ( rc !=1)
{
printf("read img data error,rc=%d!/n",rc);
fclose( fp );
return( -4 );
}
#ifdef DEBUG
while(i< ImgSize)
{
printf("%x ",ImgData[i++]);
if( !(i%32)) printf("/n");
}
#endif
int NewImgSize=InfoHead.biWidth * InfoHead.biHeight * 2;
NewImgData=(unsigned char *)malloc(NewImgSize);
if(!NewImgData)
{
printf("alloc NewImgSize data error/n");
fclose(fp);
return (-1);
}
i=0;
unsigned char * tempNewData=NewImgData;
unsigned char tempRed;
unsigned char tempGreen;
unsigned char tempBlue;
//unsigned short tempRGB;
while(i<ImgSize)
{
tempBlue =0xF8 & ImgData[i];//big 5 bits
tempGreen =0xFC & ImgData[i+1];//big 6 bits
tempRed =0xF8 & ImgData[i+2];//bit 5 bits
//tempRGB =tempRed<<8 | tempGreen<<3 | tempBlue>>3 ;
*(tempNewData++) = (unsigned char)((((tempGreen & 28)小写字母)<< 3) | (tempBlue >> 3));//红色通道使用5位、绿色通道使用6位、蓝色通道使用5位
*(tempNewData++)=tempRed | (tempGreen>>5); //GGGBBBBB,G big 3 bits
#ifdef tt
printf("R=%d,G=%d,B=%d,/ttempRed=%d,tempGreen=%d,tempBlue=%d,data1=%d,data2=%d/
/n",ImgData[i],ImgData[i+1],ImgData[i+2],tempRed,tempGreen,tempBlue,
(tempBlue | (tempGreen >>5 )),((unsigned char)(tempGreen<<3) | (tempRed>>3)));
#endif
i+=3;
}
i=0;
/*
while(i<NewImgSize)
{
printf("0x%02x,",NewImgData[i++]);
if( !(i%32)) printf("/n");
}
printf("/n");
printf("/n");
*/
int j;
在RGB文件中存储的数据位置与显示器中的位置是倒置的关系。为了确保正常显示图像,请按照指示将RGB数据重新排列。
for(j=InfoHead.biHeight-1;j>=0;j--)
{
for(i=0;i<InfoHead.biWidth;i++)
{
if(!(i %16)) printf("/n");
int index=(j*InfoHead.biWidth + i)*2;
printf("0x%02x,0x%02x,",NewImgData[index],NewImgData[index+1]);
}
}
printf("/n");
fclose( fp );
}
运行的结果直接输出到终端终了,如果需要将输出的结果放到文件中去,
可以用重定向写到文件中,我就是这么搞的,
gcc -o testbmp testbmp.c //生成testbmp可执行的文件
执行testbmp程序,并将android.bmp作为参数传递给该程序。其输出结果将被重定向到a.txt文件中。打开a.txt后即可查看所需数据
