libjpeg学习4:libjpeg-turbo之YUV

原创 2015年07月08日 22:07:14

libjpeg-turbo支持直接从JPEG解压成YUV格式,或者反之。这也是我当初想研究它的一个动力。

看了头文件注释,它是支持YUV444(即宏TJSAMP_444),YUV422(即宏TJSAMP_422),YUV420(即宏TJSAMP_420),YUV400(即宏TJSAMP_440),YUV411(即宏TJSAMP_411)。可惜的是,只支持平面格式(plane),对于交织的如UYVY或特别的如NV12(即YUV420SP)或NV16(即YUV422SP),都没看到有支持。在sourceforge上看邮件列表,发现有些描述,但还没研究过,看发布的源码,也未见有说明,估计是不支持的。

本文简单介绍如何从JPEG解压成YUV格式,以及如何将YUV压缩成JPEG。

libjpeg-turbo使用tjBufSizeYUV2函数计算YUV大小,开始时没注意第二个参数pad,默认传递0,发现没效果,而传1或4,却是可以的。解压后的YUV的格式,是由JPEG图片的采样格式决定的,如果JPEG本身是YUV420,则解压得到的YUV,就是YUV420格式。

示例代码如下:

int tjpeg2yuv(unsigned char* jpeg_buffer, int jpeg_size, unsigned char** yuv_buffer, int* yuv_size, int* yuv_type)
{
    tjhandle handle = NULL;
    int width, height, subsample, colorspace;
    int flags = 0;
    int padding = 1; // 1或4均可,但不能是0
    int ret = 0;

    handle = tjInitDecompress();
    tjDecompressHeader3(handle, jpeg_buffer, jpeg_size, &width, &height, &subsample, &colorspace);

    printf("w: %d h: %d subsample: %d color: %d\n", width, height, subsample, colorspace);
    
    flags |= 0;
    
    *yuv_type = subsample;
    // 注:经测试,指定的yuv采样格式只对YUV缓冲区大小有影响,实际上还是按JPEG本身的YUV格式来转换的
    *yuv_size = tjBufSizeYUV2(width, padding, height, subsample);
    *yuv_buffer =(unsigned char *)malloc(*yuv_size);
    if (*yuv_buffer == NULL)
    {
        printf("malloc buffer for rgb failed.\n");
        return -1;
    }

    ret = tjDecompressToYUV2(handle, jpeg_buffer, jpeg_size, *yuv_buffer, width,
			padding, height, flags);
    if (ret < 0)
    {
        printf("compress to jpeg failed: %s\n", tjGetErrorStr());
    }
    tjDestroy(handle);

    return ret;
}

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; // 1或4均可,但不能是0
    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;
}


另外,该库也支持从RGB转换成YUV,或反之。调用相应的函数即可,不再详述。示例代码如下:

int trgb2yuv(unsigned char* rgb_buffer, int width, int height, unsigned char** yuv_buffer, int* yuv_size, int subsample)
{
    tjhandle handle = NULL;
    int flags = 0;
    int padding = 1; // 1或4均可,但不能是0
    int pixelfmt = TJPF_RGB;
    int ret = 0;

    handle = tjInitCompress();
   
    flags |= 0;

    *yuv_size = tjBufSizeYUV2(width, padding, height, subsample);

    *yuv_buffer =(unsigned char *)malloc(*yuv_size);
    if (*yuv_buffer == NULL)
    {
        printf("malloc buffer for rgb failed.\n");
        return -1;
    }
    ret = tjEncodeYUV3(handle, rgb_buffer, width, 0, height, pixelfmt, *yuv_buffer, padding, subsample, flags);
    if (ret < 0)
    {
        printf("encode to yuv failed: %s\n", tjGetErrorStr());
    }

    tjDestroy(handle);

    return ret;
}

int tyuv2rgb(unsigned char* yuv_buffer, int yuv_size, int width, int height, int subsample, unsigned char** rgb_buffer, int* rgb_size)
{
    tjhandle handle = NULL;
    int flags = 0;
    int padding = 1; // 1或4均可,但不能是0
    int pixelfmt = TJPF_RGB;
    int need_size = 0;
    int ret = 0;

    handle = tjInitDecompress();
   
    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 -1;
    }

    *rgb_size = width*height*tjPixelSize[pixelfmt];

    *rgb_buffer =(unsigned char *)malloc(*rgb_size);
    if (*rgb_buffer == NULL)
    {
        printf("malloc buffer for rgb failed.\n");
        return -1;
    }
    ret = tjDecodeYUV(handle, yuv_buffer, padding, subsample, *rgb_buffer, width, 0, height, pixelfmt, flags);
    if (ret < 0)
    {
        printf("decode to rgb failed: %s\n", tjGetErrorStr());
    }

    tjDestroy(handle);

    return ret;
}


以上代码示例,二级指针均在函数内分配内存,需要调用者自行释放,否则会有内存泄漏。


李迟 7.8




版权声明:本文为迟思堂主人李迟原创文章,如转载请注明出处,并附带原文超链接地址。用于商业用途请付稿费¥100/千字。谢谢。

libjpeg学习3:turbojpeg试用

turbojpeg针对ARM和X86对了优化,宣称其速度是libjpeg的2到4倍。下载其源码,值得称赞的地方是其例子,单元测试很到位。另外是它的注释,或者说是html说明文件,对于宏、函数都有详细的...
  • subfate
  • subfate
  • 2015年07月07日 21:29
  • 3512

libjpeg与turbo libjpeg的使用

LibJpeg作为常用开源库,已有很多相关介绍。
  • delltdk
  • delltdk
  • 2014年05月07日 20:56
  • 3224

libjpeg-turbo-1.2.1.tar.gz

  • 2015年11月24日 11:21
  • 1.67MB
  • 下载

libjpeg-turbo使用实例(编解码jpeg、jpg转bmp、bmp转jpg代码)

libjpeg-turbo库用于jpeg图像编解码,上一节说了编译过程:编译libjpeg-turbo 。现在说说jpeg的编码、解码使用方法。 Windows上GDI接口支持的都是位图格式(DDB\...
  • mfcing
  • mfcing
  • 2016年09月23日 22:12
  • 5956

libjpeg-turbo最新版

  • 2018年01月18日 16:44
  • 1.46MB
  • 下载

libjpeg-turbo解压与压缩JPEG图像原理

libjpeg-turbo 相对于 libjpeg 性能有很大的提升,可以参考 https://bbs.archlinux.org/viewtopic.php?id=99147 libjpeg-tu...
  • gdp12315
  • gdp12315
  • 2015年04月15日 17:04
  • 3630

Android图片压缩库——libjpeg-turbo

为何Android图片压缩效率低
  • talkxin
  • talkxin
  • 2016年02月27日 20:41
  • 10775

libjpeg-turbo的neon功能

libjpeg-turbo是对libjpeg的扩展,支持SIMD指令,如X86架构的MMX、SSE、SSE2、3DNOW,ARM架构的NEON,在对jpeg进行编码和解码的过程中能提高速度。在图形库C...
  • alien75
  • alien75
  • 2012年04月13日 15:41
  • 5968

libjpeg-turbo我的CMake编译过程

libjpeg-turbo我的CMake编译过程需要用到bmp转jpg,所以使用了libjpeg,听说[libjpeg-turbo][6]速度更快,所以… 下面说说从下载到编译的全过程吧 我的电脑...
  • songlinok
  • songlinok
  • 2017年03月11日 16:05
  • 905

windows下编译 libjpeg以及libjpeg-turbo

二、编译libjpeg-turbo: 1、  从https://sourceforge.net/projects/libjpeg-turbo/下载libjpeg-turbo最新源代码,将其保存到E:...
  • yixianfeng41
  • yixianfeng41
  • 2016年07月19日 18:57
  • 3779
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:libjpeg学习4:libjpeg-turbo之YUV
举报原因:
原因补充:

(最多只允许输入30个字)