天天看點

jpeg-9中關于read_JPEG_file的使用及通過framebuffer顯示JPEG

#include <stdio.h>

/*
 * Include file for users of JPEG library.
 * You will need to have included system headers that define at least
 * the typedefs FILE and size_t before you can include jpeglib.h.
 * (stdio.h is sufficient on ANSI-conforming systems.)
 * You may also wish to include "jerror.h".
 */

#include "jpeglib.h"

/*
 * <setjmp.h> is used for the optional error recovery mechanism shown in
 * the second part of the example.
 */

#include <setjmp.h>



/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/

/* This half of the example shows how to feed data into the JPEG compressor.
 * We present a minimal version that does not worry about refinements such
 * as error recovery (the JPEG code will just exit() if it gets an error).
 */


/*
 * IMAGE DATA FORMATS:
 *
 * The standard input image format is a rectangular array of pixels, with
 * each pixel having the same number of "component" values (color channels).
 * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars).
 * If you are working with color data, then the color values for each pixel
 * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit
 * RGB color.
 *
 * For this example, we'll assume that this data structure matches the way
 * our application has stored the image in memory, so we can just pass a
 * pointer to our image buffer.  In particular, let's say that the image is
 * RGB color and is described by:
 */

extern JSAMPLE * image_buffer;	/* Points to large array of R,G,B-order data */
extern int image_height;	/* Number of rows in image */
extern int image_width;		/* Number of columns in image */
           
GLOBAL(int)read_JPEG_file (char * filename) {         struct jpeg_decompress_struct cinfo;         struct my_error_mgr jerr;         FILE * infile;         JSAMPARRAY buffer;         int row_stride;             if ((infile = fopen(filename, "rb")) == NULL)     {         fprintf(stderr, "can't open %s\n", filename);         return 0;     }             cinfo.err = jpeg_std_error(&jerr.pub);     jerr.pub.error_exit = my_error_exit;         if (setjmp(jerr.setjmp_buffer))     {         jpeg_destroy_decompress(&cinfo);     fclose(infile);     return 0;     }         jpeg_create_decompress(&cinfo);         jpeg_stdio_src(&cinfo, infile);         (void) jpeg_read_header(&cinfo, TRUE);                     (void) jpeg_start_decompress(&cinfo);                 row_stride = cinfo.output_width * cinfo.output_components;         buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);                 while (cinfo.output_scanline < cinfo.output_height)     {         (void) jpeg_read_scanlines(&cinfo, buffer, 1);         put_scanline_someplace(buffer[0], row_stride); }         (void) jpeg_finish_decompress(&cinfo);                 jpeg_destroy_decompress(&cinfo);         fclose(infile);             return 1; } 使用framebuffer示範jpeg格式圖檔。 程式如下:
#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 ********************/
int main(int argc, char *argv[])
{
	int             fbdev;
	char           *fb_device;
	int w ,h,i,j;

	if (argc != 2) {
		usage("insuffient auguments");
		exit(-1);
	}
	
	if ((fb_device = getenv("FRAMEBUFFER")) == NULL)
		fb_device = FB_DEV;
	fbdev = fb_open(fb_device);

	fb_stat(fbdev, &fb_width, &fb_height, &fb_depth);
	
	screensize = fb_width * fb_height * fb_depth / 8;
	fbmem = fb_mmap(fbdev, screensize);
	
	unsigned char *imgbuf, r, g, b;
	imgbuf = display_jpeg(argv[1],&w,&h);
	printf(" %s: w = %d,h = %d",argv[1],w,h);
	
	for(j = 0; j < h; j++)
	{
		for( i = 0; i < w; i++)
		{
			r = imgbuf[i*3 + j*w*3];
			g = imgbuf[i*3 + j*w*3 + 1];
			b = imgbuf[i*3 + j*w*3 + 2];
			fb_pixel(fbmem,fb_width,fb_height,i,j,r,g,b);
		}
	}

	fb_munmap(fbmem, screensize);
	
	fb_close(fbdev);

	return (0);

}

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;

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

}
           

繼續閱讀