分类: LINUX
2009-04-29 10:39:18
这学期开学以来都在忙一个电表项目的前期准备工作,几乎没有搞linux了,最近又重新拾了起来,但是现在又要打止了,因为电表又要开始搞了,所以这几天我会陆续将最近搞的一点小东西发上来,希望对大家能有所帮助,也希望大家多提提意见。
在9261EK上的framebuffer上显示jpeg图片
1、 首先安装jpeg库,在此不在赘述。注意一定要把库放到交叉编译器的正确位置,否则就要用-l参数指定库的路径。
2、 如下程序将图片显示到farmebuffer上,因为9261的lcd控制器是基于BGR555标准的,因此需要先将RGB888转换为BGR555,才能在framebuffer上显示
3、 交叉编译
arm-none-linux-gnueabi-gcc -o displaypic displaypic.c –ljpeg
将编译好的displaypic下载到开发板,将分辨率小于240*320图片也下载到开发板,如下即可将pic.jpg显示到LCD上。
./ displaypic pic.jpg
4、 以下程序是根据网上的一篇《Linux控制台下显示JPEG图像》中的程序改编的。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FB_DEV "/dev/fb0"
/***************** function declaration ******************/
void usage(char *msg);
unsigned short RGB888toRGB555(unsigned char red,
unsigned char green, unsigned char blue);
int fb_open(char *fb_device);
int fb_close(int fd);
int fb_stat(int fd, int *width, int *height, int *depth);
void *fb_mmap(int fd, unsigned int screensize);
int fb_munmap(void *start, size_t length);
int fb_pixel(void *fbmem, int width, int height,
int x, int y, unsigned short color);
/************ function implementation ********************/
int
main(int argc, char *argv[])
{
/*
* declaration for jpeg decompression
*/
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *infile;
unsigned char *buffer;
/*
* declaration for framebuffer device
*/
int fbdev;
char *fb_device;
unsigned char *fbmem;
unsigned int screensize;
unsigned int fb_width;
unsigned int fb_height;
unsigned int fb_depth;
unsigned int x;
unsigned int y;
/*
* check auguments
*/
if (argc != 2) {
usage("insuffient auguments");
exit(-1);
}
/*
* open framebuffer device
*/
if ((fb_device = getenv("FRAMEBUFFER")) == NULL)
fb_device = FB_DEV;
fbdev = fb_open(fb_device);
/*
* get status of framebuffer device
*/
fb_stat(fbdev, &fb_width, &fb_height, &fb_depth);
printf("%d ",fb_width);
printf("%d ",fb_height);
printf("%d\n",fb_depth);
/*
* map framebuffer device to shared memory
*/
screensize = fb_width * fb_height * fb_depth / 8; //所需映射内存的大小
fbmem = fb_mmap(fbdev, screensize); //映射内存的起始地址
memset (fbmem, 0, screensize);//清屏
/*
* open input jpeg file
*/
if ((infile = fopen(argv[1], "rb")) == NULL) {
fprintf(stderr, "open %s failed\n", argv[1]);
exit(-1);
}
/*
* init jpeg decompress object error handler
*/
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
/*
* bind jpeg decompress object to infile
*/
jpeg_stdio_src(&cinfo, infile);
/*
* read jpeg header
*/
jpeg_read_header(&cinfo, TRUE);
/*
* decompress process.
* note: after jpeg_start_decompress() is called
* the dimension infomation will be known,
* so allocate memory buffer for scanline immediately
*/
jpeg_start_decompress(&cinfo);
if ((cinfo.output_width > fb_width) ||
(cinfo.output_height > fb_height)) {
printf("too large JPEG file,cannot display\n");
return (-1);
}
buffer = (unsigned char *) malloc(cinfo.output_width *
cinfo.output_components);//为一条扫描线上的像素点分配存储空间
y = 0;
//while将显示图片内容到framebuffer上
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, &buffer, 1);
if (fb_depth == 16) {
unsigned short color;
for (x = 0; x < cinfo.output_width; x++) {
color = RGB888toRGB555(buffer[x * 3],
buffer[x * 3 + 1], buffer[x * 3 + 2]);
fb_pixel(fbmem, fb_width, fb_height, x, y, color);//显示一个像素点
}
} else if (fb_depth == 24) {
memcpy((unsigned char *) fbmem + y * fb_width * 3,
buffer, cinfo.output_width * cinfo.output_components);
}
y++; // next scanline
}
/*
* finish decompress, destroy decompress object
*/
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
/*
* release memory buffer
*/
free(buffer);
/*
* close jpeg inputing file
*/
fclose(infile);
/*
* unmap framebuffer's shared memory
*/
fb_munmap(fbmem, screensize);
/*
* close framebuffer device
*/
fb_close(fbdev);
return (0);
}
void
usage(char *msg)
{
fprintf(stderr, "%s\n", msg);
printf("Usage: fv some-jpeg-file.jpg\n");
}
/*
* convert 24bit RGB888 to 16bit RGB555 color format
*/
unsigned short
RGB888toRGB555(unsigned char red, unsigned char green, unsigned char blue)
{
unsigned short B = (blue <<7) & 0x
unsigned short G = (green << 2) & 0x03E0;
unsigned short R = (red >> 3);
return (unsigned short) (B | G | R);
}
/*
* open framebuffer device.
* return positive file descriptor if success,
* else return -1.
*/
int
fb_open(char *fb_device)
{
int fd;
if ((fd = open(fb_device, O_RDWR)) < 0) {
perror(__func__);
return (-1);
}
return (fd);
}
/*
* get framebuffer's width,height,and depth.
* return 0 if success, else return -1.
*/
int
fb_stat(int fd, int *width, int *height, int *depth)
{
struct fb_fix_screeninfo fb_finfo;
struct fb_var_screeninfo fb_vinfo;
if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo))
{
perror(__func__);
return (-1);
}
if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo))
{
perror(__func__);
return (-1);
}
*width = fb_vinfo.xres;
*height = fb_vinfo.yres;
*depth = fb_vinfo.bits_per_pixel;
return (0);
}
/*
* map shared memory to framebuffer device.
* return maped memory if success,
* else return -1, as mmap dose.
*/
void *
fb_mmap(int fd, unsigned int screensize)
{
caddr_t fbmem;
if ((fbmem = mmap(0, screensize, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == MAP_FAILED)
{
perror(__func__);
return (void *) (-1);
}
return (fbmem);
}
/*
* unmap map memory for framebuffer device.
*/
int
fb_munmap(void *start, size_t length)
{
return (munmap(start, length));
}
/*
* close framebuffer device
*/
int
fb_close(int fd)
{
return (close(fd));
}
/*
* display a pixel on the framebuffer device.
* fbmem is the starting memory of framebuffer,
* width and height are dimension of framebuffer,
* x and y are the coordinates to display,
* color is the pixel's color value.
* return 0 if success, otherwise return -1.
*/
int
fb_pixel(void *fbmem, int width, int height,
int x, int y, unsigned short color)
{
if ((x > width) || (y > height))
return (-1);
unsigned short *dst = ((unsigned short *) fbmem + y * width + x);
*dst = color;
return (0);
}
chinaunix网友2010-04-17 21:25:56
您好,我也在做这方面的工作,但是刚接触,我在apt-get install libjpeg6后,不知道将什么库文件放到什么交叉编译文档里,请指教