将一张JPEG图片通过嵌入式linux的帧缓冲机制绘制到7寸触摸屏上

时间:2021-12-27 07:45:08

1.移植libjpeg库

 转载自:http://blog.sina.com.cn/s/blog_68282f2e0102uyeo.html

本文主要讲如何把libjpeg库移植到mini2440arm板上。(我用的是友善tiny6410)

我的系统:Fedora11
编译工具:arm-linux-gcc
第一步下载libjpeg库
下载地址 http://www.ijg.org/
下载jpegsrc.v9a.tar.gz这个文件
第二步
解压这个文件
第三步
打开终端,切换到解压的目录
执行
./configure --prefix=/usr/local/lib CC=arm-linux-gcc --host=arm-linux --enable-shared --enable-static     (prefix可以自己指定)
第四步
执行
make
可能需要几分钟。
执行
make install 

第五步
库的使用
arm-linux-gcc -o 你的输出 你的程序 -L/usr/local/lib -l:libjpeg.so.9

2.编写实现代码

转载自:http://blog.csdn.net/angle_birds/article/details/8647365

代码:

#include    <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include "jpeglib.h"
#include "jerror.h"

#define FB_DEV "/dev/fb0"
#define __fnc__ __FUNCTION__

#define debug 0
#define debug_printf 0
#define BYREAD 0
#define BYMEM 1

/* function deciaration */

void usage(char *msg);
unsigned short RGB888toRGB565(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, unsigned int *width, unsigned int *height, unsigned int * depth);
void *fb_mmap(int fd, unsigned int screensize);
void *fd_mmap(int fd, unsigned int filesize);
int fb_munmap(void *start, size_t length);
int fb_pixel(void *fbmem, int width, int height,
int x, int y, unsigned short color);

#if(debug)
void draw(unsigned char *fbp,
struct fb_var_screeninfo vinfo,
struct fb_fix_screeninfo finfo);
#endif

/* function implementation */

int main(int argc, char **argv)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
#if(BYREAD)
FILE *infile;
#endif
int fd;
unsigned char *buffer;
struct stat st;

int fbdev;
char *fb_device;
unsigned char *fbmem;
unsigned char *fdmem;
unsigned int screensize;
unsigned int fb_width;
unsigned int fb_height;
unsigned int fb_depth;
register unsigned int x;
register 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);

/* map framebuffer device to shared memory */
screensize = fb_width * fb_height * fb_depth / 8;
fbmem = fb_mmap(fbdev, screensize);

#if (BYREAD)
/* open input jpeg file */
if ((infile = fopen(argv[1], "rb")) == NULL) {
fprintf(stderr, "open %s failed\n", argv[1]);
exit(-1);
}
#endif

if ((fd = open(argv[1], O_RDONLY)) < 0) {
perror("open");
exit(-1);
}

if (fstat(fd, &st) < 0) {
perror("fstat");
exit(-1);
}

fdmem = fd_mmap(fd, st.st_size);

/* init jpeg decompress object error handler */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);

/* bind jpeg decompress object to infile */
#if (BYREAD)
jpeg_stdio_src(&cinfo, infile);
#endif

#if (BYMEM)
jpeg_mem_src(&cinfo, fdmem, st.st_size);
#endif

/* read jpeg header */
jpeg_read_header(&cinfo, TRUE);

/* decompress process */
jpeg_start_decompress(&cinfo);
if ((cinfo.output_width > fb_width) ||
(cinfo.output_height > fb_height)) {
printf("too large jpeg file, can't display\n");
#if (0)
return -1;
#endif
}

buffer = (unsigned char *) malloc(cinfo.output_width *
cinfo.output_components);

struct fb_fix_screeninfo fb_finfo;
struct fb_var_screeninfo fb_vinfo;

if (ioctl(fbdev, FBIOGET_FSCREENINFO, &fb_finfo)) {
perror(__fnc__);
return -1;
}

if (ioctl(fbdev, FBIOGET_VSCREENINFO, &fb_vinfo)) {
perror(__fnc__);
return -1;
}

#if(debug)
draw(fbmem, fb_vinfo, fb_finfo);
#endif
y = 0;
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 =
RGB888toRGB565(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);
} else if (fb_depth == 32) {
// memcpy((unsigned char *) fbmem + y * fb_width * 4,
// buffer, cinfo.output_width * cinfo.output_components);
for (x = 0; x < cinfo.output_width; x++) {
* (fbmem + y * fb_width * 4 + x * 4) = (unsigned char) buffer[x * 3 + 2];
* (fbmem + y * fb_width * 4 + x * 4 + 1) = (unsigned char) buffer[x * 3 + 1];
* (fbmem + y * fb_width * 4 + x * 4 + 2) = (unsigned char) buffer[x * 3 + 0];
* (fbmem + y * fb_width * 4 + x * 4 + 3) = (unsigned char) 0;
}
}
y++; // next scanline
}

/* finish decompress, destroy decompress object */
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);

/* release memory buffer */
free(buffer);

#if (BYREAD)
/* close jpeg inputing file */
fclose(infile);
#endif

/* unmap framebuffer's shared memory */
fb_munmap(fbmem, screensize);

#if (BYMEM)
munmap(fdmem, (size_t) st.st_size);
close(fd);
#endif

/* 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");
}

/* 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(__fnc__);
return -1;
}
return fd;
}

int fb_close(int fd)
{
return (close(fd));
}

/* get framebuffer's width, height, and depth.
* return 0 if success, else return -1.
*/
int fb_stat(int fd, unsigned int *width, unsigned int *height, unsigned int * depth)
{
struct fb_fix_screeninfo fb_finfo;
struct fb_var_screeninfo fb_vinfo;

if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo)) {
perror(__fnc__);
return -1;
}

if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {
perror(__fnc__);
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;
}

/* map shared memmory to a opened file */
void *fd_mmap(int fd, unsigned int filesize)
{
caddr_t fdmem;

if ((fdmem = mmap(0, filesize, PROT_READ,
MAP_SHARED, fd, 0)) == MAP_FAILED) {
perror(__func__);
return (void *) (-1);
}

return fdmem;
}

/* unmap map memory for framebuffer device */
int fb_munmap(void *start, size_t length)
{
return (munmap(start, length));
}

/* convert 24bit RGB888 to 16bit RGB565 color format */
unsigned short RGB888toRGB565(unsigned char red,
unsigned char green, unsigned char blue)
{
unsigned short B = (blue >> 3) & 0x001F;
unsigned short G = ((green >> 2) << 5) & 0x07E0;
unsigned short R = ((red >> 3) << 11) & 0xF800;

return (unsigned short) (R | G | B);
}

/* display a pixel on the framebuffer device.
* fbmem is the starting memory of framebuffer,
* width and height are dimension 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;
}

编译命令:

arm-linux-gcc -o fb_jpeg fb_jpeg.c -I/workspace/tiny6410/libjpeg/jpeg-9a/install/include -L/workspace/tiny6410/libjpeg/jpeg-9a/install/lib -l:libjpeg.so.9


3.在板测试

设置好LD_LIBRARY_PATH指向刚才编译出来的libjpeg安装目录下的lib目录,然后运行./fb_jpeg /sdcard/image.jpg

测试效果:

将一张JPEG图片通过嵌入式linux的帧缓冲机制绘制到7寸触摸屏上

(-------------------仅供参考交流-----------------------)