widora 驱动屏幕显示jpg 图像使用libjpeg 出现这个问题
-
)
下面是代码
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <jpeglib.h>
#include <jerror.h>#define FB_DEV "/dev/fb0"
unsigned char fbmem;
unsigned int screensize;
unsigned int fb_width;
unsigned int fb_height;
unsigned int fb_depth;
unsigned int x;
unsigned int y;
/**************** function declaration ****************/
void usage(char msg);
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, int r, int g, int b);
unsigned char * display_jpeg(char * filename,int w, int h);
/ function implementation ********************/unsigned char * display_jpeg(char * filename, int *w, int *h)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *infile;
unsigned char *buffer;
unsigned char *temp;if ((infile = fopen(filename, "rb")) == NULL) { fprintf(stderr, "open %s failed/n", filename); exit(-1); } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); *w = cinfo.output_width; *h = cinfo.output_height; printf("output_width====%d\n",cinfo.output_width); printf("output_height====%d\n",cinfo.output_height); 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 * cinfo.output_height); temp = buffer; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, &buffer, 1); buffer += cinfo.output_width * cinfo.output_components; } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return temp; fclose(infile);
}
void usage(char *msg)
{
fprintf(stderr, "%s/n", msg);
printf("Usage: fv some-jpeg-file.jpg/n");
}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);
}
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);
}
int fb_munmap(void *start, size_t length)
{
return (munmap(start, length));
}int fb_close(int fd)
{
return (close(fd));}
int fb_pixel(void *fbmem, int width, int height,
int x, int y, int r, int g, int b)
{
if ((x > width) || (y > height))return (-1); unsigned char *dst = fbmem + y * 5504 + x * 4; //'5504'为个人PC机的bpp dst[0] = b; dst[1] = g; dst[2] = r; return (0);
}
int main1(char *name)
{
int fbdev;
char *fb_device;
int w ,h,i,j;
unsigned short color;fb_width=320; fb_height=240; fb_depth=16; unsigned char *imgbuf, r, g, b; imgbuf = display_jpeg(name,&w,&h); for(j = 0; j < h; j++) { for( i = 0; i < w; i++) { color= imgbuf[i*3 + j*w*3+2]; color<<=8; color|= imgbuf[i*3 + j*w*3 + 1]; color<<=8; color|= imgbuf[i*3 + j*w*3]; draw_dot(i,j,rgb2tft(color)); } } return (0);
}
void drawbmp(unsigned int x,unsigned int y,unsigned char *name)
{
main1(name);
}
-
嫁接了一下,OK.
/* ------------------------------------------------------------------------- original source: https://blog.csdn.net/luxiaoxun/article/details/7622988 1. Modified for a 240x320 SPI LCD display. 2. The width of the displaying picture must be a multiple of 4. ./open-gcc -L./lib -I./include -ljpeg -o jpgshow fbshow.c Midas ---------------------------------------------------------------------------*/ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <linux/fb.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <arpa/inet.h> #include <jpeglib.h> #include <jerror.h> //14byte文件头 typedef struct { char cfType[2];//文件类型,"BM"(0x4D42) long cfSize;//文件大小(字节) long cfReserved;//保留,值为0 long cfoffBits;//数据区相对于文件头的偏移量(字节) }__attribute__((packed)) BITMAPFILEHEADER; //__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐 //40byte信息头 typedef struct { char ciSize[4];//BITMAPFILEHEADER所占的字节数 long ciWidth;//宽度 long ciHeight;//高度 char ciPlanes[2];//目标设备的位平面数,值为1 int ciBitCount;//每个像素的位数 char ciCompress[4];//压缩说明 char ciSizeImage[4];//用字节表示的图像大小,该数据必须是4的倍数 char ciXPelsPerMeter[4];//目标设备的水平像素数/米 char ciYPelsPerMeter[4];//目标设备的垂直像素数/米 char ciClrUsed[4]; //位图使用调色板的颜色数 char ciClrImportant[4]; //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要 }__attribute__((packed)) BITMAPINFOHEADER; typedef struct { unsigned char blue; unsigned char green; unsigned char red; // unsigned char reserved; // for 32bit pix only }__attribute__((packed)) PIXEL;//颜色模式RGB BITMAPFILEHEADER FileHead; BITMAPINFOHEADER InfoHead; static char *fbp = 0; static int xres = 0; static int yres = 0; static int bits_per_pixel = 0; //tft lcd /* ----- functions --------*/ int show_bmp(char* fpath); int show_jpg(char* fpath); unsigned char * open_jpgImg(char * filename, int *w, int *h); void close_jpgImg(unsigned char *imgbuf); /*================== main =================*/ int main ( int argc, char *argv[] ) { int fbfd = 0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long int screensize = 0; //打开显示设备 fbfd = open("/dev/fb0", O_RDWR); if (!fbfd) { printf("Error: cannot open framebuffer device.\n"); exit(1); } if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) { printf("Error:reading fixed information.\n"); exit(2); } if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { printf("Error: reading variable information.\n"); exit(3); } printf("R:%d,G:%d,B:%d \n", vinfo.red.length, vinfo.green.length, vinfo.blue.length ); printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel ); xres = vinfo.xres; yres = vinfo.yres; bits_per_pixel = vinfo.bits_per_pixel; if(bits_per_pixel != 16) printf("WARNING: bits_per_pixel !=16, this program is base on R5_G6_B5 fb color format!\n"); //计算屏幕的总大小(字节) screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; printf("screensize=%d byte\n",(int)screensize); //对象映射 fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if ((int)fbp == -1) { printf("Error: failed to map framebuffer device to memory.\n"); exit(4); } printf("sizeof file header=%d\n", sizeof(BITMAPFILEHEADER)); printf("into show_bmp function\n"); //显示图像 // show_bmp(argv[1]); show_jpg(argv[1]); //删除对象映射 munmap(fbp, screensize); close(fbfd); return 0; } int show_bmp(char* fpath) { FILE *fp; int rc; int line_x, line_y; long int location = 0; printf("fpath=%s\n",fpath); fp = fopen( fpath, "rb" ); if (fp == NULL) { return( -1 ); } rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp ); if ( rc != 1) { printf("read header error!\n"); fclose( fp ); return( -2 ); } //检测是否是bmp图像 if (memcmp(FileHead.cfType, "BM", 2) != 0) { printf("it's not a BMP file\n"); fclose( fp ); return( -3 ); } rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp ); if ( rc != 1) { printf("read infoheader error!\n"); fclose( fp ); return( -4 ); } printf("BMP width=%d,height=%d ciBitCount=%d\n",(int)InfoHead.ciWidth, (int)InfoHead.ciHeight, (int)InfoHead.ciBitCount); //检查是否24bit色 if(InfoHead.ciBitCount != 24 ){ printf("It's not 24bit_color BMP!\n"); return -1; } //检查宽度是否240x320 if(InfoHead.ciWidth > 240 ){ printf("The width is great than 240!\n"); return -1; } if(InfoHead.ciHeight > 320 ){ printf("The height is great than 320!\n"); return -1; } //跳转的数据区 fseek(fp, FileHead.cfoffBits, SEEK_SET); int x0=0,y0=0; //set original coodinate if( InfoHead.ciHeight+y0 > 320 || InfoHead.ciWidth+x0 > 240 ) { printf("The origin of picture (x0,y0) is too big for a 240x320 LCD.\n"); return -1; } line_x = line_y = 0; //向framebuffer中写BMP图片 while(!feof(fp)) { PIXEL pix; //unsigned short int tmp; rc = fread( (char *)&pix, 1, sizeof(PIXEL), fp); if (rc != sizeof(PIXEL)) break; // frame buffer location location = line_x * bits_per_pixel / 8 +x0 + (InfoHead.ciHeight - line_y - 1 +y0) * xres * bits_per_pixel / 8; //显示每一个像素, in ili9431 node of dts, color sequence is defined as 'bgr'(as for ili9431) . // little endian is noticed. // ---- converting to format R5G6B5(as for framebuffer) ----- *(fbp + location + 0)=(((pix.green)&0b11100)<<3) + (((pix.blue)&0b11111000)>>3); *(fbp + location + 1)=((pix.red)&0b11111000) + (((pix.green)&0b11100000)>>5); line_x++; if (line_x == InfoHead.ciWidth ) { line_x = 0; line_y++; //printf("line_y = %d\n",line_y); if(line_y == InfoHead.ciHeight) break; } } fclose( fp ); return( 0 ); } int show_jpg(char* fpath) { int width,height; unsigned char *imgbuf; unsigned char *dat; uint16_t tmp; long int location = 0; int line_x,line_y; imgbuf=open_jpgImg(fpath,&width,&height); if(imgbuf==NULL) { printf("open_jpgImg fails!\n"); return -1; } dat=imgbuf; printf("open_jpgImg() succeed, width=%d, height=%d\n",width,height); int x0=0,y0=0; //set original coodinate line_x = line_y = 0; for(line_y=0;line_y<height;line_y++) { for(line_x=0;line_x<width;line_x++) { location = line_x * bits_per_pixel / 8 +x0 + (height - line_y - 1 +y0) * xres * bits_per_pixel / 8; //显示每一个像素, in ili9431 node of dts, color sequence is defined as 'bgr'(as for ili9431) . // little endian is noticed. // ---- dat(R8G8B8) converting to format R5G6B5(as for framebuffer) ----- *(fbp + location + 0)=((*(dat+1)&0b11100)<<3) + ((*(dat+2) & 0b11111000)>>3); *(fbp + location + 1)=(*dat&0b11111000) + ((*(dat+1)&0b11100000)>>5); dat+=3; } } close_jpgImg(imgbuf); } /*-------------------------------------------------------------- open jpg file and return decompressed image buffer pointer int *w,*h: with and height of the image return: =NULL fail >0 decompressed image buffer pointer --------------------------------------------------------------*/ unsigned char * open_jpgImg(char * filename, int *w, int *h) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; FILE *infile; unsigned char *buffer; unsigned char *temp; if ((infile = fopen(filename, "rb")) == NULL) { fprintf(stderr, "open %s failed\n", filename); exit(-1); } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); *w = cinfo.output_width; *h = cinfo.output_height; printf("output_width====%d\n",cinfo.output_width); printf("output_height====%d\n",cinfo.output_height); /* --- check size ----*/ if ((cinfo.output_width > 240) || (cinfo.output_height > 320)) { printf("too large size JPEG file,cannot display\n"); return NULL; } buffer = (unsigned char *) malloc(cinfo.output_width * cinfo.output_components * cinfo.output_height); temp = buffer; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, &buffer, 1); buffer += cinfo.output_width * cinfo.output_components; } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return temp; fclose(infile); } /* release mem for decompressed jpeg image buffer */ void close_jpgImg(unsigned char *imgbuf) { if(imgbuf != NULL) free(imgbuf); }