libjpeg测试程序

来源:互联网 发布:淘宝信用卡套现流程 编辑:程序博客网 时间:2024/05/29 17:17

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <pthread.h>
#include <string.h>
#include <jpeglib.h>
#define FB_DEV "/dev/fb0"
/***************** function declaration ******************/
void usage(char *msg);
unsigned short RGB888toRGB565(unsigned char red,
unsigned char green, unsigned char blue);
int fb_open(char *fb_device);
int fb_close(int fd);
int fb_stat(int fd, int *width, int *height, int *depth,int yoffset);
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, unsigned short color);
/************ function implementation ********************/
int main(int argc, char *argv[])
{
 /*
 * declaration for jpeg decompression
 */
 struct jpeg_decompress_struct cinfo;//解压的jpeg所有信息
 struct jpeg_error_mgr jerr;//jpeg错误处理对象
 int i=1;
 FILE *infile;//要显示的文件
 unsigned char *buffer;//缓冲区
 /* 
 * declaration for framebuffer device
 */
 int fbdev;//打开的framebuffer设备号
 char *fb_device;//framebuffer设备名
 unsigned char *fbmem;//LCD内存映射
 unsigned int screensize;//LCD屏幕大小
 unsigned int fb_width;//LCD宽度
 unsigned int fb_height;//LCD高度
 unsigned int fb_depth;//LCD像素几个字节
 unsigned int x;
 unsigned int y;
 //if (argc != 2) {
  //usage("insuffient auguments");//判断命令行参数
  //exit(-1);
 //}
 if ((fb_device = "/dev/fb0") == NULL)
  fb_device = FB_DEV;
 fbdev = fb_open(fb_device);//打开LCD设备并返回设备号
 //获取framebuffer的信息:宽度、高度、每像素二进制位数
 fb_stat(fbdev, &fb_width, &fb_height, &fb_depth,-1);
 printf("%d %d %d\n",fb_width,fb_height,fb_depth);
 screensize = fb_width* fb_height * fb_depth / 8*2;//计算LCD大小,一帧数据多少个字节
 
 fbmem = fb_mmap(fbdev, screensize);//映射LCD内存
 
 cinfo.err = jpeg_std_error(&jerr);//注册错误处理函数
 jpeg_create_decompress(&cinfo);//创建jpeg对象
 int n=2;
 //while(1)
 {
#if 0
  if(n%2==0)
  {
   fbmem=fbmem+screensize/2;
  }
  else
  {
   fbmem=fbmem-screensize/2;
  }
  n++;
#endif
  //fbmem=fbmem+640*480*2;
  if ((infile = fopen(argv[i], "rb")) == NULL) {//打开jpeg二进制格式文件
   printf("%s\n",argv[i]);   
   fprintf(stderr, "open %s failed\n", argv[1]);
   exit(-1);
  }
  jpeg_stdio_src(&cinfo, infile);//绑定jpeg源文件和jpeg对象
  jpeg_read_header(&cinfo, TRUE);//读取jpeg头信息 
  cinfo.scale_num=1;
  cinfo.scale_denom=1;//压缩比例1:4,
  jpeg_start_decompress(&cinfo);//开始解码
  //if ((cinfo.output_width > fb_width) ||(cinfo.output_height > fb_height))//判断解码后大小
  {
  // printf("too large JPEG file,cannot display\n");
   //return (-1);
  }
  //分配内存,output_components记录的使每像素的颜色数,每种颜色一个字节
  buffer = (unsigned char *) malloc(cinfo.output_width *cinfo.output_components);
  y = 0;

 
  //fb_stat(fbdev, &fb_width, &fb_height, &fb_depth,480);
  while (cinfo.output_scanline < cinfo.output_height) {
   jpeg_read_scanlines(&cinfo, &buffer, 1);//读取行
   if (fb_depth == 16) {
    unsigned short color;
    for (x = 0; x < cinfo.output_width; x++) {//output_width为解码的图片宽度
     //转换颜色
     color = RGB888toRGB565(buffer[x * 3],buffer[x * 3 + 1], buffer[x * 3 + 2]);
     fb_pixel(fbmem, fb_width, fb_height, x, y, color);//填充像素
    }
   }
   else if (fb_depth == 24) {
    memcpy((unsigned char *) fbmem + y * fb_width * 3,
      buffer, cinfo.output_width * cinfo.output_components);
   }
   y++; // 下一行图片
  } 
  //关闭文件
  fclose(infile); 
  //完成转换,并释放对象
  jpeg_finish_decompress(&cinfo);
  i++;
  if(i>=argc)
  {
   i=1;
  }
  fb_stat(fbdev, &fb_width, &fb_height, &fb_depth,0);
  sleep(1);
 } 
 
 jpeg_destroy_decompress(&cinfo);
 //释放行缓冲区
 free(buffer);
 
 //释放framebuffer内存
 fb_munmap(fbmem, screensize);
 //关闭LCD设备
 fb_close(fbdev);
 return (0);
}

void usage(char *msg)
{
 fprintf(stderr, "%s\n", msg);
 printf("Usage: fv some-jpeg-file.jpg\n");
}
//从24真彩色转换为16位真彩色
unsigned short RGB888toRGB565(unsigned char red, unsigned char green, unsigned char blue)
{
 unsigned short B = (blue >> 3) & 0x001F;//取高5位
 unsigned short G = ((green >> 2) << 5) & 0x07E0;//取高6位,并移动位置
 unsigned short R = ((red >> 3) << 11) & 0xF800;//取高5位并移动位置
 return (unsigned short) (R | G | B);//合并为16的像素数据
}
//打开framebuffer设备并返回打开的设备号
int fb_open(char *fb_device)
{
 int fd;
 if ((fd = open(fb_device, O_RDWR)) < 0) {
  perror(__func__);
  return (-1);
 }
 return (fd);
}
//获取framebuffer的信息:宽度、高度、每像素二进制位数
int fb_stat(int fd, int *width, int *height, int *depth,int yoffset)
{
 //FBIOGET_FSCREENINFO和FBIOGET_VSCREENINFO。前者返回与Framebuffer有关的固定的信息,比如图形硬件上实际的帧缓存空间的大小、能否硬件加速等信息。而后者返回的是与Framebuffer有关的可变信息。
 struct fb_fix_screeninfo fb_finfo;
 struct fb_var_screeninfo fb_vinfo;
 if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_finfo)) {//返回framebuffer物理信息
  perror(__func__);
  return (-1);
 }
 if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {////返回framebuffer可变信息
  perror(__func__);
  return (-1);
 }
 *width = fb_vinfo.xres;//宽度
 *height = fb_vinfo.yres;//高度
 *depth = fb_vinfo.bits_per_pixel;//var.bits_per_pixel为16每像素二进制位数
 
 printf("%d\n",fb_vinfo.yres_virtual);
 if(yoffset<0)
 {
  return (0);
 }
 fb_vinfo.yoffset=yoffset;
 if (ioctl(fd,FBIOPAN_DISPLAY, &fb_vinfo)) {////返回framebuffer可变信息
  perror(__func__);
  return (-1);
 }
 if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {////返回framebuffer可变信息
  perror(__func__);
  return (-1);
 }
 printf("%d\n",fb_vinfo.yoffset);
 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);//返回缓冲区指针
}
//释放framebuffer内存
int fb_munmap(void *start, size_t length)
{
 return (munmap(start, length));
}
//关闭LCD
int fb_close(int fd)
{
 return (close(fd));
}
//显示像素fbmem为framebuffer内存缓冲区,width为LCD宽度,height为LCD高度,x,为写入的行位置,y为写入的行
int fb_pixel(void *fbmem, int width, int height,int x, int y, unsigned short color)
{
 if ((x > width) || (y > height))
  return (-1); 
 //(unsigned short *) fbmem强制转换为整形
 unsigned short *dst = ((unsigned short *) fbmem + y * width + x);//计算位置
 //printf("%x %x\n",dst,((unsigned short *) fbmem + y * width + x));
 *dst = color;
 return (0);
}

原创粉丝点击