android mjpg格式,Camera常用格式MJPEG和jpeg-turbo库

雍光远
2023-12-01

sam_code@hotmail.com

USB Camera在通过V4L2接口获取Camera数据时,有多种图像格式可选择。但最常用的却是YUV和MJPEG.

又因为YUV图片所占空间大,在超过640x480情况下,会超过USB数据传输带宽。

所以只能使用MJPEG.

现在就谈谈MJPEG相关内容。

1. 视频压缩格式:

1.1:JPEG (Joint Photographic Experts Group)压缩技术是所有图像压缩技术的基础。

它适合静态图像的压缩,直接处理整幅画面,压缩倍数为20-80倍,分辨率没有选择的余地。在传输中,必须要等整个压缩档传输完成才可以解压,这就造成传输时间较长。它是帧内压缩。

1.2. MJPEG(Motion JPEG):

在JPEG基础上发展起来的动态图像压缩技术,也是帧内压缩,只单独的对某一帧进行压缩,而基本不考虑视频流中不同帧之间的变化。其压缩后的图像还可以任意剪切。

Motion JPEG, 即动态JPEG.

按一定帧数使用JPEG算法压缩视频信号,完成动态视频的压缩。MJPEG图像流的单元就是一帧一帧的JPEG画片。

因为每帧可以任意存取,所以MJPEG常用于视频编辑系统。

1.3. MPEG:

其实是一个标准。

其中MPEG-4. 它会使用帧间数据。压缩比很高。应用广泛。

2. libjpeg-turbo:

jpeg, Mjpeg的压缩和解压,比较耗费CPU。

所以就有了libjpeg-turbo库,它可以更快的压缩和解压jpeg数据。

因为是帧内压缩,所以可以对JPEG数据进行各种处理,如放大/缩小,翻转,剪切,镜像等。

2.1: libjpeg-turbo 对JPEG的压缩和解压:

libjpeg-turbo提供压缩(Compress)和解压(Decompress)接口。

同时,它还有个概念----Transform.

2.1.1: 压缩:

给定RGB data. 把它压缩成指定jpeg文件。

A. 打开一个压缩实例:

tjhandle tjInitCompress(void)

B. 把给定pixel,w,h pitch等信息的数据,压缩成jpeg(给定sample,质量)数据。

int tjCompress2(tjhandle handle, const unsigned char

*srcBuf,

int width, int pitch, int height, int

pixelFormat,

unsigned char **jpegBuf, unsigned long

*jpegSize,

int jpegSubsamp, int jpegQual, int flags)

C. 销毁实例:

int tjDestroy(tjhandle handle)

2.1.2:解压:

把给定的JPEG数据,解压成RGB数据:

这个过程,只是简单的解压,或者仅仅是图片大小变化。

A. 打开一个解码实例

tjInstance = tjInitDecompress();

B. 通过读取到的jpeg数据,来分析文件头,获取图像信息(长宽,sample, colour信息等)

int tjDecompressHeader3(tjhandle handle,

const unsigned char

*jpegBuf,

unsigned long jpegSize, int

*width,

int *height, int

*jpegSubsamp,

int *jpegColorspace)

jpegBuf是jpeg数据。

C. 解压到指定格式,指定长宽数据:

int tjDecompress2(tjhandle handle, const unsigned char

*jpegBuf,

unsigned long jpegSize,

unsigned char *dstBuf,

int width, int pitch, int

height, int pixelFormat,

int flags)

width, height: 目标图像长宽。

pixelFormat: 目标图像格式, enum TJPF

中定义,如RGBX。

此时,dstBuf中的内容,就是解压过的,指定大小,深度,和图像格式的图片数据了。

如果指定为RGBX,则直接存文件即为BMP文件。

D. 销毁实例:

int tjDestroy(tjhandle handle)

2.1.3:Transform:

Transform是干什么呢,Sam觉得是因为要实质修改JPEG数据,重新排列。

比如剪切,翻转,镜像。这些动作叫做Transform.

A. 打开一个transform实例:

tjhandle tjInitTransform(void)

B. Transform转换:

tjtransform xform; //指定transform的参数,如裁剪区域

想要裁剪:

xform.r.x = iX; //左上角位置

xform.r.y = iY;

xform.r.h , xform.r.w //区域高度。

xform.options |= TJXOPT_CROP; //指定要剪切。

int tjTransform(tjhandle handle, const unsigned char

*jpegBuf,

unsigned long jpegSize, int n,

unsigned char **dstBufs, unsigned long

*dstSizes,

tjtransform *t, int flags)

dstBufs中保存这transform后的数据。

C. 可选: 获取新的jpeg数据信息:

DLLEXPORT int tjDecompressHeader3(tjhandle handle,

const unsigned char

*jpegBuf,

unsigned long jpegSize, int

*width,

int *height, int

*jpegSubsamp,

int *jpegColorspace)

D. 后续可以随意处理jpeg数据了。如解压。

E. 销毁:

int tjDestroy(tjhandle handle)

2.2: libjpeg-turbo对图像文件的处理:

unsigned char *tjLoadImage(const char *filename, int

*width,

int align, int *height, int *pixelFormat,

int flags)

int tjSaveImage(const char *filename, unsigned char

*buffer,

int width, int pitch, int height, int

pixelFormat,

int flags)

2.3:获取放大缩小factor:

libjpet-turbo并不可以随意比例放大缩小,而是指定了一系列(16个)比例系数。

可以先获取这个列表:

scalingFactors =

tjGetScalingFactors(&numScalingFactors);

if(scalingFactors == NULL)

{

printf("\nGet Scaling Factor Error.\n");

return -1;

}

printf("\nThere are [%d] ScalingFactors\n",

numScalingFactors);

for(int i = 0; i < numScalingFactors; i++)

{

printf("\t Numerator/Denominator is:[%d/%d]\n",

scalingFactors[i].num, scalingFactors[i].denom);

}

此时就可以得到turbo-jpeg给定的Scaling Factor.

 类似资料: