解題的關鍵在於 顯示圖片的雙重for迴圈條件與目標位置的結合,且該程式輸入的坐標值為圖片左上角像素點坐標 ...
目錄
LCD屏顯示圖片習題
題目
解析
該題的顯著要求有兩個,一是任意位置,二是任意大小。為滿足這兩個要求得先讀取並記錄bmp數據,且bmp文件屬於普通文件,所以選擇標準IO函數fopen()打開bmp,並用結構體變數進行記錄;然後為了提升用戶使用體驗,即bmp在顯示時不會出現黑線,對LCD屏進行記憶體映射,最後使用獲取到的x1和y1作為迴圈條件,完成任意大小的bmp在任意位置顯示。
代碼完整展示
/*******************************************************************
*
* file name: ShowBmp.c
* author : [email protected]
* date : 2024/05/13
* function : 該案例是掌握LCD屏顯示圖片的基本原理
* note : None
*
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*
* *****************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
//取消位元組對齊
#pragma pack(1)
// 定義BMP文件頭部結構
typedef struct{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
}BITMAPFILEHEADER;
typedef struct{
unsigned int biSize;
int biWidth; //寬
int biHeight; //高
unsigned short biPlanes;
unsigned short biBitCount; //色深
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}BITMAPINFOHEADER;
//恢復位元組對齊
#pragma pack()
/********************************************************************
*
* name : ShowBmp
* function : 實現任意圖片大小在任意位置進行顯示
* argument :
* @fname :需要顯示的圖片文件路徑
@x1 :圖片顯示位置的橫坐標
@y1 :圖片顯示位置的橫坐標
*
* retval : 調用成功返回0,否則返回-1;
* author : [email protected]
* date : 2024/05/13
* note : none
*
* *****************************************************************/
int ShowBmp(const char *fname,int x1,int y1)
{
//1.打開待顯示的BMP圖像 fopen
FILE * bmp_fp = fopen(fname,"rb");
if (NULL == bmp_fp)
{
return -1;
}
//2.讀取BMP文件的圖像信息,獲取BMP的寬和高
BITMAPINFOHEADER headerinfo;
BITMAPFILEHEADER fileinfo;
fseek(bmp_fp,14,SEEK_SET);
fread(&headerinfo,1,40,bmp_fp); //讀取40位元組
printf("bmp width = %d,height = %d\n",headerinfo.biWidth,headerinfo.biHeight);
//3.讀取BMP圖片的顏色分量 800*480*3
char *bmp_buf= calloc(1,3*(headerinfo.biWidth)*(headerinfo.biHeight));
fread(bmp_buf,1,3*(headerinfo.biWidth)*(headerinfo.biHeight),bmp_fp);
//4.關閉BMP
fclose(bmp_fp);
//5.打開LCD open
int lcd_fd = open("/dev/fb0",O_RDWR);
//6.對LCD進行記憶體映射 mmap
int * lcd_mp = (int *)mmap(NULL,4*800*480,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
//7.迴圈的把BMP圖像的顏色分量依次寫入到LCD的像素點中
int i = 0;
int data = 0;
//設置圖片位置的關鍵在於迴圈條件,且要註意映射時需要從圖片最後一行開始
for (int y = 480 - (480 - headerinfo.biHeight - y1) - 1; y >= y1; y--)
{
for (int x = x1; x < headerinfo.biWidth + x1; ++x)
{
//把BMP圖片的一個像素點的顏色分量轉換為LCD屏幕的一個像素點的顏色分量格式 ARGB <--- BGR
data |= bmp_buf[i]; //B
data |= bmp_buf[i+1]<<8; //G
data |= bmp_buf[i+2]<<16; //R
lcd_mp[800*y + x] = data; //BGR BGR BGR ....
i+=3;
data = 0;
}
}
//8.關閉LCD
close(lcd_fd);
munmap(lcd_mp,800*480*4);
return 0;
}
int main(int argc, char const *argv[])
{
int x1 = 0, y1 = 0;
//獲取用戶想要的圖片顯示位置
printf("Please input x1 = \n");
scanf("%d", &x1);
printf("Please input y1 = \n");
scanf("%d", &y1);
//調用顯示函數
ShowBmp(argv[1],x1,y1);
return 0;
}