由于时间的的仓促,没来及注释;
1、Makefile文件:
main_fb:main_fb.o myfb.o
gcc -ljpeg main_fb.o myfb.o -o main_fb
main_fb.o:main_fb.c myfb.h
gcc -c main_fb.c
myfb.o:myfb.c myfb.h
gcc -c myfb.c
.PHONY:clean
clean:
rm -f a.out *~ *.o
2、framebuffer的头文件myfb.h:
#ifndef MYFB_H
#define MYFB_H
#include <stdio.h>
#include <stdlib.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <jpeglib.h>
#include <jerror.h>
#include <string.h>
typedef struct
{
int fb;
struct fb_var_screeninfo vinfo;
//struct fb_fix_screeninfo finfo;
long screensize;
unsigned char *fbp;
}fb_type;
int initilize_fb(fb_type *myfb);
void clean_screen(fb_type *myfb);
int destroy_fb(fb_type *myfb);
void draw_fb(fb_type *myfb, char *imagename);
#endif
3、framebuffer的源文件myfb.c:
#include "myfb.h"
static int set_pixel(void *memoff, int width, int height, int x, int y, unsigned short color);
static int set_pixel32(void *memoff, int width, int height, int x, int y, unsigned int color);
static unsigned short tocolor16(unsigned char red, unsigned char green, unsigned char blue);
static unsigned int tocolor24(unsigned char blue, unsigned char green, unsigned char red);
int initilize_fb(fb_type *myfb)
{
int fid;
if((fid = open("/dev/fb0", O_RDWR)) < 0)
{
return -1;
}
myfb->fb = fid;
#if 0
if(ioctl(fid, FBIOGET_FSCREENINFO, &(myfb->finfo)) < 0)
{
exit(-2);
}
#endif
if(ioctl(fid, FBIOGET_VSCREENINFO, &(myfb->vinfo)))
{
return -2;
}
myfb->screensize = myfb->vinfo.xres * myfb->vinfo.yres * myfb->vinfo.bits_per_pixel / 8;
//printf("screensize=%ld\n", myfb->screensize);
if((myfb->fbp = mmap(NULL, myfb->screensize, PROT_READ|PROT_WRITE, MAP_SHARED, fid, 0)) == (void *)-1)
{
return -3;
}
return 0;
}
void clean_screen(fb_type *myfb)
{
memset(myfb->fbp, 0, myfb->screensize);
}
int destroy_fb(fb_type *myfb)
{
if(munmap((void *)myfb->fbp, (size_t)myfb->screensize) < 0)
{
exit(-1);
}
close(myfb->fb);
return 0;
}
void draw_fb(fb_type *myfb, char *imagename)
{
FILE *fid;
//for jpeg decompress
struct jpeg_decompress_struct image_info;
struct jpeg_error_mgr image_err;
unsigned char *buffer;
unsigned int x;
unsigned int y;
//fb attribute
unsigned int width = myfb->vinfo.xres;
unsigned int height = myfb->vinfo.yres;
unsigned int pixels = myfb->vinfo.bits_per_pixel;
unsigned char *fbp = myfb->fbp;
if((fid = fopen(imagename, "rb")) == NULL)
{
exit(1);
}
//init jpeg decompress
image_info.err = jpeg_std_error(&image_err);
jpeg_create_decompress(&image_info);
//bind object to image_info
jpeg_stdio_src(&image_info, fid);
//read jpeg header
jpeg_read_header(&image_info, TRUE);
//decompress process
jpeg_start_decompress(&image_info);
if((image_info.output_width > width) || (image_info.output_height > height))
{
exit(-11);
}
//initilize buffer to store decompress image
if((buffer = malloc(image_info.output_width * image_info.output_components)) == NULL)
{
exit(-1);
}
y = 0;
while(image_info.output_scanline < image_info.output_height)
{
jpeg_read_scanlines(&image_info, &buffer, 1);
if(pixels == 16)
{
unsigned short color16;
for(x = 0; x < image_info.output_width; ++x)
{
color16 = tocolor16(buffer[x * 3], buffer[x * 3 + 1], buffer[x * 3 + 2]);
set_pixel(fbp, width, height, x, y, color16);
}
}
else if(pixels == 24)
{
memcpy(fbp + y * width * 3, buffer, image_info.output_width * image_info.output_components);
}
else if(pixels == 32)
{
unsigned int color32;
for(x = 0; x < image_info.output_width; ++x)
{
color32 = tocolor24(buffer[x * 3], buffer[x * 3 + 1], buffer[x * 3 + 2]);
set_pixel32(fbp, width, height, x, y, color32);
}
}
y++;
}
//finish decompress and destroy decompress object
jpeg_finish_decompress(&image_info);
jpeg_destroy_decompress(&image_info);
//ralease memory buffer
free(buffer);
fclose(fid);
}
static unsigned short tocolor16(unsigned char red, unsigned char green, unsigned char blue)
{
unsigned short ablue = (blue >> 3) & 0x001F;
unsigned short agreen =((green >> 2) << 5) & 0x07E0;
unsigned short ared = ((red >> 3) << 11) & 0xF800;
return(unsigned short)(ablue | agreen | ared);
}
static unsigned int tocolor24(unsigned char red, unsigned char green, unsigned char blue)
{
//unsigned int aalpha = 0x00000000;
unsigned int ablue = blue & 0x000000FF;
unsigned int agreen =(green & 0x000000FF) << 8;
unsigned int ared = (red & 0x000000FF) << 16;
return((unsigned int)(ablue | agreen | ared));
}
/*
* Display a pixel on the framebuffer device, memoff 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 successly,oterwise return -1
*/
static int set_pixel(void *memoff, int width, int height, int x, int y, unsigned short color)
{
if((x > width) || (y > height))
{
exit(-1);
}
unsigned short *dst = ((unsigned short *)memoff + y * width + x);
*dst = color;
return 0;
}
static int set_pixel32(void *memoff, int width, int height, int x, int y, unsigned int color)
{
if((x > width) || (y > height))
{
exit(-1);
}
unsigned int *dst = ((unsigned int *)memoff + y * width + x);
*dst = color;
return 0;
}
4、Main 文件main_fb.c:
#include <errno.h>
#include <sys/mount.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include "myfb.h"
char imgbuf[256][256] = {0};
int length = 0;
int usb_init(const char *path);
void usb_destory(const char *path);
void usb_traversaldir(char *filename);
int main(int argc, char **argv)
{
char path[256] = "/mnt/myusb";
char cwd[256];
int i;
char ch;
int usb_flag = 0;
fb_type *myfb;
#if 0
if(argc != 2)
{
fprintf(stderr, "Usage: %s <imagename>\n", argv[0]);
exit(1);
}
#endif
if(usb_init(path) < 0)
{
fprintf(stdout, "no usb device \n");
if(getcwd(path, sizeof(path)) == NULL)
{
fprintf(stderr, "getcwd() failed:%s\n", strerror(errno));
exit(1);
}
}
else
{
usb_flag = 1;
}
fprintf(stdout, "%s\n", path);
usb_traversaldir(path);
if((myfb = malloc(sizeof(fb_type))) == NULL)
{
fprintf(stderr, "malloc() failed:%s\n", strerror(errno));
exit(1);
}
memset(myfb, 0, sizeof(fb_type));
int ret;
if((ret = initilize_fb(myfb)) < 0)
{
fprintf(stderr, "initilize fb device failed:%d\n", ret);
exit(1);
}
//fprintf(stdout, "x:%d,y:%d,pixel:%d\n", myfb->vinfo.xres, myfb->vinfo.yres, myfb->vinfo.bits_per_pixel);
if(length > 0)
{
for(i = 0; i < length; ++i)
{
clean_screen(myfb);
draw_fb(myfb, imgbuf[i]);
//scanf("%1c", &ch);
sleep(5);
}
}
else
{
fprintf(stderr, "no image to display\n");
}
clean_screen(myfb);
destroy_fb(myfb);
free(myfb);
if(usb_flag)
{
usb_destory(path);
}
return 0;
}
int usb_init(const char *path)
{
if(mkdir(path, 0777) < 0)
{
//fprintf(stderr, "mkdir() failed:%s\n", strerror(errno));
return(-1);
}
if(mount("/dev/sdb1", path, "vfat", MS_SYNCHRONOUS, NULL ) != 0)
{
//fprintf(stderr, "mount() failed:%s\n", strerror(errno));
return(-2);
}
return 0;
}
void usb_destory(const char *path)
{
if(umount(path) < 0)
{
fprintf(stderr, "umount() failed:%s\n", strerror(errno));
exit(1);
}
if(rmdir(path) < 0)
{
fprintf(stderr, "rmdir() failed:%s\n", strerror(errno));
exit(1);
}
}
void usb_traversaldir(char *filename)
{
char *ch;
//int lstat(const char *path, struct stat *buf);
struct stat status;
DIR *dp;
struct dirent *dirp;
if(lstat(filename, &status) < 0)
{
fprintf(stderr, "lstat %s failed: %s\n", filename, strerror(errno));
exit(1);
}
if(!S_ISDIR(status.st_mode))
{
if(S_ISREG(status.st_mode))
{
if((ch = strrchr(filename, '.')) != NULL)
{
if(strcmp(ch, ".jpg") == 0|| strcmp(ch, ".jpeg") == 0)
{
strcpy(imgbuf[length], filename);
++length;
//printf("%s\n",filename);
}
}
}
return;
}
else
{
//fprintf(stdout, "%s\n", filename);
//DIR *opendir(const char *name);
if((dp = opendir(filename)) == NULL)
{
fprintf(stderr, "opendir(%s) failed: %s\n", filename, strerror(errno));
exit(1);
}
//DIR *fdopendir(int fd);
while((dirp = readdir(dp)) != NULL)
{
char buf[1024];
memset(buf, 0, 1024);
memcpy(buf, filename, strlen(filename));
strcat(buf, "/");
strcat(buf, dirp->d_name);
//fprintf(stdout, "%s\n", dirp->d_name);
if(memcmp(dirp->d_name, ".", 1) == 0 || memcmp(dirp->d_name, "..", 2) == 0)
{
continue;
}
usb_traversaldir(buf);
}
}
free(dirp);
closedir(dp);
return;
}