UsageLibrary

Martin Srom

Usage of LIBGPUJPEG library

To build libgpujpeg library check Requirements and go to gpujpeg/libgpujpeg/ directory and run 'make' command. The shared library object ./libgpujpeg.so will be build. To use library in your project you have to include library to your sources and linked shared library object to your executable:

#include "libgpujpeg/gpujpeg.h"

Requirements

To be able to build and run libgpujpeg library and gpujpeg console application you need:

  • CUDA Toolkit (http://developer.nvidia.com/cuda-toolkit) installed (which contains NPP libraray), default installation path is /usr/local/cuda. If you have the CUDA installed somewhere else, you need to specify it by environment variable CUDA_INSTALL_PATH or in Makefiles by CUDA_INSTALL_PATH variable.
  • NVIDIA developer drivers
  • CUDA enabled NVIDIA GPU

The libgpujpeg library uses NVIDIA Performance Primitives library, but it is included in CUDA toolkit. There were some build error in npp headers when using some specific versions of GCC and NPP library. If you encounter these kind of problem, try to use the newest version of CUDA toolkit or older version of GCC.

Encoding:

For encoding by libgpujpeg library you have to declare two structures and set proper values to them. The first is definition of encoding/decoding parameters, and the second is structure with parameters of input image:

struct gpujpeg_parameters param;
gpujpeg_set_default_parameters(&param);   
param.quality = 80; 
// (default value is 75)
param.restart_interval = 16; 
// (default value is 8)
param.interleaved = 1;
// (default value is 0)

struct gpujpeg_image_parameters param_image;
gpujpeg_image_set_default_parameters(&param_image);
param_image->width = 1920;
param_image->height = 1080;
param_image->comp_count = 3;
// (for now, it must be 3)
param_image->color_space = GPUJPEG_RGB; 
// or GPUJPEG_YCBCR_ITU_R or GPUJPEG_YCBCR_JPEG
// (default value is GPUJPEG_RGB)
param_image.sampling_factor = GPUJPEG_4_4_4;
// or GPUJPEG_4_2_2
// (default value is GPUJPEG_4_4_4)


If you want to use subsampling in JPEG format call following function, that will set default sampling factors (2x2 for Y, 1x1 for Cb and Cr):

// Use default sampling factors
gpujpeg_parameters_chroma_subsampling(&param);


Or define sampling factors by hand:

// User custom sampling factors
param.sampling_factor[0].horizontal = 4;
param.sampling_factor[0].vertical = 4;
param.sampling_factor[1].horizontal = 1;
param.sampling_factor[1].vertical = 2;
param.sampling_factor[2].horizontal = 2;
param.sampling_factor[2].vertical = 1;


Next you have to initialize CUDA device by calling:

gpujpeg_init_device(device_id, 0);


where first parameters is CUDA device id and second parameter is flag if verbose output should be used (0 or 1). Next step is to create encoder:

struct gpujpeg_encoder* encoder = gpujpeg_encoder_create(&param_image, 
    &param_encoder);
if ( encoder == NULL )
    return -1;


When creating encoder, library allocates all device buffers which will be needed for image encoding and when you encode concrete image, they are already allocated and encoder will used them for every image. Now we need raw image data that we can encode by encoder, for example we can load it from file:

int image_size = 0;
uint8_t* image = NULL;
if ( gpujpeg_image_load_from_file("input_image.rgb", &image, 
         &image_size) != 0 )
    return -1;


Next step is to encode uncompressed image data to JPEG compressed data by encoder:

struct gpujpeg_encoder_input encoder_input;
gpujpeg_encoder_input_set_image(&encoder_input, image);

uint8_t* image_compressed = NULL;
int image_compressed_size = 0;
if ( gpujpeg_encoder_encode(encoder, &encoder_input, &image_compressed, 
         &image_compressed_size) != 0 )
    return -1;


Compressed data are placed in internal encoder buffer so we have to save them somewhere else before we start encoding next image, for example we can save them to file:

if ( gpujpeg_image_save_to_file("output_image.jpg", image_compressed, 
         image_compressed_size) != 0 )
    return -1;


Now we can load, encode and save next image or finish and move to clean up encoder. Finally we have to clean up so destroy loaded image and destroy the encoder.

gpujpeg_image_destroy(image);
gpujpeg_encoder_destroy(encoder);

Decoding:

For decoding we don't need to initialize two structures of parameters. We only have to initialize CUDA device if we haven't initialized it yet and create decoder:

gpujpeg_init_device(device_id, 0);

struct gpujpeg_decoder* decoder = gpujpeg_decoder_create(&param_image);
if ( decoder == NULL )
    return -1;


Now we have two options. The first is to do nothing and decoder will postpone buffer allocations to decoding first image where it determines proper image size and all other parameters. All the following images must have the same parameters. The second option is to provide input image size and optionally other parameters and the decoder will allocate all buffers and it is fully ready when encoding even the first image.

struct gpujpeg_parameters param;
gpujpeg_set_default_parameters(&param);
param.restart_interval = 16; 
param.interleaved = 1;

struct gpujpeg_image_parameters param_image;
gpujpeg_image_set_default_parameters(&param_image);
param_image->width = 1920;
param_image->height = 1080;
param_image->comp_count = 3;

// Pre initialize decoder before decoding
gpujpeg_decoder_init(decoder, &param, &param_image);


If you want to specify output image color space and/or subsampling factor, you can use following two parameters. You can specify them though the param structure befor passing it to gpujpeg_decoder_init. But if you postpone this initialization process to the first image, you have no other option than specify them in this way:

decoder->coder.param_image.color_space = GPUJPEG_RGB;
// or GPUJPEG_YCBCR_ITU_R or GPUJPEG_YCBCR_JPEG
// (default value is GPUJPEG_RGB)
decoder->coder.param_image.sampling_factor = GPUJPEG_4_4_4;
// or GPUJPEG_4_2_2
// (default value is GPUJPEG_4_4_4)


Next we have to load JPEG image data from file and decoded it to raw image data:

int image_size = 0;
uint8_t* image = NULL;
if ( gpujpeg_image_load_from_file("input_image.jpg", &image, 
         &image_size) != 0 )
    return -1;

uint8_t* image_decompressed = NULL;
int image_decompressed_size = 0;
if ( gpujpeg_decoder_decode(decoder, image, image_size, 
         &image_decompressed, &image_decompressed_size) != 0 )
    return -1;


Now we can save decoded raw image data to file and perform cleanup:

if ( gpujpeg_image_save_to_file("output_image.rgb", image_decompressed, 
         image_decompressed_size) != 0 )
    return -1;

gpujpeg_image_destroy(image);
gpujpeg_decoder_destroy(decoder);

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.