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

!1543288741113-bread.jpg