/*
All Rights Reserved
Author:fanping.deng@gmail.com
Function: convert RGB565 to BMP
Build by g++
*/
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
typedef short WORD;
typedef int DWORD;
typedef int LONG;
typedef char BYTE;
//BITMAP File Header info
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
}__attribute__((packed)) BITMAPFILEHEADER;
//Bitmap info header
typedef struct tagBITMAPINFOHEADER{ // bmih
DWORD biSize;
LONG biWidth; //以像素为单位的图像宽度
LONG biHeight;// 以像素为单位的图像长度
WORD biPlanes;
WORD biBitCount;// 每个像素的位数
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
}__attribute__((packed)) BITMAPINFOHEADER;
typedef struct tagPaletteRGB
{
BYTE b;
BYTE g;
BYTE r;
BYTE reserved;
}__attribute__((packed)) paletteRGB;
int g_len = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//+sizeof(paletteRGB);
void initBMPHeader(BITMAPFILEHEADER* pBmpFileHeader)
{
pBmpFileHeader->bfType = 0X4D42; //Magic number
pBmpFileHeader->bfSize = g_len + 320*480*3; //320*480, screen size, hardcoded. You should change it for different size
pBmpFileHeader->bfReserved1 = 0X00;
pBmpFileHeader->bfReserved2 = 0X00;
pBmpFileHeader->bfOffBits = g_len;
}
void initBMPInfoHeader(BITMAPINFOHEADER* pBmpInfoHeader)
{
pBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
pBmpInfoHeader->biWidth = 320 ;//这个地方写死了,因为当时测试手机的屏幕就是这个尺寸的
pBmpInfoHeader->biHeight= 480;
pBmpInfoHeader->biPlanes=1;
pBmpInfoHeader->biBitCount=24;
pBmpInfoHeader->biCompression=0;
pBmpInfoHeader->biSizeImage=320*480*3;
pBmpInfoHeader->biXPelsPerMeter = pBmpInfoHeader->biYPelsPerMeter = 0;
pBmpInfoHeader->biClrUsed = pBmpInfoHeader->biClrImportant = 0;
}
void convetBmp(int fs,int fd, short* pSrcShortBuffer,char *pDstIntBUffer);
int main(int argc,char* argv[])
{
if(argc < 3)
{
printf("error use bmpgenerator,we need the source path");
return -1;
}
BITMAPFILEHEADER bmpFileHeader;
initBMPHeader(&bmpFileHeader);
BITMAPINFOHEADER bmpInfoHeader;
initBMPInfoHeader(&bmpInfoHeader);
paletteRGB bmpPalette;
memset(&bmpPalette,0,sizeof(paletteRGB));
int fd = open(argv[1],O_CREAT|O_WRONLY);
if(fd == -1)
{
printf("fail to create dst file %s\n",argv[1]);
exit(-1);
}
int fs = open(argv[2],O_RDONLY);
if(fs == -1)
{
printf("fail to open src file %s\n",argv[2]);
exit(-1);
}
//Write head info to the destination file
//注意:转换后BMP的数据格式是RGB888,所以不需要palette信息。关于BMP的信息可以搜索一下
write(fd,&bmpFileHeader,sizeof(BITMAPFILEHEADER));
write(fd,&bmpInfoHeader,sizeof(BITMAPINFOHEADER));
//write(fd,&bmpPalette,sizeof(paletteRGB));
//320*480
//按行来算
char* pDstIntBUffer = new char[3*320];
memset(pDstIntBUffer,0,sizeof(char)*320);
short* pSrcShortBuffer = new short[320];
memset(pSrcShortBuffer,0,sizeof(short)*320);
convetBmp(fs,fd,pSrcShortBuffer,pDstIntBUffer);
close(fd);
close(fs);
delete[] pSrcShortBuffer;
delete[] pDstIntBUffer;
printf("bmp generated\n");
return 0;
}
void convetBmp(int fs,int fd, short* pSrcShortBuffer,char *pDstIntBUffer)
{
int height = 480;
int srcLineLength = sizeof(short)*320;
int dstLienLength = sizeof(char)*3*320;
while(height > 0)
{
lseek(fs,(height-1)*srcLineLength,SEEK_SET);
read(fs,(char*)pSrcShortBuffer,srcLineLength);
for(int x = 0; x < 320; x++)
{
short srcPixel = *(pSrcShortBuffer+x); //first change RGB565 to RGB888
char srcR = (srcPixel&0xF800)>>11;
char srcG = (srcPixel&0x07E0)>>5;
char srcB = srcPixel&0x001F;
pDstIntBUffer[x*3 + 0] = srcB;
pDstIntBUffer[x*3 + 1] = srcG;
pDstIntBUffer[x*3 + 2] = srcR;
pDstIntBUffer[x*3 + 0] <<= 3;
pDstIntBUffer[x*3 + 1] <<= 2;
pDstIntBUffer[x*3 + 2] <<= 3;
// pDstIntBUffer[x*3 + 0] |= (srcB&0X07);
// pDstIntBUffer[x*3 + 1] |= (srcG&0X03);
// pDstIntBUffer[x*3 + 2] |= (srcR&0X07);
}
write(fd,(char*)pDstIntBUffer,dstLienLength);
--height;
}
}