RGB24转jpeg

   我的摄像头不支持直接取jpeg图片,读取的原始数据是YUYV格式,要在内存中转换成RGB24后,再存为jpeg图片。可以到<a target=_blank href="http://www.ijg.org/" target="_blank">www.ijg.org</a>网站下载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.youkuaiyun.com/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中的文件。
   就是说这个路径下你只能通过鼠标右键的方式进行操作。
RGB565是一种颜色编码格式,它使用16位来表示一个像素的颜色信息,其中5位用来表示红色分量,6位用来表示绿色分量,5位用来表示蓝色分量。而JPEG是一种图像压缩格式,它可以将图像数据压缩成较小的文件尺寸,同时保持图像质量。因此,将RGB565格式的图像换成JPEG格式,需要进行以下步骤: 1. 将RGB565格式的图像数据解码成RGB24格式,即每个像素使用24位来表示颜色信息。这可以通过将每个像素的5位红色分量、6位绿色分量和5位蓝色分量进行扩展得到。 2. 将RGB24格式的图像数据压缩成JPEG格式。这可以使用JPEG编码库,如libjpeg等。 下面是一个使用libjpeg库将RGB565格式的图像换成JPEG格式的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <jpeglib.h> void rgb565_to_rgb24(unsigned char *rgb565_data, unsigned char *rgb24_data, int width, int height) { int i, j; unsigned short rgb565; unsigned char r, g, b; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { // get RGB565 color from data rgb565 = (rgb565_data[(i * width + j) * 2] << 8) | rgb565_data[(i * width + j) * 2 + 1]; // expand to RGB24 format r = (rgb565 >> 11) << 3; g = ((rgb565 >> 5) & 0x3f) << 2; b = (rgb565 & 0x1f) << 3; rgb24_data[(i * width + j) * 3] = r; rgb24_data[(i * width + j) * 3 + 1] = g; rgb24_data[(i * width + j) * 3 + 2] = b; } } } int rgb24_to_jpeg(unsigned char *rgb24_data, int width, int height, int quality, char *filename) { int i, j; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; FILE *outfile; unsigned char *image_buffer; int image_size; // allocate memory for image buffer image_size = width * height * 3; image_buffer = (unsigned char *)malloc(image_size); // initialize JPEG compression object cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); // open output file if ((outfile = fopen(filename, "wb")) == NULL) { fprintf(stderr, "Can't open %s\n", filename); return 0; } jpeg_stdio_dest(&cinfo, outfile); // set image parameters cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); // start compression jpeg_start_compress(&cinfo, TRUE); // write image data for (i = 0; i < height; i++) { row_pointer[0] = &rgb24_data[i * width * 3]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } // finish compression jpeg_finish_compress(&cinfo); // release resources fclose(outfile); jpeg_destroy_compress(&cinfo); free(image_buffer); return 1; } int main() { int width = 320; int height = 240; int quality = 80; unsigned char *rgb565_data = (unsigned char *)malloc(width * height * 2); unsigned char *rgb24_data = (unsigned char *)malloc(width * height * 3); char *filename = "output.jpg"; // TODO: fill rgb565_data with actual data // convert RGB565 to RGB24 rgb565_to_rgb24(rgb565_data, rgb24_data, width, height); // compress RGB24 to JPEG rgb24_to_jpeg(rgb24_data, width, height, quality, filename); // release resources free(rgb565_data); free(rgb24_data); return 0; } ``` 以上代码仅供参考,实际应用中可能需要根据具体需求进行修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值