IPSDK  4_1_0_2
IPSDK : Image Processing Software Development Kit

module demonstrating the computation of the lightness image on a color image More...

module demonstrating the computation of the lightness image on a color image

Overview

This application computes the lightness image on a color input image loaded from a given input TIFF file, and saves the result in a given TIFF file.

See also
lightness algorithm

Usage

The application can be called through a command line as follows:

   <application_exe_filename> [--inputImgFilePath <input_image_file_path>] [--outputImgFilePath <output_image_file_path>]
     
   Arguments:
      --inputImgFilePath  optional; specifies the name of the TIFF file, from
                          which the input image will be loaded; if not 
                          specified by the user, the input image is loaded from
                          file 
                          <DEV_ROOT>/data/Sample/images/Lena_RGB_510x509_UInt8.tif
                          
      --outputImgFilePath optional; specifies the name of the TIFF file, in
                          which the output image resulting from the 
                          computation of the lightness will be saved;
                          if not specified by the user, the output image is 
                          saved in file
                          <TEMPORARY_IPSDK_DIR>/Sample/lightness.tif

Here is a snapshot of default input image used by the application and of corresponding output image when application is launched without any argument:

Sample_Lightness.png

Source code documentation

We start by including all the necessary header files:

// --- IPSDK includes
// ------------------
// used to initialize IPSDK environment
#include <IPSDKCore/Config/LibraryInitializer.h>
// used to compute the lightness image on a grey-level input image
// used to manage exceptions possibly thrown by algoritms functions
#include <IPSDKBaseProcessing/Logger/IPSDKBaseProcessingException.h>
// used to catch exceptions potentially thrown by functions loadTiffImageFile and saveTiffImageFile
#include <IPSDKImageFile/Logger/IPSDKImageFileException.h>
// used to read/write an image from/to a TIFF file:
// used to retrieve usual folders (IPSDK temporary folder, root development folder, etc.)
// used to display log messages
// --- third-party boost includes
// ------------------------------
// boost/filesystem/*: contains functions and classes providing facilities to
// manipulate files and directories, and associated paths
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/convenience.hpp>
// boost/program_options/*: contains functions and classes used to manage and
// interpret arguments of command line
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
// --- third-party log4cplus include
// ---------------------------------
// used to add console as output support of logs
#include <log4cplus/consoleappender.h>
// --- STL include
// ---------------
// for std::cout
#include <iostream>

In the main function body, we start by asking to display all the log messages generated by IPSDK libraries and by our application itself to the application console:

int
main(int argc, char* argv[])
{
// add console appender for application logs
log4cplus::SharedAppenderPtr pConsole(new log4cplus::ConsoleAppender);
log4cplus::Logger::getRoot().addAppender(pConsole);
log4cplus::Logger::getRoot().setLogLevel(log4cplus::INFO_LOG_LEVEL);

Next, we initialize the IPSDK environment by invoking "ipsdk::core::LibraryInitializer::getInstance().init()". This method must be called before using any entity or function of IPSDK libraries. It returns an object of type ipsdk::core::LibInitResult, that tells us whether the initialization was OK or not. If the initialization failed (because the IPSDK license file was not found, for instance), we notify the user with an appropriate log message, and we close the application.

// initialize IPSDK environment (first call to be done before calling any
// function or using any entity of IPSDK environment)
switch(initRes.getResult().value()) {
case ipsdk::core::eLibInitStatus::eLIS_Warn:
// IPSDK library is initialized but there were warnings;
// notify the user by displaying a message
% initRes.getMsg());
break;
case ipsdk::core::eLibInitStatus::eLIS_Failed:
// IPSDK library initialization; notify the user and exit
return -1;
break;
default:
break;
}

Then we declare objects 'inImgFilePath' and 'outImgFilePath'. These objects are of type boost::filesystem::path (see documentation of third party boost libraries at http://www.boost.org for details), and are used to store the paths of TIFF files from/to which input/output images are loaded/saved.

// boost objects, used to store input and output images files paths
boost::filesystem::path inImgFilePath, outImgFilePath;

These paths are initialized through the call of the "readCmdArguments" function. As its name suggests, it parses the command line to initialize the input and output images files paths, depending on the options specified by the user. The definition of this function is not explained here, because it mainly uses boost functions, and no IPSDK code.

// read program options from command line, and, if appropriate,
// initialize input and output images files paths
if(!readCmdArguments(argc, argv, inImgFilePath, outImgFilePath))
return -1;

Once the IPSDK environment correctly initialized, we load our input image from the associated TIFF file, by calling the function ipsdk::image::file::loadTiffImageFile. This function takes our object 'inImgFilePath" (of type boost::filesystem::path) as argument and returns an object of type ipsdk::image::ImagePtr, that contains our input image. We store it in "pInImg" variable.

The call of "loadTiffImageFile is enclosed in a try/catch block, to handle the case where an exception is thrown by loadTiffImageFile (if the file is not found or corrupted, for instance). If an error occurs, a message is displayed to the user, IPSDK environment is cleaned by calling "ipsdk::core::LibraryInitializer::getInstance().clear()" and the application terminates.

// declare the variable that will contain the input image, loaded from
// TIFF file
try {
// read input image from specified path
pInImg = ipsdk::image::file::loadTiffImageFile(inImgFilePath);
} catch(const image::file::IPSDKImageFileException& e) {
// loadTiffImageFile function threw an exception; display error log
// message
% inImgFilePath.string() % e.getMsg());
// clear IPSDK environment features; should be called before exiting
// program
// quit the application with an exit code indicating an error
return -1;
}

We can now compute the lightness image on our freshly loaded input image, by calling the function ipsdk::imaproc::color::lightnessImg. This function takes our object pInImg, and returns the resulting image in an object of type ImagePtr, that we store in our variable pOutImg.

Once again, the call of "lightnessImg" function is enclosed in a try/catch block to handle any failure during this operation. If the operation fails, we notify the user and clean IPSDK environment before exiting.

// declare the variable that will contain the output image, resulting from
// the computation of lightness
ImagePtr pOutImg;
try {
// compute the lightness of input image
} catch(const processor::IPSDKBaseProcessingException& e) {
// one of the 2 previous function calls
% e.getMsg());
// clear IPSDK environment features; should be called before exiting
// program
// quit the application with an exit code indicating an error
return -1;
}

If all the previous operations were successfully completed, we save the image resulting from the "lightness" operation to the TIFF file specified by the user (or to a default TIFF file, if the user did not specify anything):

try {
// save the resulting image in specified path
ipsdk::image::file::saveTiffImageFile(outImgFilePath, pOutImg);
} catch(const image::file::IPSDKImageFileException& e) {
% outImgFilePath % e.getMsg());
// clear IPSDK environment features; should be called before exiting
// program
// quit the application with an exit code indicating an error
return -1;
}

The final action consists in cleaning the IPSDK environment before exiting. This cleaning operation (call to "ipsdk::core::LibraryInitializer::getInstance().clear()") must be the last call to IPSDK environment. It guarantees in particular that all threads created by IPSDK libraries are complete.

// clearing IPSDK environment features; should be called before exiting
// program
return 0;
}

See the full source listing