我的摄像头不支持直接取jpeg图片,读取的原始数据是YUYV格式,要在内存中转换成RGB24后,再存为jpeg图片。可以到www.ijg.org网站下载libjpeg的源码。
一、准备工作
下载好源码之后编译之后可以得到libjpeg的静态链接库(.a)和动态链接库(.so),如图:
使用的时候把源代码里面的jconfig.h,jmorecfg.h,jpeglib.h这三个文件放到自己项目的路径下,在自己的程序里面添加头文件,#include “jpeglib.h” 。编译的时候添加一下你刚刚编译得到的库文件libjpeg.so和libjpeg.so.9.1.0的路径即可。要注意不同的运行环境需要不同的编译器,如果是arm中运行,就需要指定交叉编译工具。
1. PC下编译libjpeg
先解压tar xvfz jpegsrc.v9a.tar.gz,解压得到的源码里面有一个install.txt介绍说如果是UNIX系统就只需要:
#./configure
#make
#make test (test是用来自检验是否安装成功的)
#make install
我按照此步骤安装之后没找到库文件的位置,就自己指定路径重新编译了一下。
#./configure --prefix=/usr/local/jpeg --enable-shared--enable-static
2. 使用arm-linux-gcc来交叉编译arm环境中的libjpeg
#./configure --prefix=/opt/Cubieboard/jpeg --host=arm-linuxCC=arm-linux-gnueabihf-gcc --enable-shared --enable-static
#make
#make install
参数--enable-shared --enable-static 对静态链接库和动态链接库都支持。linux库文件分为静态库和动态库两种。静态库习惯以.a 结尾,而动态库习惯以.so(shared object)结尾。而且必须以lib开头。
http://blog.chinaunix.net/uid-22125732-id-1790604.html
二、 jpeg压缩步骤
压缩和解压缩步骤:
int save_rgb_to_jpg(char *soureceData, int imgWidth, int imgHeight, char * fileName)
{
int depth = 3;//1 for gray, 3 for color
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *outfile;
JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
int row_stride = imgWidth; // physical row width in image buffer
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if ((outfile = fopen(fileName, "wb")) == NULL)
{
fprintf(stderr, "can't open %s\n", fileName);
return -1;
}
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = imgWidth; // image width and height, in pixels
cinfo.image_height = imgHeight;
cinfo.input_components = depth; // of color components per pixel
cinfo.in_color_space = JCS_RGB; //or JCS_GRAYSCALE; colorspace of input image
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE ); /* limit to baseline-JPEG values */
jpeg_start_compress(&cinfo, TRUE);
row_stride = imgWidth; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height)
{
row_pointer[0] = & soureceData[cinfo.next_scanline * row_stride*depth];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
fclose(outfile);
return 0;
}
http://blog.itpub.net/7232789/viewspace-714150/
http://blog.csdn.net/limingshandian/article/details/7751300
三、编译自己的工程
#arm-linux-gnueabihf-gcc -o myjpg myjpg.c -L/usr/local/jpeg/lib-ljpeg -Wl,-rpath,/usr/local/jpeg/lib
-L是指定编译时链接库的路径。-ljpeg指定编译时的链接库名称,在链接时候,加上选项-l后接库文件名,注意:必须是文件名去掉后缀和lib。不加-L则编译器默认在/lib和/usr/lib路径下寻找,当然,编译器会告诉你“找不到XXX.so”。
-Wl,-rpath,/usr/local/jpeg/lib这三个用逗号隔开的参数是告诉ld执行的时候到该路径下寻找库。最开始我没有加上这个参数,编译的时候没有出错,但是执行的时候提示ld找不到XXX.so。
使用ldd查看链接库的路径,如:
#ldd myjpg
可以看到目标文件的链接库的路径
http://blog.sina.com.cn/s/blog_690c46500100kxhd.html
四、遇到的问题
1. jpg的文件名中不能有冒号。
这个让我排查了好久。最初我是在开发板上,插上U盘,想直接把文件写到U盘中(/mnt/usb下),一开始还以为不能直接写到U盘。觉得开发板调试太慢,就把程序放到host中去调试,那么问题就来了,U盘插上去以后,自动在/media/下生成一个目录/D48D-12AB,于是我就直接写入/media//D48D-12AB下,又失败了。
2. 不能直接写或者cp来操作/media/ D48D-12AB中的文件。
就是说这个路径下你只能通过鼠标右键的方式进行操作。