widora 驱动屏幕显示jpg 图像使用libjpeg 出现这个问题



  • ![替代文字](![图片地址](0_1539422256720_2.jpg 图片地址))0_1539422262199_8DAF7E8968F2496C2A48F61DC0FA53CB.jpg

    下面是代码

    #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);
    }
    
    

    0_1543288740956_bread.jpg