libjpeg-turbo可以看成是libjpeg的优化加速版,从理论上来说,它所耗费的时间只有libjpeg的1/3。
编译:
tar -zxvf libjpeg-turbo-1.4.3.tar.gz
cd libjpeg-turbo-1.4.3
./configure --prefix=安装目录 --host=编译平台 //我用的是海思平台 arm-hisiv500-linux
make
make install
int tyuv2jpeg(unsigned char* yuv_buffer, int yuv_size, int width, int height, int subsample, unsigned char** jpeg_buffer, unsigned long* jpeg_size, int quality)
{
tjhandle handle = NULL;
int flags = 0;
int padding = 1; //must be 1 or 4
int need_size = 0;
int ret = 0;
handle = tjInitCompress();
flags |= 0;
need_size = tjBufSizeYUV2(width, padding, height, subsample);
if (need_size != yuv_size)
{
printf("we detect yuv size: %d, but you give: %d, check again.\n", need_size, yuv_size);
return 0;
}
ret = tjCompressFromYUV(handle, yuv_buffer, width, padding, height, subsample, jpeg_buffer, jpeg_size, quality, flags);
if (ret < 0)
{
printf("compress to jpeg failed: %s\n", tjGetErrorStr());
}
tjDestroy(handle);
return ret;
}
unsigned char *jpeg_buf = NULL;
tyuv2jpeg(picture, yuv_size, width, height, TJSAMP_420, &jpeg_buf, &jpeg_size, 50); //50:quality
width:图像宽度
height:图像高度
yuv_size:yuv大小,等于width*height*3/2
quality:转换后的图像质量(1~100)
subsample:
enum TJSAMP
{
/**
* 4:4:4 chrominance subsampling (no chrominance subsampling). The JPEG or
* YUV image will contain one chrominance component for every pixel in the
* source image.
*/
TJSAMP_444=0,
/**
* 4:2:2 chrominance subsampling. The JPEG or YUV image will contain one
* chrominance component for every 2x1 block of pixels in the source image.
*/
TJSAMP_422,
/**
* 4:2:0 chrominance subsampling. The JPEG or YUV image will contain one
* chrominance component for every 2x2 block of pixels in the source image.
*/
TJSAMP_420,
/**
* Grayscale. The JPEG or YUV image will contain no chrominance components.
*/
TJSAMP_GRAY,
/**
* 4:4:0 chrominance subsampling. The JPEG or YUV image will contain one
* chrominance component for every 1x2 block of pixels in the source image.
*
* @note 4:4:0 subsampling is not fully accelerated in libjpeg-turbo.
*/
TJSAMP_440,
/**
* 4:1:1 chrominance subsampling. The JPEG or YUV image will contain one
* chrominance component for every 4x1 block of pixels in the source image.
* JPEG images compressed with 4:1:1 subsampling will be almost exactly the
* same size as those compressed with 4:2:0 subsampling, and in the
* aggregate, both subsampling methods produce approximately the same
* perceptual quality. However, 4:1:1 is better able to reproduce sharp
* horizontal features.
*
* @note 4:1:1 subsampling is not fully accelerated in libjpeg-turbo.
*/
TJSAMP_411
};
在TJSAMP中并没有看到420sp的相关信息,因此,如果我们的数据是420sp的话,就需要转换成420p后再进行保存。
YUV420p:先保存Y,再保存U,最后是V
YUV420sp:先保存Y,然后UV交叉保存。又分为NV12和NV21,区别就在于U和V哪个在前哪个在后
图1为420p,图2为420sp(NV12)
//NV21->YUV420P
void yuv420sp_to_yuv420p(unsigned char* yuv420sp, unsigned char* yuv420p, int width, int height)
{
int i, j;
int y_size = width * height;
unsigned char* y = yuv420sp;
unsigned char* uv = yuv420sp + y_size;
unsigned char* y_tmp = yuv420p;
unsigned char* u_tmp = yuv420p + y_size;
unsigned char* v_tmp = yuv420p + y_size * 5 / 4;
// y
memcpy(y_tmp, y, y_size);
// u
for (j = 0, i = 0; j < y_size/2; j+=2, i++)
{
v_tmp[i] = uv[j];
u_tmp[i] = uv[j+1];
}
}
有时候我们还需要一些截图功能,就需要裁剪YUV数据,然后再保存成jpeg
int tailor_yuv(unsigned char* srcframe,unsigned char *dstframe,int startX,int startY,int normal_width,int normal_height,int tailor_width,int tailor_height)
{
if(!srcframe || !dstframe)
return -1;
int i = 0;
int j = 0;
int k = 0;
if(startX % 2 != 0)
startX++;
if(startY % 2 != 0)
startY++;
unsigned char *tmpY = (unsigned char *)malloc(tailor_width*tailor_height);
unsigned char *tmpUV = (unsigned char *)malloc(tailor_width*tailor_height/2);
if(!tmpY || !tmpUV)
return -1;
for(i = startY;i < startY + tailor_height;i++)
{
//copy Y
memcpy(tmpY+j*tailor_width,srcframe + i * normal_width + startX,tailor_width);
j++; //current height num
}
for(i = startY/2;i < (startY + tailor_height)/2;i++)
{
//copy UV
memcpy(tmpUV+k*tailor_width,srcframe + (normal_width * normal_height) + i * normal_width + startX,tailor_width);
k++; //current height num
}
memcpy(dstframe, tmpY, tailor_width*tailor_height);
memcpy(dstframe+tailor_width*tailor_height, tmpUV, tailor_width*tailor_height/2);
free(tmpY);
free(tmpUV);
return 0;
}
startX,startY:裁剪的起始点
normal_width,normal_height:未裁剪前的尺寸
tailor_width,tailor_height:裁剪后的尺寸
原理:先保存Y分量,再保存uv分量,根据起始点和尺寸进行裁剪。