#include <ImageDev/ImageDev.h>
#include <ioformat/IOFormat.h>
#include <string.h>

using namespace imagedev;
using namespace ioformat;

int
main( int argc, char* argv[] )
{
    int status = 0;

    try
    {
        // ImageDev library initialization
        if ( imagedev::isInitialized() == false )
            imagedev::init();

        // Open a tif file to binarize
        auto imageInput = ioformat::readImage( std::string( IMAGEDEVDATA_IMAGES_FOLDER ) + "objects.tif" );

        // Threshold image pixels having an intensity between 60 and 255
        std::cout << "Thresholding between a minimum and maximum value..." << std::endl;
        auto imageOutput = thresholding( imageInput, { 60, 255 } );
        // Rescale the binary image intensities between 0 and 255 for visualization and save it
        imageOutput = rescaleIntensity( imageOutput,
                                        RescaleIntensity::OutputType::UNSIGNED_INTEGER_8_BIT,
                                        RescaleIntensity::RangeMode::MIN_MAX,
                                        { 2, 98 },
                                        { 0, 255 },
                                        { 0, 255 } );
        ioformat::writeView( imageOutput, "T03_02_manual.png" );

        // Threshold image pixels having an intensity greater than 60
        std::cout << "Thresholding by comparison to a value..." << std::endl;
        imageOutput = thresholdingByCriterion( imageInput,
                                               ThresholdingByCriterion::ComparisonCriterion::GREATER_THAN_OR_EQUAL_TO,
                                               40 );
        // Rescale the binary image intensities between 0 and 255 for visualization and save it
        imageOutput = rescaleIntensity( imageOutput,
                                        RescaleIntensity::OutputType::UNSIGNED_INTEGER_8_BIT,
                                        RescaleIntensity::RangeMode::MIN_MAX,
                                        { 2, 98 },
                                        { 0, 255 },
                                        { 0, 255 } );
        ioformat::writeView( imageOutput, "T03_02_criterion.png" );

        // Threshold image pixels automatically with Otsu's method
        std::cout << "Automatic thresholding with Otsu method..." << std::endl;
        auto result = autoThresholdingBright( imageInput,
                                              AutoThresholdingBright::RangeMode::MIN_MAX,
                                              { 0, 255 },
                                              AutoThresholdingBright::ThresholdCriterion::FACTORISATION );
        std::cout << "Otsu threshold value = " << result.outputMeasurement->threshold( 0 ) << std::endl;
        // Rescale the binary image intensities between 0 and 255 for visualization and save it
        imageOutput = rescaleIntensity( result.outputBinaryImage,
                                        RescaleIntensity::OutputType::UNSIGNED_INTEGER_8_BIT,
                                        RescaleIntensity::RangeMode::MIN_MAX,
                                        { 2, 98 },
                                        { 0, 255 },
                                        { 0, 255 } );
        ioformat::writeView( imageOutput, "T03_02_auto.png" );

        std::cout << "This example ran successfully." << std::endl;
    }
    catch ( const imagedev::Exception& error )
    {
        // Print potential exception in the standard output
        std::cerr << "ImageDev exception: " << error.what() << std::endl;
        status = -1;
    }

    // ImageDev library finalization
    imagedev::finish();

    // Check if we must ask for an enter key to close the program
    if ( !( ( argc == 2 ) && strcmp( argv[1], "--no-stop-at-end" ) == 0 ) )
        std::cout << "Press Enter key to close this window." << std::endl, getchar();

    return status;
}
