libjpeg的交叉编译以及jpeg图片的缩放(缩略图)

libjpeg库的交叉编译

libjpeg库主要用于jpeg格式图片的编解码,其交叉编译过程如下

1.  下载源码

从官方网站http://www.ijg.org/files/ 下载libjpeg库的源码,本次编译过程使用的是jpegsrc.v9a.tar.gz

2. 解压源码

2.1 切换到下载目录,执行

 tar -xzvf jpegsrc.v9a.tar.gz 

2.2 切换到源码目录

 cd jpeg-9a/ 

3. 交叉编译

3.1 设置交叉编译器的环境变量

export CC=/home/jarvischu/arm-linux-uclibcgnueabi-gcc

3.2 执行configure,其中–prefix 用来指定编译结果的存放位置; –host 用来指明交叉编译

./configure --prefix=/home/jarvischu/jpeg --enable-shared --enable-static --host=arm-unknown-linux

3.3 执行make命令

make

3.4 执行make install 命令

 sudo make install 

至此,交叉编译结束,编译结果存放在/home/jarvischu/jpeg目录下,该目录包含了编译得到的lib和include

 

使用libjpeg库实现jpeg图片的缩放(缩略图)


#include <stdio.h>
#include "jpeglib.h"
#include <setjmp.h>

struct my_error_mgr {
  struct jpeg_error_mgr pub;	/* "public" fields */

  jmp_buf setjmp_buffer;	/* for return to caller */
};

typedef struct my_error_mgr * my_error_ptr;

/*
 * Here's the routine that will replace the standard error_exit method:
 */

METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  my_error_ptr myerr = (my_error_ptr) cinfo->err;

  /* Always display the message. */
  /* We could postpone this until after returning, if we chose. */
  (*cinfo->err->output_message) (cinfo);

  /* Return control to the setjmp point */
 longjmp(myerr->setjmp_buffer, 1);
}

//读取Jpeg图片的数据并返回,如果出错,返回NULL
unsigned char* ReadJpeg(const char* path, int& width, int& height)
{
	FILE *file = fopen( path, "rb" );
	if ( file == NULL )	{
		return NULL;
	}

	struct jpeg_decompress_struct info; //for our jpeg info

// 	struct jpeg_error_mgr err; //the error handler
// 	info.err = jpeg_std_error(&err);

	 struct my_error_mgr my_err;

	 info.err = jpeg_std_error(&my_err.pub);
	 my_err.pub.error_exit = my_error_exit;

	 /* Establish the setjmp return context for my_error_exit to use. */
	 if (setjmp(my_err.setjmp_buffer)) {
		 /* If we get here, the JPEG code has signaled an error.
		 * We need to clean up the JPEG object, close the input file, and return.
		 */
		 printf("Error occured\n");
		 jpeg_destroy_decompress(&info);
		 fclose(file);
		 return NULL;
	 }

	jpeg_create_decompress( &info ); //fills info structure
	jpeg_stdio_src( &info, file );        //void

	int ret_Read_Head = jpeg_read_header( &info, 1 ); //int

	if(ret_Read_Head != JPEG_HEADER_OK){
		printf("jpeg_read_header failed\n");
		fclose(file);
		jpeg_destroy_decompress(&info);
		return NULL;
	}

	bool bStart = jpeg_start_decompress( &info );
	if(!bStart){
		printf("jpeg_start_decompress failed\n");
		fclose(file);
		jpeg_destroy_decompress(&info);
		return NULL;
	}
	int w = width = info.output_width;
	int h = height = info.output_height;
	int numChannels = info.num_components; // 3 = RGB, 4 = RGBA
	unsigned long dataSize = w * h * numChannels;

	// read RGB(A) scanlines one at a time into jdata[]
	unsigned char *data = (unsigned char *)malloc( dataSize );
	if(!data) return NULL;

	unsigned char* rowptr;
	while ( info.output_scanline < h )
	{
		rowptr = data + info.output_scanline * w * numChannels;
		jpeg_read_scanlines( &info, &rowptr, 1 );
	}

	jpeg_finish_decompress( &info );    

	fclose( file );

	return data;
}

/*参数为:
 *返回图片的宽度(w_Dest),
 *返回图片的高度(h_Dest),
 *返回图片的位深(bit_depth),
 *源图片的RGB数据(src),
 *源图片的宽度(w_Src),
 *源图片的高度(h_Src)
 */
unsigned char* do_Stretch_Linear(int w_Dest,int h_Dest,int bit_depth,unsigned char *src,int w_Src,int h_Src)
{
	int sw = w_Src-1, sh = h_Src-1, dw = w_Dest-1, dh = h_Dest-1;
	int B, N, x, y;
	int nPixelSize = bit_depth/8;
	unsigned char *pLinePrev,*pLineNext;
	unsigned char *pDest = new unsigned char[w_Dest*h_Dest*bit_depth/8];
	unsigned char *tmp;
	unsigned char *pA,*pB,*pC,*pD;

	for(int i=0;i<=dh;++i)
	{
		tmp =pDest + i*w_Dest*nPixelSize;
		y = i*sh/dh;
		N = dh - i*sh%dh;
		pLinePrev = src + (y++)*w_Src*nPixelSize;
		//pLinePrev =(unsigned char *)aSrc->m_bitBuf+((y++)*aSrc->m_width*nPixelSize);
		pLineNext = (N==dh) ? pLinePrev : src+y*w_Src*nPixelSize;
		//pLineNext = ( N == dh ) ? pLinePrev : (unsigned char *)aSrc->m_bitBuf+(y*aSrc->m_width*nPixelSize);
		for(int j=0;j<=dw;++j)
		{
			x = j*sw/dw*nPixelSize;
			B = dw-j*sw%dw;
			pA = pLinePrev+x;
			pB = pA+nPixelSize;
			pC = pLineNext + x;
			pD = pC + nPixelSize;
			if(B == dw)
			{
				pB=pA;
				pD=pC;
			}

			for(int k=0;k<nPixelSize;++k)
			{
				*tmp++ = ( unsigned char )( int )(
					( B * N * ( *pA++ - *pB - *pC + *pD ) + dw * N * *pB++
					+ dh * B * *pC++ + ( dw * dh - dh * B - dw * N ) * *pD++
					+ dw * dh / 2 ) / ( dw * dh ) );
			}
		}
	}
	return pDest;
}

bool write_JPEG_file (const char * filename, unsigned char* image_buffer, int quality,int image_height, int image_width)
{

	if(filename == NULL || image_buffer == NULL) return false;

	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	FILE * outfile;		/* target file */
	JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
	int row_stride;		/* physical row width in image buffer */
	cinfo.err = jpeg_std_error(&jerr);
	/* Now we can initialize the JPEG compression object. */
	jpeg_create_compress(&cinfo);

	if ((outfile = fopen(filename, "wb")) == NULL) {
		fprintf(stderr, "can't open %s\n", filename);
		return false;
	}
	jpeg_stdio_dest(&cinfo, outfile);

	cinfo.image_width = image_width; 	/* image width and height, in pixels */
	cinfo.image_height = image_height;
	cinfo.input_components = 3;		/* # of color components per pixel */
	cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */

	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

	jpeg_start_compress(&cinfo, TRUE);

	row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */

	while (cinfo.next_scanline < cinfo.image_height) {
		row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

	jpeg_finish_compress(&cinfo);
	fclose(outfile);

	jpeg_destroy_compress(&cinfo);

	return true;
}

//生成图片的缩略图(图片的一个缩小版本)
 bool generate_image_thumbnail(const char* inputFile, const char* outputFile)
{
	if(inputFile == NULL || outputFile == NULL) return false;

	//读取jpeg图片像素数组
	int w=0,h=0;
	unsigned char* buff = ReadJpeg(inputFile,w,h);
	if(buff == NULL) {
		printf("ReadJpeg Failed\n");
		return false;
	}

	//缩放图片,缩放后的大小为(tb_w,tb_h)
	int tb_w = 160, tb_h = 160;
	unsigned char * img_buf = do_Stretch_Linear(tb_w,tb_h,24,buff,w,h);
	free(buff);

	//将缩放后的像素数组保存到jpeg文件
	bool bRetWrite = write_JPEG_file(outputFile,img_buf,10,tb_h,tb_w);
	delete[] img_buf;

	if(bRetWrite){
		return true;
	}else{
		printf("GenerateImageThumbnail: write failed\n");
		return true;
	}
}

作者:JarvisChu
原文链接:libjpeg的交叉编译以及jpeg图片的缩放(缩略图)
版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0

2 条评论

  • Opera Campaign 18 36.0.2130.65 Opera Campaign 18 36.0.2130.65 Windows 7 Windows 7
    Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 OPR/36.0.2130.65 (Edition Campaign 18)

    代码还是相当给力的,完美的解决了我的问题。
    但是有个小bug,如下函数最后两个参数写反了
    bool write_JPEG_file (const char * filename, unsigned char* image_buffer, int quality,int image_height, int image_width)
    应该是:
    bool write_JPEG_file (const char * filename, unsigned char* image_buffer, int quality,int image_width, int image_height)

    回复

发表评论