catalogue
1, 24 bit bmp picture format features
2, Specific implementation ideas
1, 24 bit bmp picture format features
54 header bytes, 3 bytes for each pixel, BGR order, upside down storage, if the number of bytes occupied by the width of bmp picture cannot be divided by 4, the window system will fill each line with garbage, enough to divide by 4 bytes.
LCD: each pixel occupies 4 bytes, and the values of ARGB are listed respectively. A indicates transparency
The 54 byte header information is described in detail in another big man's blog. The following is a link: 24 bit picture features
2, Specific implementation ideas
Step 1: open the picture you want to display. It must be in bmp format. open()
Step 2: turn on the LCD driver of the development board. open("/dev/fb0")
Step 3: read the pixels of the picture and save them to buf. (after the value of the effective pixel is 54 bytes, use lseek() to move the cursor) read().
Part IV: write pixels to the LCD, which must correspond, otherwise the picture will be distorted.
Finally, turn off the image and LCD.
#include "myhead.h" int main(int argc,char **argv) { int i; int x,y; int bmpfd; int lcdfd; //Define the array to store the read color value char bmpbuf[800*480*3]; //BGR data //Define the array to store the ARGB data obtained by conversion int lcdbuf[800*480]; //Define a temporary array int tempbuf[800*480]; //Open the bmp picture to display bmpfd=open(argv[1],O_RDWR); if(bmpfd==-1) { perror("open bmp fail!\n"); return -1; } //Turn on the LCD driver lcdfd=open("/dev/fb0",O_RDWR); if(lcdfd==-1) { perror("open lcd fail!\n"); return -1; } //Skip 54 bytes of header information and read from 55 lseek(bmpfd,54,SEEK_SET); //Read from 55 bytes read(bmpfd,bmpbuf,800*480*3); //Convert 3 bytes of bmp data -- "into 4 bytes of ARGB data /* bmpbuf[0]-->R bmpbuf[1]-->G bmpbuf[2]-->B */ for(i=0; i<800*480; i++) //Ensure that each pixel can be converted lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i]; //(x,y) this point is exchanged with (x,479-y) lcdbuf[y*800+x] //Turn the picture upside down for(x=0; x<800; x++) for(y=0; y<480; y++) //lcdbuf[(479-y)*800+x]=lcdbuf[y*800+x]; // Error, you should not assign values to yourself tempbuf[(479-y)*800+x]=lcdbuf[y*800+x]; //Fill the converted ARGB data into the LCD screen write(lcdfd,tempbuf,800*480*4); //close close(bmpfd); close(lcdfd); return 0; }
Question 1:
write() is too inefficient and slow to display images.
reason:
Solution: #include < sys / MMAN. H >
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
Return value: the first address of the LCD screen is returned successfully
Failed NULL
Parameter: addr -- "is generally set to NULL, indicating that the operating system automatically allocates the first address of the hardware
length -- the address size of the LCD screen you want to map 800*480*4
prot -- access permission of memory area
PROT_READ // readable
PROT_WRITE // Writable
flags - "can your mapped address space be shared
MAP_SHARED Can share
MAP_PRIVATE Cannot share
fd -- file descriptor of the hardware device you want to map
Offset -- address offset, generally set to 0
Unmap
int munmap(void *addr, size_t length);
Parameter: addr -- "the first address you mapped before
length -- mapped memory size
Question 2:
How to display images of any size at any position
#include "myhead.h" int showbmp(int x,int y,char *bmpname); int main(int argc,char **argv) { int x = atoi(argv[2]);//atoi() converts a character type to an integer int y = atoi(argv[3]); showbmp(x,y,argv[1]); return 0; } int showbmp(int x,int y,char *bmpname) { int i,j,k=0; int w,h;//Width and height of the picture int bmpfd; int lcdfd; int headbuf[2]={0};//headbuf[0] width headbuf[1] height //Define the array to store the ARGB data obtained by conversion int lcdbuf[800*480]; //Open the bmp picture to display bmpfd=open(bmpname,O_RDWR); if(bmpfd==-1) { perror("open bmp fail!\n"); return -1; } //Turn on the LCD driver lcdfd=open("/dev/fb0",O_RDWR); if(lcdfd==-1) { perror("open lcd fail!\n"); return -1; } //The first address of lcd is mapped int *lcdmem=mmap(NULL,800*480*4, PROT_READ |PROT_WRITE,MAP_SHARED ,lcdfd,0 ); lseek(bmpfd,18,SEEK_SET); //Read header information read(bmpfd,headbuf,8); w=headbuf[0]; h=headbuf[1]; if(x+w>800||y+h>480 ) //Judge whether the image is within a reasonable range { perror("Picture out of range!\n"); return -1; } //Define the array to store the read color value char bmpbuf[w*h*3]; //BGR data //Define a temporary array int tempbuf[w*h]; //Skip 54 bytes of header information and read from 55 lseek(bmpfd,28,SEEK_CUR); if((3*w)%4==0) { read(bmpfd,bmpbuf,w*h*3); //Read from 55 bytes }else { for(int k=0;k<h;k++) { read(bmpfd,&bmpbuf[k*w*3],w*3); lseek(bmpfd,4-(3*w)%4,SEEK_CUR ); } } for(i=0; i<w*h; i++) //Ensure that each pixel can be converted lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i]; //Turn the picture upside down for(i=0; i<w; i++) for(int j=0; j<h; j++) tempbuf[(h-j)*w+i]=lcdbuf[j*w+i]; //Determine coordinates for(i=0;i<h;i++) for(int j=0;j<w;j++) { *(lcdmem+800*(i+y)+j+x)=tempbuf[k]; k++; } //close close(bmpfd); close(lcdfd); //Unmap munmap(lcdmem,800*480*3); return 0; }