libjpeg编译使用详解

一、交叉编译libjpeg

# tar -xzvf libjpeg-turbo-1.2.1.tar.gz   

#cd libjpeg-turbo-1.2.1

#mkdir tmp

# ./configure --prefix=$PWD/tmp --host=arm-linux  
#make  
#make install                /* 会安装在当前目录下面tmp目录里面 */   

二、交叉编译jpg2rgb.c
方法一:编译器后面直接跟上头文件,库文件。路径是我们开始编译出来的路径。
arm-linux-gcc -o jpg2rgb jpg2rgb.c -I /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/include  -L /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/lib  -ljpeg
cp jpg2rgb /work/nfs_root/fs_mini_mdev_new
cp libjpeg-turbo-1.2.1/tmp/lib/so /work/nfs_root/fs_mini_mdev_new/lib/ -d

方法二:把库文件,头文件放在交叉编译里面库文件,头文件的路径下面。
把编译出来的头文件应该放入:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include
cd  /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/include

cp  *   /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include

把编译出来的库文件应该放入:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib

cd  /home/book/workspace/project/libjpeg-turbo-1.2.1/tmp/lib
cp so  -d   /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib

 cp so /work/nfs_root/      / 把库文件复制到开发板lib目录下,我们用的是动态库所以需要拷贝 /

arm-linux-gcc -o jpg2rgb jpg2rgb.c -ljpeg      / 要指定jpeg库,数学库则指定m /

 jpg2rgb.c文件如下:

#include <stdio.h>  
#include "jpeglib.h"  
#include <setjmp.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <sys/ioctl.h>  
#include <sys/mman.h>  
#include <linux/fb.h>  
#include <string.h>  
#include <stdlib.h>  


#define FB_DEVICE_NAME "/dev/fb0"   /* 指定lcd驱动自动创建的设别节点名 */  
#define DBG_PRINTF  printf                /* 方便调试打印 */  
  
static int g_fd;  
static struct fb_var_screeninfo g_tFBVar;    /* lcd相关的参数,在这篇文章中重点是libjpeg */  
static struct fb_fix_screeninfo g_tFBFix;  
static unsigned char *g_pucFBMem;  
static unsigned int g_dwScreenSize;  
  
static unsigned int g_dwLineWidth;  
static unsigned int g_dwPixelWidth;  
  
static int FBDeviceInit(void)  
{  
int ret;  
  
g_fd = open(FB_DEVICE_NAME, O_RDWR);  
if (0 > g_fd)  
{  
DBG_PRINTF("can"t open %s
", FB_DEVICE_NAME);  
}  
  
  
ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);  
if (ret < 0)  
{  
DBG_PRINTF("can"t get fb"s var
");  
return -1;  
}  
  
  
ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);  
if (ret < 0)  
{  
DBG_PRINTF("can"t get fb"s fix
");  
return -1;  
}  
  
g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;  
g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);  
if (0 > g_pucFBMem)  
{  
DBG_PRINTF("can"t mmap
");  
return -1;  
}  
  
  
g_dwLineWidth  = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;  
g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;  
  
return 0;  
}  
  
static int FBShowPixel(int iX, int iY, unsigned int dwColor)  
{  
unsigned char *pucFB;  
unsigned short *pwFB16bpp;  
unsigned int *pdwFB32bpp;  
unsigned short wColor16bpp; /* 565 */  
int iRed;  
int iGreen;  
int iBlue;  
  
  
if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))  
{  
DBG_PRINTF("out of region
");  
return -1;  
}  
  
  
pucFB      = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;  
pwFB16bpp  = (unsigned short *)pucFB;  
pdwFB32bpp = (unsigned int *)pucFB;  
  
switch (g_tFBVar.bits_per_pixel)  
{  
case 8:  
{  
*pucFB = (unsigned char)dwColor;  
break;  
}  
case 16:  
{  
iRed   = (dwColor >> (16+3)) & 0x1f;  
iGreen = (dwColor >> (8+2)) & 0x3f;  
iBlue  = (dwColor >> 3) & 0x1f;  
wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;  
*pwFB16bpp= wColor16bpp;  
break;  
}  
case 32:  
{  
*pdwFB32bpp = dwColor;  
break;  
}  
default :  
{  
DBG_PRINTF("can"t support %d bpp
", g_tFBVar.bits_per_pixel);  
return -1;  
}  
}  
  
  
return 0;  
}  
  
static int FBCleanScreen(unsigned int dwBackColor)  
{  
unsigned char *pucFB;  
unsigned short *pwFB16bpp;  
unsigned int *pdwFB32bpp;  
unsigned short wColor16bpp; /* 565 */  
int iRed;  
int iGreen;  
int iBlue;  
int i = 0;  
pucFB      = g_pucFBMem;  
pwFB16bpp  = (unsigned short *)pucFB;  
pdwFB32bpp = (unsigned int *)pucFB;  
  
switch (g_tFBVar.bits_per_pixel)  
{  
case 8:  
{  
memset(g_pucFBMem, dwBackColor, g_dwScreenSize);  
break;  
}  
case 16:  
{  
iRed   = (dwBackColor >> (16+3)) & 0x1f;  
iGreen = (dwBackColor >> (8+2)) & 0x3f;  
iBlue  = (dwBackColor >> 3) & 0x1f;  
wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;  
while (i < g_dwScreenSize)  
{  
*pwFB16bpp= wColor16bpp;  
pwFB16bpp++;  
i += 2;  
}  
break;  
}  
case 32:  
{  
while (i < g_dwScreenSize)  
{  
*pdwFB32bpp= dwBackColor;  
pdwFB32bpp++;  
i += 4;  
}  
break;  
}  
default :  
{  
DBG_PRINTF("can"t support %d bpp
", g_tFBVar.bits_per_pixel);  
return -1;  
}  
}  
  
  
return 0;  
}  
  
static int FBShowLine(int iXStart, int iXEnd, int iY, unsigned char *pucRGBArray)  
{  
int i = iXStart * 3;  
int iX;  
unsigned int dwColor;  
  
if (iY >= g_tFBVar.yres)  
return -1;  
  
if (iXStart >= g_tFBVar.xres)  
return -1;  
  
if (iXEnd >= g_tFBVar.xres)  
{  
iXEnd = g_tFBVar.xres;  
}  
  
for (iX = iXStart; iX < iXEnd; iX++)  
{  
/* 0xRRGGBB */  
dwColor = (pucRGBArray[i]<<16) + (pucRGBArray[i+1]<<8) + (pucRGBArray[i+2]<<0);  
i += 3;  
FBShowPixel(iX, iY, dwColor);  
}  
return 0;  
}  
  
/* 下面才是本文的重点 */  
/*  
Allocate and initialize a JPEG decompression object    // 分配和初始化一个decompression结构体  
Specify the source of the compressed data (eg, a file) // 指定源文件  
Call jpeg_read_header() to obtain image info  // 用jpeg_read_header获得jpg信息  
Set parameters for decompression  // 设置解压参数,比如放大、缩小  
jpeg_start_decompress(...);   // 启动解压:jpeg_start_decompress  
while (scan lines remain to be read)  
jpeg_read_scanlines(...);  // 循环调用jpeg_read_scanlines  
jpeg_finish_decompress(...);  // jpeg_finish_decompress  
Release the JPEG decompression object  // 释放decompression结构体  
*/  
  
  
/* Uage: jpg2rgb <jpg_file>  
 */  
  
int main(int argc, char **argv)  
{  
struct jpeg_decompress_struct cinfo;  
struct jpeg_error_mgr jerr;  
FILE * infile;  
int row_stride;  
unsigned char *buffer;  
  

if (argc != 2)  
{  
printf("Usage: 
");  
printf("%s <jpg_file>
", argv[0]);  
return -1;  
}  
  
if (FBDeviceInit())     /* 初始化Lcd */  
{  
return -1;  
}  
  
FBCleanScreen(0);      /* 清屏lcd */  
  
// 分配和初始化一个decompression结构体  
cinfo.err = jpeg_std_error(&jerr);  
jpeg_create_decompress(&cinfo);  
  
// 指定源文件  
if ((infile = fopen(argv[1], "rb")) == NULL) {  
fprintf(stderr, "can"t open %s
", argv[1]);  
return -1;  
}  
jpeg_stdio_src(&cinfo, infile);  
  
// 用jpeg_read_header获得jpg信息  
jpeg_read_header(&cinfo, TRUE);  
/* 源信息 */  
printf("image_width = %d
", cinfo.image_width);  
printf("image_height = %d
", cinfo.image_height);  
printf("num_components = %d
", cinfo.num_components);  
  
// 设置解压参数,比如放大、缩小  
printf("enter scale M/N:
");  
scanf("%d/%d", &cinfo.scale_num, &cinfo.scale_denom);  
printf("scale to : %d/%d
", cinfo.scale_num, cinfo.scale_denom);  
  
// 启动解压:jpeg_start_decompress  
jpeg_start_decompress(&cinfo);  
  
/* 输出的图象的信息 */  
printf("output_width = %d
", cinfo.output_width);  
printf("output_height = %d
", cinfo.output_height);  
printf("output_components = %d
", cinfo.output_components);  
  
// 一行的数据长度  
row_stride = cinfo.output_width * cinfo.output_components;  
buffer = malloc(row_stride);  
  
// 循环调用jpeg_read_scanlines来一行一行地获得解压的数据  
while (cinfo.output_scanline < cinfo.output_height)   
{  
(void) jpeg_read_scanlines(&cinfo, &buffer, 1);  
  
// 写到LCD去  
FBShowLine(0, cinfo.output_width, cinfo.output_scanline, buffer);  
}  
  
free(buffer);  
jpeg_finish_decompress(&cinfo);  
jpeg_destroy_decompress(&cinfo);  
  
return 0;  
}  

上文中红色以下的才是本文的重点,lcd驱动才以前驱动部分已经讲得很明白了。

文章导航