当前位置: 首页 > 工具软件 > LibJPEG > 使用案例 >

libjpeg编译使用详解

宋望
2023-12-01
一、交叉编译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\n", FB_DEVICE_NAME);
}


ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
if (ret < 0)
{
DBG_PRINTF("can't get fb's var\n");
return -1;
}


ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
if (ret < 0)
{
DBG_PRINTF("can't get fb's fix\n");
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\n");
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\n");
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\n", 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\n", 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: \n");
printf("%s <jpg_file>\n", 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\n", argv[1]);
return -1;
}
jpeg_stdio_src(&cinfo, infile);

// 用jpeg_read_header获得jpg信息
jpeg_read_header(&cinfo, TRUE);
/* 源信息 */
printf("image_width = %d\n", cinfo.image_width);
printf("image_height = %d\n", cinfo.image_height);
printf("num_components = %d\n", cinfo.num_components);

// 设置解压参数,比如放大、缩小
printf("enter scale M/N:\n");
scanf("%d/%d", &cinfo.scale_num, &cinfo.scale_denom);
printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom);

// 启动解压:jpeg_start_decompress
jpeg_start_decompress(&cinfo);

/* 输出的图象的信息 */
printf("output_width = %d\n", cinfo.output_width);
printf("output_height = %d\n", cinfo.output_height);
printf("output_components = %d\n", 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驱动才以前驱动部分已经讲得很明白了。

 类似资料: