clibjpeg-turboturbojpeg

libjpeg turbo tjCompressFromYUV


I'd like to compress a planar 4:2:0 YUV buffer to a jpeg image using libturbojpeg in C, but I'm having trouble using the tjCompressFromYUV() function.

This is my code:

#define PADDING     2
tjhandle tjh;
unsigned long buf_size;
unsigned char *jpegBuf = NULL;
unsigned long jpegSize;
int width = 352;
int height = 288;
int quality = 70;
unsigned char *ucp_frame;
int j;
FILE *fp = NULL;

ucp_frame = malloc(width * height * 3 / 2);
if ( NULL == ucp_frame ) {
    printf("malloc error ucp_frame\n");
    return 0;
}

fp = fopen("planar_352x288.raw", "rb");
if( NULL == fp ) {
    printf("fopen error\n");
    return 0;
}

j = fread( ucp_frame, 1, width * height * 3 / 2, fp);
if( j != width * height * 3 / 2 ) {
    printf("fread error\n");
    return 0;
}
fclose(fp);

tjh = tjInitCompress();
if( NULL == tjh ) {
    printf("tjInitCompress error '%s'\n",  tjGetErrorStr() );
    return 0;
}

buf_size = tjBufSizeYUV2( width, PADDING, height, TJSAMP_420);
jpegBuf = tjAlloc(buf_size);

if( tjCompressFromYUV( tjh, ucp_frame, width, PADDING, height,
                       TJSAMP_420, &jpegBuf, &jpegSize, quality,
                       TJFLAG_NOREALLOC ) ) {
    printf("tjCompressFromYUV error '%s'\n",  tjGetErrorStr() );
}

The error string returned by tjGetErrorStr() is "Bogus input colorspace".

I tried linking libturbojpeg versions 1.4.2 and 1.4.90.

Any help wolud be appreciated,

Thanks


Solution

  • Turbojpeg API tjCompressFromYUV allows you such options for jpegBuf:

    @param jpegBuf address of a pointer to an image buffer that will receive the JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to accommodate the size of the JPEG image. Thus, you can choose to:

    1. pre-allocate the JPEG buffer with an arbitrary size using #tjAlloc() and let TurboJPEG grow the buffer as needed,

    2. set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer for you, or

    3. pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated (setting #TJFLAG_NOREALLOC guarantees this.)

      If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set #TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.

    So by using 2-nd option, there is no need to call tjBufSizeYUV2 and tjAlloc, simply have jpegBuf=NULL before calling tjCompressFromYUV and do tjFree after compressing.