jpg圖片在開發板上顯示


文件IO項目:
在開發板屏幕上循環顯示目錄里的圖片
a.按照一定的間隔循環顯示目錄里的bmp圖片
b.實現手指滑動來顯示目錄里的圖片(bmp,jpg)上一張,下一張


d1:
1.能操控屏幕(查詢開發板屏幕分辨率,以及每個像素點占幾個字節)
命令:FBIOGET_VSCREENINFO
查詢結果保存在些結構中:
struct fb_var_screeninfo fbinfo;
__u32 xres; 屏幕分辨率
__u32 yres;
__u32 bits_per_pixel; 每個像素點占多少位 /* guess what */

ioctl(fd,FBIOGET_VSCREENINFO,&fbinfo);
1.control device
控制設備

int ioctl(int fd, int request, ...);
fd:文件描述符,表示要操作的設備
request:一般表示一個命令號,該命令由驅動開發者提供
...:其它參數,不同的命令參數是不一樣的,也由驅動程序員提供

返回值:返回0
失敗-1
------------------------------------------------
2.功能:映射一個文件或設備到內存,實現像操作普通內存一樣去操作文件或設備
void *mmap(
void *addr, 把文件內容映射到內存哪個地址,給NULL,讓操作系統自動分配
size_t length,要映射的文件內容的長度
int prot, 映射的內存區域的權限
PROT_EXEC 可執行
PROT_READ 可讀
PROT_WRITE 可寫
int flags,映射標志,決定對映射部分的操作是否對其它進程可見
MAP_SHARED:共享的,對其它進程可見,內存操作直接應用到文件中去
MAP_PRIVATE:私有的,對其它進程不可見,內存操作不應用到文件中去

int fd,文件描述符,要映射的文件
off_t offset 偏移量,表示文件從哪個位置開始映射
);

返回值:成功返回映射內存區域的首地址
失敗返回 MAP_FAILED(-1),同時errno被設置


int munmap(void *addr, size_t length);
功能:解除映射
addr:mmap的返回值
length:映射內存的長度

返回值:成功返回0
失敗返回-1




void *memset(void *s, int c, size_t n);
s:要設置的內存首地址
c:要設置的內容
n:長度

//struct student s;
//memset(&s,0,sizeof(s));
//void *memcpy(void *dest, const void *src, size_t n);

memcpy(addr,gImage_cat2,800*480*4);


2.顯示圖片



-----------------------------------------
Linux Frame Buffer:
幀緩沖設備:
是對具體圖像硬件的一個抽像,它讓上層圖像應用程序不必關心具體的硬件實現細節。
在內存(顯存)中開辟一段空間,用來保存在屏幕上像素點的顏色值,然后操作屏幕就直接操作這段內存就可以了,這就是說的幀緩沖。

LCD顯示原理:
屏幕是由y行且每行x個像素點的矩陣組成
在屏幕上顯示圖像就是給每個像素點顯示一個顏色。

幀緩沖設備操作流程:
1.open打開設備
2.ioctl獲取屏幕信息
3.mmap映射設備到內存
4.操作顯存
5.munmap解除映射
6.close關閉文件

 

 

 

 

1.顯示jpg圖片
libjpeg移植:
1.解壓
tar xvf jpegsrc.v8a.tar.gz
2.cd jpeg-8a/
3.配置參數(生成Makefile)
./configure --host=arm-linux --target=arm-linux --prefix=/usr/local/libjpeg-8a CC=arm-linux-gcc
(
注:
如果沒有建立交叉編譯工具軟鏈接的同學請用這個
CC=arm-none-linux-gnueabi-gcc
)

4.make
5.sudo make install
注:
sudo make install時可能出現以下錯誤
./libtool: line 950: arm-linux-ranlib: command not found
解決方法:
sudo -s
export PATH=$PATH:/usr/local/arm/arm-2009q3/bin
重新執行以下命令
make install

 

6.把生成庫文件打包下載到開發板
cd /usr/local/libjpeg-8a
tar zcvf libjpeg-8a.tar.gz lib/

7.在開發板上解壓剛下載的包
tar xvf libjpeg-8a.tar.gz
cd lib/
cp libjpeg.* /lib/


arm-linux-gcc test_jpeg.c -o test_jpeg2
-ljpeg //指定鏈接的庫名
-I /usr/local/libjpeg-8a/include/ //指定頭文件存放路徑
-L /usr/local/libjpeg-8a/lib/ //指定庫文件存放路徑



-------------------------
tftp用法:
1.烏班圖下啟動服務

sudo service tftpd-hpa restart
[sudo] password for csgec:
tftpd-hpa stop/waiting
tftpd-hpa start/running, process 15716

2.tftp -g -r filename 主機IP
(timeout)
如果超時,請檢查網絡是否暢通
從主機ping開發板
從開發板ping主機
檢查開發板和主機是否在同一網段
如果是筆記本,把無線網卡先斷開

--------------------------------------
輸入事件:
鼠標事件
鍵盤事件
觸屏事件
...
#include <linux/input.h>
一般觸屏分為是否按下,用壓力值來區分,當壓力值為0時表示沒按下
觸屏事件使用的是絕對坐標(包括x和y)
struct input_event {
struct timeval time;//該事件發生的時間
__u16 type;//事件類型
EV_KEY 0x01 鍵盤事件
EV_REL 0x02 鼠標事件
EV_ABS 0x03 觸摸事件

__u16 code;//根據事件類型同,含義不同
if type == EV_KEY
code 為鍵盤的鍵值
if type = EV_REL
code 為坐標軸 REL_X REL_Y
if type = EV_ABS
code 為坐標軸 ABS_X ABS_Y ABS_PRESSURE(壓力)
__s32 value;//根據事件類型同,含義不同
if type == EV_KEY
value 1 / 0 表示按鍵up/down
if type = EV_REL
value表示相應的坐標軸的偏移
if type = EV_ABS
value表示相應的坐標軸的絕對坐標
X:(1-800)
Y:(1-480)
壓力值:200 或 0(表示沒按下)

};

#define ABS_PRESSURE 0x18//表示壓力值

獲取起點和終點
起點:按下去就可獲取
終點:當壓力值為0時,也就是松開時的那個坐標值
終點-起點 > 50

 

 

 

#include<stdio.h>
#include<linux/input.h>
#include<fcntl.h>

int main(int argc,char **argv)
{

int fd = open("/dev/event0",O_RDONLY);
if(fd < 0)
{
perror("open");
return -1;
}
struct input_event ev;
int r;
while(1)
{
r = read(fd,&ev,sizeof(ev));
if(r == sizeof(ev))
{
printf("type = %x,code = %x,value = %x\n",ev.type,ev.code,ev.value);
}
/*
if(ev.type == EV_ABS && ev.code == ABS_PRESSURE)
{
printf("value = %d\n",ev.value);
}

if(ev.type == EV_ABS && ev.code == ABS_X)
{

printf("value = %d\n",ev.value);

}
*/

 

}
return 0;
}

 

 

 

 

/*************************************************************************
> File Name: test_jpeg.c
> Author: csgec
> Mail: longer.zhou@gmail.com
> Created Time: Thu 04 Aug 2016 10:57:30 AM CST
************************************************************************/

#include<stdio.h>
#include<jpeglib.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<stdlib.h>

void lcdDraw_point(int *p,int x,int y,int color)
{
*(p + 800*y + x) = color;
}

int main(int argc,char ** argv)
{
//1
int fb = open("/dev/fb0",O_RDWR);
if(fb < 0)
{
perror("open");
return -1;
}

//2
void *addr = mmap(0,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
if(addr == MAP_FAILED)
{
perror("mmap");
return -1;
}

//-----------利用libjpeg解壓jpeg文件的步驟--------------------------------
//1.分配並初始化一個jpeg解壓對象
printf("start jpeg\n");
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);

//2.指定要解壓的文件
FILE *infile;
infile = fopen(argv[1],"r");
if(infile == NULL)
{
fprintf(stderr, "can't open %s\n", argv[1]);
return -1;
}
jpeg_stdio_src(&cinfo, infile);

//3.獲取圖片信息
jpeg_read_header(&cinfo, TRUE);

//4.啟動解壓過程,cinfo中下面幾個成員會比較有用
//cinfo.output_width 寬_
//cinfo.output_height 高
//cinfo.output_components 像素分量(一個像素點占幾個字節)
//cinfo.
jpeg_start_decompress(&cinfo);

//5.讀取一行掃描線數據並處理,通常的代碼是這樣的
//成功后buffer里保存的就是解壓后的行像素點的數據
//R G B 從上到下,從左到右
unsigned char *buffer = malloc(cinfo.output_width * cinfo.output_components);
printf("start scanline\n");
while(cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo,
&buffer,//保存解壓后的數據的二級指針
1//掃描的行數
);
int x,color;
unsigned char r,g,b;
unsigned char *p = buffer;
for(x = 0; x < 800; x++)
{
r = *p++;
g = *p++;
b = *p++;

color = (r << 16) | (g << 8) | b;
lcdDraw_point(addr,x,cinfo.output_scanline-1,color);
// int y = cinfo.output_scanline-1;
// int *pf = (int*)addr;
// *(pf + 800*y + x) = color;
}

}
printf("finish decompress\n");
//6.完成解壓過程
jpeg_finish_decompress(&cinfo);
//7.釋放資源
jpeg_destroy_decompress(&cinfo);
fclose(infile);
close(fb);

return 0;

}

 

 

/*************************************************************************
> File Name: test_jpeg.c
> Author: csgec
> Mail: longer.zhou@gmail.com
> Created Time: Thu 04 Aug 2016 10:57:30 AM CST
************************************************************************/

#include<stdio.h>
#include<jpeglib.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<stdlib.h>

void draw_point(int *p,int x,int y,int color)
{
int *pf = p + (800*y + x);
*pf = color;

}
int main(int argc,char ** argv)
{
//1
int fb = open("/dev/fb0",O_RDWR);
if(fb < 0)
{
perror("open");
return -1;
}

//2
void *addr = mmap(0,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
if(addr == MAP_FAILED)
{
perror("mmap");
return -1;
}

//-----------利用libjpeg解壓jpeg文件的步驟--------------------------------
//1.分配並初始化一個jpeg解壓對象
printf("start jpeg\n");
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);

//2.指定要解壓的文件
FILE *infile;
infile = fopen(argv[1],"r");
if(infile == NULL)
{
fprintf(stderr, "can't open %s\n", argv[1]);
return -1;
}
jpeg_stdio_src(&cinfo, infile);

//3.獲取圖片信息
jpeg_read_header(&cinfo, TRUE);

//4.啟動解壓過程,cinfo中下面幾個成員會比較有用
//cinfo.output_width 寬_
//cinfo.output_height 高
//cinfo.output_components 像素分量(一個像素點占幾個字節)
//cinfo.
jpeg_start_decompress(&cinfo);

//5.讀取一行掃描線數據並處理,通常的代碼是這樣的
//成功后buffer里保存的就是解壓后的行像素點的數據
//R G B 從上到下,從左到右
unsigned char *buffer = malloc(cinfo.output_width * cinfo.output_components);
printf("start scanline\n");
while(cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo,
&buffer,//保存解壓后的數據的二級指針
1//掃描的行數
);
int x,color;
unsigned char r,g,b;
unsigned char *p = buffer;
for(x = 0; x < 800; x++)
{
r = *p++;
g = *p++;
b = *p++;

color = (r << 16) | (g << 8) | b;
draw_point(addr,x,cinfo.output_scanline-1,color);
/*
int y = cinfo.output_scanline-1;
int *pf = (int*)addr;
*(pf + 800*y + x) = color;
*/
}

}
printf("finish decompress\n");
//6.完成解壓過程
jpeg_finish_decompress(&cinfo);
//7.釋放資源
jpeg_destroy_decompress(&cinfo);
fclose(infile);
close(fb);

return 0;

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM