源代码: (包含用libjpeg显示jpeg格式图片代码) /* * ===================================================================================== * * Filename: digital_frame.c * * Description: framebuffer下用libjeg库显示jpeg图片 * * Version: 1.0 * Created: 2011年03月21日 14时01分21秒 * Revision: none * Compiler: gcc * * Author: sunsea1026@gmail.com * * ===================================================================================== */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <linux/fb.h> #include <unistd.h> #include <jpeglib.h> #define FB_DEV "/dev/fb0" #define JPEG 0x001 #define PNG 0x010 #define BMP 0x100 #define UNKNOWN 0x111 static int fb_dev; static struct fb_var_screeninfo fb_var; static int screen_w, screen_h, screen_bits; static void *fbmem, *data; static FILE *infile; //JPEG的内容 typedef struct jpeg_color { unsigned char r; unsigned char g; unsigned char b; }COLOR;; typedef struct jpeg_pixel_t { unsigned char r; unsigned char g; unsigned char b; unsigned char a; }PIXEL_T; //BMP的内容 typedef struct bmp_file_header { char cfType[2]; //文件类型,必须为“BM”(0x4D42) char cfSize[4]; //文件的大小(字节) char cfReserved[4]; //保留,必须为0 char cfoffBits[4]; //位图阵列相对与文件头的偏移量(字节) }__attribute__((packed)) BITMAPFILEHEADER; //文件头结构 typedef struct bmp_info_header { char ciSize[4]; //sizeof of BITMAPINFOHEADER char ciWidth[4]; //位图宽度(像素) char ciHeight[4]; //位图高度(像素) char ciPlanes[2]; //目标设备的位平面数,必须置为1 char ciBitCount[2]; //每个像素的位数,1,4,8或24 char ciCompress[4]; //位图阵列的压缩方法,0=不压缩 char ciSizeImage[4]; //图像大小(字节) char ciXPelsPerMeter[4]; //目标设备水平每米像素个数 char ciYPelsPerMeter[4]; //目标设备垂直每米像素个数 char ciClrUsed[4]; //位图实际使用的颜色表的颜色数 char ciClrImportant[4]; //重要颜色索引的个数 }__attribute__((packed)) BITMAPINFOHEADER; //位图信息头结构 //初始化fb0 void fb_init() { //打开fb0设备文件 fb_dev = open(FB_DEV, O_RDWR); if(fb_dev < 0) { printf("Error:open %s error/n", FB_DEV); printf("Usage:[sudo ./digital_frame xxx.jpg]/n"); exit(1); } //获取fb0参数 ioctl(fb_dev, FBIOGET_VSCREENINFO, &fb_var); screen_w = fb_var.xres; screen_h = fb_var.yres; screen_bits = fb_var.bits_per_pixel; printf("Framebuffer:%d * %d/n", screen_w, screen_h); printf("screen_bits:%d/n", screen_bits); fbmem = mmap(0, screen_w * screen_h * screen_bits / 8, PROT_READ | PROT_WRITE, MAP_SHARED, fb_dev, 0); return; } //判断图片格式 int judge_picture_mode(char **argv) { char header[8]; printf("picture = %s/n", argv[1]); infile = fopen(argv[1], "rb"); if(infile == NULL) { printf("Error:open %s error!/n", argv[1]); exit(1); } memset(header, 0, sizeof(header)); fread(&header, 8, 1, infile); fseek(infile, -8, 1); if((unsigned char)header[0] == 0xff) { return JPEG; } else if((unsigned char)header[0] == 0x89) { return PNG; } else if(0 == strncmp(header, "BM", 2)) { return BMP; } else { return UNKNOWN; } } //显示jpg/jpeg格式图片 void display_jpeg() { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; int picture_w, picture_h, picture_bits; int i, j, x, y; unsigned char *buffer, *tmpbuf; COLOR picture_color; PIXEL_T **fbp; fbp = (PIXEL_T **)malloc(sizeof(PIXEL_T *) * screen_w); //x, y 代表图片的起始坐标 for(i = 0, x = 400 * screen_bits / 8, y = 200; i < screen_w; i++) { fbp[i] = (PIXEL_T *)(fbmem + (y + i) * screen_w * screen_bits / 8 + x); } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); //指定要解压缩的图像文件 jpeg_stdio_src(&cinfo, infile); //获取图像信息 jpeg_read_header(&cinfo, TRUE); //开始解压 jpeg_start_decompress(&cinfo); picture_w = cinfo.output_width; picture_h = cinfo.output_height; picture_bits = cinfo.output_components; /* printf("picture info:/n"); printf("width = %d/n", picture_w); printf("height = %d/n", picture_h); printf("bits = %d/n", picture_bits); */ //获取颜色值 buffer = (unsigned char *)malloc(picture_w * picture_bits); memset(buffer, 0, picture_w * picture_bits); for(i = 0; i < picture_h; i++) { tmpbuf = buffer; jpeg_read_scanlines(&cinfo, &tmpbuf, 1); for(j = 0; j < picture_w; j++) { memcpy(&picture_color, tmpbuf, sizeof(picture_color)); fbp[i][j].b = picture_color.r; fbp[i][j].g = picture_color.g; fbp[i][j].r = picture_color.b; tmpbuf += picture_bits; } } //完成解压 jpeg_finish_decompress(&cinfo); //释放解压对象 jpeg_destroy_decompress(&cinfo); free(buffer); return; } //显示png图片 void display_png() {/* png_structp png_ptr; png_infop info_ptr; int picture_w, picture_h, picture_color_type; png_ptr = create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); info_ptr = png_create_info_struct(png_ptr); setjmp(png_jmpbuf(png_ptr)); png_init_io(png_ptr, infile); png_read_png(png_ptr, info_ptr, PNG_TRANSFROM_EXPAND, 0); picture_w = png_get_image_width(PngPtr, InfoPtr); picture_h = png_get_image_height(PngPtr, InfoPtr); picture_color_type = png_get_image_color_type(PngPtr, InfoPtr); printf("picture info:/n"); printf("width = %d/n", picture_w); printf("height = %d/n", picture_h); printf("color_type = %d/n", picture_color_type); */ return; } //chartolong long chartolong(char *string, int length) { long number; if(length <= 4) { memset(&number, 0, sizeof(long)); memcpy(&number, string, length); } return number; } //显示bmp格式图片 void display_bmp() { BITMAPFILEHEADER FileHead; BITMAPINFOHEADER InfoHead; int rc ,i ,j, x, y; int ciWidth, ciHeight, ciBitCount; long int BytesPerLine = 0; COLOR picture_color; PIXEL_T **fbp; unsigned char *buffer, *tmpbuf; //读位图文件头 rc = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, infile); if(rc != 1) { printf("Error:read bmp header error!/n"); fclose(infile); exit(1); } //判断位图的类型 if(memcmp(FileHead.cfType, "BM", 2) != 0) { printf("This is not a bmp picture!/n"); fclose(infile); exit(1); } //读取位图信息头 rc = fread((char *)&InfoHead, sizeof(BITMAPINFOHEADER), 1, infile); if(rc != 1) { printf("Error:read bmp infoheader error!/n"); fclose(infile); exit(1); } ciWidth = (int)chartolong(InfoHead.ciWidth, 4); ciHeight = (int)chartolong(InfoHead.ciHeight, 4); ciBitCount = (int)chartolong(InfoHead.ciBitCount, 4); fseek(infile, (int)chartolong(FileHead.cfoffBits, 4), SEEK_SET); BytesPerLine = (ciWidth * ciBitCount + 31) / 32 * 4; /* printf("bmp info/n"); printf("width = %d/n", ciWidth); printf("height = %d/n", ciHeight); printf("bit = %d/n", ciBitCount); */ fbp = (PIXEL_T **)malloc(sizeof(PIXEL_T *) * screen_w); for(i = 0, x = 0 * screen_bits / 8, y = 0; i < screen_w; i++) { fbp[i] = (PIXEL_T *)(fbmem + (y + i) * screen_w * screen_bits / 8 + x); } buffer = (unsigned char *)malloc(BytesPerLine); memset(buffer, 0, BytesPerLine); for(i = ciHeight - 1; i >= 0; i--) { tmpbuf = buffer; rc = fread(tmpbuf, BytesPerLine, 1, infile); for(j = 0; j < ciWidth; j++) { memcpy(&picture_color, tmpbuf, ciBitCount / 8); fbp[i][j].r = picture_color.r; fbp[i][j].g = picture_color.g; fbp[i][j].b = picture_color.b; tmpbuf += ciBitCount / 8; } } return; } int main(int argc, char* argv[]) { int picture_mode; if(argc != 2) { printf("Usage:[sudo ./digital_frame xxx.jpg]/n"); exit(1); } //fb0初始化 fb_init(); //判断图片格式 picture_mode = judge_picture_mode(argv); switch(picture_mode) { case JPEG: printf("JPEG/JPG/n"); display_jpeg(); break; case PNG: printf("PNG/n"); display_png(); break; case BMP: printf("bmp/n"); display_bmp(); break; case UNKNOWN: printf("UNKNOWN/n"); break; default: break; } fclose(infile); return 0; }