Writing RGB or GREY buffer into a JPEG file

      Comments Off on Writing RGB or GREY buffer into a JPEG file

Import issue:

This example code is for Linux ( or possible for MacOSX ).
and .. Fixed some wrong code

Makefile

It must be declared to link with jpeg library in system, or it should not be switched with turbo-jpeg.

LFLAGS += -ljpeg

Code for jpeglib.

#include <jpeglib.h>

int writejpeg( const char* fname, unsigned char *src, size_t w, size_t h, size_t d, unsigned qual = 100 )
{
    FILE* outf = NULL;
    struct jpeg_compress_struct jcs = {0};
    struct jpeg_error_mgr jem = {0};

    JSAMPROW row_pointer[1];
    jcs.err = jpeg_std_error(&jem);
    jpeg_create_compress(&jcs);

    jcs.image_width = w;
    jcs.image_height = h;
    jcs.input_components = d;

    switch( d )
    {
        case 1:
            jcs.in_color_space = JCS_GRAYSCALE;
            break;

        case 3:
            jcs.in_color_space = JCS_RGB;
            break;
        
        default:
            return -1;
    }
    
    outf = fopen( fname,"wb" );
    if ( outf == NULL )
        return -2;

    jpeg_stdio_dest(&jcs, outf);
    
    if ( qual > 100 ) qual = 100;
    else
    if ( qual == 0  ) qual = 10;
    
    jpeg_set_defaults(&jcs);
    jpeg_set_quality(&jcs, qual, TRUE);
    jpeg_start_compress(&jcs, TRUE);

    while( jcs.next_scanline < jcs.image_height )
    {
        row_pointer[0] = &src[ jcs.next_scanline *
                               jcs.image_width *
                               jcs.input_components ];
        jpeg_write_scanlines( &jcs, row_pointer, 1 );
    }

    jpeg_finish_compress(&jcs);
    jpeg_destroy_compress(&jcs);
    fclose(out);

    return 0;
}

Code for TURBOJPEG
LFLAGS += -lturbojpeg
#include <turbojpeg.h>

int writejpeg( const char* fname, unsigned char* src, size_t w, size_t h, size_t d, unsigned qual = 100 )
{
    unsigned long jsz = 0;
    int jfmt = 0;
    int jsmp = 0;
    
    switch( d )
    {
        case 1:
            jfmt = TJPF_GRAY;
            jsmp = TJSAMP_GRAY;
            break;
            
        case 2:
            return -1;

        case 3:
            jfmt = TJPF_RGB;
            jsmp = TJSAMP_444;
            break;

        case 4:
            jfmt = TJPF_RGBA;
            jsmp = TJSAMP_444;
            break;
    }

    if ( qual > 100 ) qual = 100;
    else
    if ( qual == 0  ) qual = 10;
        
    uchar* outbuff = NULL;
    
    thandle jComp = tjInitCompress();
    if ( jComp != NULL )
    {
        tjCompress2( jComp,
                     src,
                     w,
                     0,
                     h,
                     jfmt,
                     &outbuff,
                     &jsz,
                     TJSAMP_444,
                     qual,
                     TJFLAG_FASTDCT );
         tjDestroy( jComp );
         
         if ( jsz > 0 )
         {
             FILE* outf = fopen( fname, "wb" );
             if ( outf != NULL )
             {
                 fwrite( outbuff, 1, jsz, outf );
                 fclose( outf );
                 
                 delete[] outbuff;
                 return 0;
             }
             else
             {
                 delete[] outbuff;
             }
         }
    }
    
    return -1;
}

Using case for FLTK RGB image

bool WriteImage2JPEG( Fl_RGB_Image* img, const char* fn ) 
{ 
    if ( ( img != NULL ) && ( fn != NULL ) ) 
    { 
        uchar* pRef = (uchar*)pRef->data()[0]; 
        int ret = writejpeg( fn, pRef, img->w(), img->h(), img->d(), 81 ); 
        if ( ret == 0 ) 
            return true; 
    } 
    return false; 
}