这几天在忙着往appsboot下移植了lcd的驱动,想自己修改显示的图片,本想在网上搜一下转换程序的,但搜了一些都不好用,索性自己写了一个.
说明一下,rgb24的图片文件的格式是B,G,R,的,也就是说,一个像素,首先是一个字节的Blue,再是一个字节的Green,最后是一个字节的Red.然后因为rgb24的文件中没有颜色表选项,所以程序中把颜色表给省掉了.
为做成能在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程序了,好几个函数都不知道怎么用了,把相关几个函数的用法也顺便发一下:
1.
fread返回的不是字节数,当且仅当下面这么用的时候,返回值才是字节数
char buff[size];
FILE *fp;
...
fread(buff, 1, size, fp);
...
如果是: fread(buff, size, 1, fp)
返回1表示读取了size字节,返回0表示读取数量不够size字节,究竟是多少不知道!!-----------------确实是这样的!
fread 的作用是按定长记录读取文件,返回的是记录数。
from http://blog.csdn.net/jlnhyd/archive/2009/06/04/4242783.aspx
2.
void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。
3.bmp文件的格式和相关结构体可在这里找到:
http://blog.csdn.net/dawn81/archive/2006/02/09/595131.aspx
4.rgb24和rgb565的转换在这里可以找到:
http://blog.csdn.net/anufa/archive/2007/03/14/1529484.aspx
但转换时还是要详细了解清楚.
程序如下:
#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(真彩色)之一
int biCompression; // 位图压缩类型,必须是0(不压缩),1(BI_RLE8压缩类型)或2(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 & 0x1c)<<3) | tempBlue>>3;//RRRRRGGG,G little 3 bits
*(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 //运行testbmp程序,参数为android.bmp ,将输出的结果重定向到a.txt文件,打开a.txt文件,就可以看到所需要的数据