<|start_filename|>src/math/hough_transform.cpp<|end_filename|>
#include "hough_transform.h"

#include <algorithm>
#include <cmath>

namespace
{
    const float minimumAngleStep = 0.001f * static_cast<float>( pvmath::pi ) / 180.0f;
    const float minimumLineTolerance = 1e-5f;
}

namespace
{
    template <typename _Type>
    bool runHoughTransform( const std::vector< PointBase2D<_Type> > & input, _Type initialAngle, _Type angleTolerance, _Type angleStep,
                            _Type lineTolerance, std::vector< PointBase2D<_Type> > & outOnLine, std::vector< PointBase2D<_Type> > & outOffLine )
    {
        // validate input data
        if ( input.size() < 2u )
            return false;

        if ( angleStep < minimumAngleStep )
            angleStep = minimumAngleStep;

        if ( angleTolerance < minimumAngleStep )
            angleTolerance = minimumAngleStep;

        if ( angleTolerance < angleStep )
            angleTolerance = angleStep;

        if ( lineTolerance < minimumLineTolerance )
            lineTolerance = minimumLineTolerance;

        // find a range of search
        const int angleStepPerSide = static_cast<int>((angleTolerance / angleStep) + 0.5);
        const _Type lineToleranceRange = lineTolerance * 2;

        const size_t inputPointCount = input.size();
        std::vector < _Type > distanceToLine ( inputPointCount );

        int bestAngleId = -angleStepPerSide;
        size_t highestPointCount = 0u;
        _Type averageDistance = 0;

        _Type angleVal = -(initialAngle - angleStep * static_cast<_Type>( angleStepPerSide) ); // this should be an opposite angle

        for ( int angleId = -angleStepPerSide; angleId <= angleStepPerSide; ++angleId, angleVal -= angleStep ) {
            const _Type cosVal = std::cos( angleVal );
            const _Type sinVal = std::sin( angleVal );

            // find and sort distances
            _Type * distanceVal = distanceToLine.data();
            const PointBase2D<_Type> * point = input.data();
            const PointBase2D<_Type> * pointEnd = point + inputPointCount;

            for ( ; point != pointEnd; ++point, ++distanceVal )
                (*distanceVal) = point->x * sinVal + point->y * cosVal;

            std::sort( distanceToLine.begin(), distanceToLine.end() );

            // find maximum number of points
            size_t initialPointId = 0u;
            size_t onLinePointCount = 1u;

            for ( size_t pointId = 0u, endPointId = 1u; endPointId < inputPointCount; ++pointId ) {
                const _Type tolerance = lineToleranceRange + distanceToLine[pointId];

                for ( ; endPointId < inputPointCount; ++endPointId ) {
                    if ( tolerance < distanceToLine[endPointId] )
                        break;
                }

                if ( onLinePointCount < endPointId - pointId ) {
                    onLinePointCount = endPointId - pointId;
                    initialPointId = pointId;
                }
            }

            if ( highestPointCount <= onLinePointCount ) {
                const _Type currentDistance = (distanceToLine[initialPointId + onLinePointCount - 1u] + distanceToLine[initialPointId]) / 2;
                if ( highestPointCount < onLinePointCount || std::abs( currentDistance ) < std::abs( averageDistance ) ) {
                    highestPointCount = onLinePointCount;
                    bestAngleId = angleId;
                    averageDistance = currentDistance;
                }
            }
        }

        outOnLine.clear();
        outOffLine.clear();

        angleVal = -(initialAngle + angleStep * static_cast<_Type>( bestAngleId ));

        const _Type minDistance = averageDistance - lineTolerance;
        const _Type maxDistance = averageDistance + lineTolerance;

        // sort points
        const _Type cosVal = std::cos( angleVal );
        const _Type sinVal = std::sin( angleVal );

        _Type * distanceVal = distanceToLine.data();
        const PointBase2D<_Type> * point = input.data();
        const PointBase2D<_Type> * pointEnd = point + inputPointCount;

        for ( ; point != pointEnd; ++point, ++distanceVal ) {
            (*distanceVal) = point->x * sinVal + point->y * cosVal;

            if ( ((*distanceVal) < minDistance) || ((*distanceVal) > maxDistance) )
                outOffLine.push_back( (*point) );
            else
                outOnLine.push_back( (*point) );
        }

        return true;
    }
}

namespace Image_Function
{
    bool HoughTransform( const std::vector< PointBase2D<double> > & input, double initialAngle, double angleTolerance, double angleStep,
                         double lineTolerance, std::vector< PointBase2D<double> > & outOnLine, std::vector< PointBase2D<double> > & outOffLine )
    {
        return runHoughTransform<double>(input, initialAngle, angleTolerance, angleStep, lineTolerance, outOnLine, outOffLine);
    }

    bool HoughTransform( const std::vector< PointBase2D<float> > & input, float initialAngle, float angleTolerance, float angleStep,
                         float lineTolerance, std::vector< PointBase2D<float> > & outOnLine, std::vector< PointBase2D<float> > & outOffLine )
    {
        return runHoughTransform<float>(input, initialAngle, angleTolerance, angleStep, lineTolerance, outOnLine, outOffLine);
    }
}


<|start_filename|>src/memory/memory_allocator.h<|end_filename|>
#pragma once

#include <cstdint>
#include <set>
#include <stdexcept>
#include <vector>

// Base class for memory allocation
class BaseMemoryAllocator
{
public:
    BaseMemoryAllocator()
        : _size( 0 )
    {
    }

    virtual ~BaseMemoryAllocator()
    {
    }

    // Allocates a chunk of memory. We recommend to call this function only one time at the startup of an application.
    // Do not reallocate memory if some objects in your source code are allocated through this allocator.
    void reserve( size_t size )
    {
        if ( size == 0 )
            throw std::logic_error( "Memory size cannot be 0" );

        if ( size == _size )
            return;

        _allocate( size );

        size_t usedSize = 0;

        while ( size > 0 ) {
            uint8_t levelCount = _getAllocationLevel( size );
            size_t value = static_cast<size_t>(1) << levelCount;

            if ( value > size ) {
                value >>= 1;
                --levelCount;
            }

            if ( usedSize == 0 )
                _freeChunk.resize( levelCount + 1u );

            _freeChunk[levelCount].insert( usedSize );

            usedSize += value;
            size -= value;
        }
    }
protected:
    void _free()
    {
        _deallocate();

        _freeChunk.clear();
        _size = 0;
    }

    // returns a level (power of 2) needed for a required size
    static uint8_t _getAllocationLevel( size_t initialSize )
    {
        size_t size = 1;
        uint8_t level = 0;

        while ( size < initialSize ) {
            size <<= 1;
            ++level;
        }

        return level;
    }

    // splits the preallocated memory by levels
    bool _split( uint8_t from )
    {
        bool levelFound = false;
        uint8_t startLevel = from;

        for ( uint8_t i = from; i < _freeChunk.size(); ++i ) {
            if ( !_freeChunk[i].empty() ) {
                startLevel = i;
                levelFound = true;
                break;
            }
        }

        if ( !levelFound )
            return false;

        if ( startLevel > from ) {
            size_t memorySize = static_cast<size_t>(1) << (startLevel - 1);

            for ( ; startLevel > from; --startLevel, memorySize >>= 1 ) {
                const size_t previousLevelValue = *_freeChunk[startLevel].begin();
                _freeChunk[startLevel - 1u].insert( previousLevelValue );
                _freeChunk[startLevel - 1u].insert( previousLevelValue + memorySize );
                _freeChunk[startLevel].erase( _freeChunk[startLevel].begin() );
            }
        }

        return true;
    }

    // merges preallocated memory by levels
    void _merge( size_t offset, uint8_t from )
    {
        size_t memorySize = static_cast<size_t>(1) << from;

        for ( std::vector < std::set < size_t > >::iterator level = _freeChunk.begin() + from; level < _freeChunk.end();
              ++level, memorySize <<= 1 ) {
            std::set< size_t >::iterator pos = level->find( offset );
            std::set< size_t >::iterator neighbour = pos;
            ++neighbour;

            if ( neighbour != level->end() ) {
                if ( *(neighbour)-*(pos) == memorySize ) {
                    offset = *pos;
                    (level + 1)->insert( offset );
                    level->erase( pos, ++neighbour );
                    continue;
                }
            }

            if ( pos != level->begin() ) {
                neighbour = pos;
                --neighbour;

                if ( *(pos)-*(neighbour) == memorySize ) {
                    offset = *neighbour;
                    (level + 1)->insert( offset );
                    level->erase( neighbour, ++pos );
                    continue;
                }
            }

            return;
        }
    }

    size_t _size; // a size of memory allocated chunk
    std::vector < std::set < size_t > > _freeChunk; // free memory in preallocated memory

private:
    virtual void _allocate( size_t size ) = 0; // true memory allocation
    virtual void _deallocate() = 0; // true memory deallocation
};


<|start_filename|>src/cuda/filtering_cuda.cuh<|end_filename|>
#pragma once

#include "cuda_fft.cuh"

namespace Image_Function_Cuda
{
    using namespace penguinV;

    Image Gaussian( const Image & in, uint32_t kernelSize, float sigma );
    void  Gaussian( const Image & in, Image & out, uint32_t kernelSize, float sigma );

    FFT_Cuda::ComplexData GetGaussianKernel( uint32_t width, uint32_t height, uint32_t kernelSize, float sigma );
}


<|start_filename|>src/ui/ui.h<|end_filename|>
#pragma once
#include <string>
#include "../image_buffer.h"
#include "../math/math_base.h"

struct PaintColor
{
    PaintColor( uint8_t _red = 0u, uint8_t _green = 0u, uint8_t _blue = 0u, uint8_t _alpha = 255u )
        : red  ( _red   )
        , green( _green )
        , blue ( _blue  )
        , alpha( _alpha )
    {
    }

    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
};

class UiWindow
{
public:
    explicit UiWindow( const penguinV::Image & image = penguinV::Image(), const std::string & title = std::string() );
    virtual ~UiWindow();
    void show(); // show window at the screen
    virtual void setImage( const penguinV::Image & image ); // replaces existing shown image by new image
    virtual void drawPoint( const Point2d & point, const PaintColor & color );
    virtual void drawLine( const Point2d & start, const Point2d & end, const PaintColor & color );
    virtual void drawEllipse( const Point2d & center, double xRadius, double yRadius, const PaintColor & color );
    virtual void drawRectangle( const Point2d & topLeftCorner, double width, double height, const PaintColor & color );
protected:
    virtual void _display();

    penguinV::Image _image; // we store a copy of image
    std::string _title;
    bool _shown;
};


<|start_filename|>cmake/find_png.cmake<|end_filename|>
include(ExternalProject)
option(PENGUINV_ENABLE_PNG_SUPPORT "Enable support of libpng" ON)
option(PENGUINV_USE_EXTERNAL_PNG "Download libpng and build from source" OFF)
option(PENGUINV_INSTALL_ZLIB "Download zlib and build from source" ON)
option(PENGUINV_INSTALL_PNG "Download libpng and build from source" ON)

if(PENGUINV_ENABLE_PNG_SUPPORT)
    find_package(PNG)
    if(NOT PNG_FOUND)
        set(PENGUINV_USE_EXTERNAL_PNG ON CACHE BOOL "" FORCE)
        message(STATUS "libpng has not been found in the system and will be downloaded")
    endif()
endif()

if(PENGUINV_USE_EXTERNAL_PNG)
    set(DOWNLOAD_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/downloads"
    CACHE PATH "Location where external projects will be downloaded.")
    mark_as_advanced(DOWNLOAD_LOCATION)

    # ZLIB
    set(ZLIB_INSTALL ${CMAKE_BINARY_DIR}/zlib)
    set(ZLIB_BUILD_DIR ${CMAKE_BINARY_DIR}/zlib/build)
    set(ZLIB_LIB_DIR ${ZLIB_INSTALL}/lib)
    set(ZLIB_INCLUDE_DIR ${ZLIB_INSTALL}/include)
    set(ZLIB_HEADERS
        "${ZLIB_INSTALL}/include/zconf.h"
        "${ZLIB_INSTALL}/include/zlib.h")

    if(WIN32)
        if(MSVC)
            set(ZLIB_STATIC_LIBRARIES
                debug ${ZLIB_LIB_DIR}/zlibstaticd.lib
                optimized ${ZLIB_LIB_DIR}/zlibstatic.lib)
        else()
            if(CMAKE_BUILD_TYPE EQUAL Debug)
                set(ZLIB_STATIC_LIBRARIES ${ZLIB_LIB_DIR}/zlibstaticd.lib)
        else()
                set(ZLIB_STATIC_LIBRARIES ${ZLIB_LIB_DIR}/zlibstatic.lib)
        endif()
        endif()
    else()
        set(ZLIB_STATIC_LIBRARIES ${ZLIB_LIB_DIR}/libz.a)
    endif()

    if(DEFINED ENV{APPVEYOR})
        if(EXISTS ${ZLIB_INSTALL})
            set(PENGUINV_INSTALL_ZLIB OFF CACHE BOOL "" FORCE)
        endif()
    endif()
    
    if(PENGUINV_INSTALL_ZLIB)
        ExternalProject_Add(zlib
            PREFIX zlib
            URL https://sourceforge.net/projects/libpng/files/zlib/1.2.11/zlib1211.zip
            URL_MD5 16b41357b2cd81bca5e1947238e64465
            BINARY_DIR ${ZLIB_BUILD_DIR}
            BUILD_BYPRODUCTS ${ZLIB_STATIC_LIBRARIES}
            DOWNLOAD_DIR ${DOWNLOAD_LOCATION}
            INSTALL_DIR ${ZLIB_INSTALL}
            CMAKE_CACHE_ARGS
                -DCMAKE_BUILD_TYPE:STRING=Release
                -DCMAKE_INSTALL_PREFIX:STRING=${ZLIB_INSTALL}
                -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON)

        add_custom_target(zlib_create_destination_dir
        COMMAND ${CMAKE_COMMAND} -E make_directory ${ZLIB_INCLUDE_DIR}
        DEPENDS zlib)
        add_custom_target(zlib_copy_headers_to_destination 
        DEPENDS zlib_create_destination_dir)
        foreach(header_file ${ZLIB_HEADERS})
        add_custom_command(TARGET zlib_copy_headers_to_destination PRE_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy_if_different ${header_file} ${ZLIB_INCLUDE_DIR})
        endforeach()
    endif()
    
    add_library(ZLIB_EXTERNAL STATIC IMPORTED)
    set(ZLIB_LIBRARY_RELEASE ${ZLIB_INSTALL}/lib/zlibstatic.lib)
    set(ZLIB_LIBRARY_RELWITHDEBINFO ${ZLIB_INSTALL}/lib/zlibstatic.lib)
    set(ZLIB_LIBRARY_DEBUG ${ZLIB_INSTALL}/lib/zlibstaticd.lib)
    set_target_properties(ZLIB_EXTERNAL PROPERTIES
        IMPORTED_LOCATION_RELEASE "${ZLIB_LIBRARY_RELEASE}"
        IMPORTED_LOCATION_RELWITHDEBINFO "${ZLIB_LIBRARY_RELWITHDEBINFO}"
        IMPORTED_LOCATION_DEBUG "${ZLIB_LIBRARY_DEBUG}")

    # PNG
    set(PNG_INSTALL ${CMAKE_BINARY_DIR}/png)
    set(PNG_BUILD_DIR ${CMAKE_BINARY_DIR}/png/build)
    set(PNG_LIB_DIR ${PNG_INSTALL}/lib)
    set(PNG_INCLUDE_DIR ${PNG_INSTALL}/include)
    set(PNG_HEADERS
            "${PNG_INCLUDE_DIR}/libpng16/png.h"
            "${PNG_INCLUDE_DIR}/libpng16/pngconf.h"
            "${PNG_INCLUDE_DIR}/libpng16/pnglibconf.h")

    if(DEFINED ENV{APPVEYOR})
        if(EXISTS ${PNG_INSTALL})
            set(PENGUINV_INSTALL_PNG OFF CACHE BOOL "" FORCE)
        endif()
    endif()

    if(WIN32)
        if(MSVC)
            set(PNG_STATIC_LIBRARIES
                debug ${PNG_LIB_DIR}/libpng16_staticd.lib
                optimized ${PNG_LIB_DIR}/libpng16_static.lib)
        else()
            if(CMAKE_BUILD_TYPE EQUAL Debug)
                set(PNG_STATIC_LIBRARIES ${PNG_LIB_DIR}/libpng16_staticd.lib)
        else()
                set(PNG_STATIC_LIBRARIES ${PNG_LIB_DIR}/libpng16_static.lib)
        endif()
        endif()
    else()
        set(PNG_STATIC_LIBRARIES ${PNG_LIB_DIR}/libpng16.a)
    endif()

    if(PENGUINV_INSTALL_ZLIB)
        if(PENGUINV_INSTALL_PNG)
            ExternalProject_Add(png
                PREFIX png
                DEPENDS zlib
                URL https://sourceforge.net/projects/libpng/files/libpng16/1.6.35/lpng1635.zip
                URL_MD5 d8bfd42ee9e59404349b50106e04e1f9
                BINARY_DIR ${PNG_BUILD_DIR}
                BUILD_BYPRODUCTS ${PNG_STATIC_LIBRARIES}
                DOWNLOAD_DIR ${DOWNLOAD_LOCATION}
                INSTALL_DIR ${PNG_INSTALL}
                CMAKE_CACHE_ARGS
                    -DCMAKE_BUILD_TYPE:STRING=Release
                    -DCMAKE_INSTALL_PREFIX:STRING=${PNG_INSTALL}
                    -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
                    -DPNG_TESTS:BOOL=OFF
                    -DPNG_SHARED:BOOL=OFF
                    -DPNG_STATIC:BOOL=ON
                    -DSKIP_INSTALL_EXECUTABLES:BOOL=OFF
                -DZLIB_ROOT:STRING=${ZLIB_INSTALL})
        endif()
    else()
        if(PENGUINV_INSTALL_PNG)
            ExternalProject_Add(png
                PREFIX png
                URL https://sourceforge.net/projects/libpng/files/libpng16/1.6.35/lpng1635.zip
                URL_MD5 d8bfd42ee9e59404349b50106e04e1f9
                BINARY_DIR ${PNG_BUILD_DIR}
                BUILD_BYPRODUCTS ${PNG_STATIC_LIBRARIES}
                DOWNLOAD_DIR ${DOWNLOAD_LOCATION}
                INSTALL_DIR ${PNG_INSTALL}
                CMAKE_CACHE_ARGS
                    -DCMAKE_BUILD_TYPE:STRING=Release
                    -DCMAKE_INSTALL_PREFIX:STRING=${PNG_INSTALL}
                    -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
                    -DPNG_TESTS:BOOL=OFF
                    -DPNG_SHARED:BOOL=OFF
                    -DPNG_STATIC:BOOL=ON
                    -DSKIP_INSTALL_EXECUTABLES:BOOL=OFF
                -DZLIB_ROOT:STRING=${ZLIB_INSTALL})
        endif()
    endif()

    if(PENGUINV_INSTALL_PNG)
        add_custom_target(png_create_destination_dir
            COMMAND ${CMAKE_COMMAND} -E make_directory ${PNG_INCLUDE_DIR}
            DEPENDS png)
        add_custom_target(png_copy_headers_to_destination
            DEPENDS png_create_destination_dir)
        foreach(header_file ${PNG_HEADERS})
            add_custom_command(TARGET png_copy_headers_to_destination PRE_BUILD
                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${header_file} ${PNG_INCLUDE_DIR})
        endforeach()
    endif()

    add_library(PNG_EXTERNAL STATIC IMPORTED)
    set(PNG_LIBRARY_RELEASE ${PNG_INSTALL}/lib/libpng16_static.lib)
    set(PNG_LIBRARY_RELWITHDEBINFO ${PNG_INSTALL}/lib/libpng16_static.lib)
    set(PNG_LIBRARY_DEBUG ${PNG_INSTALL}/lib/libpng16_staticd.lib)
    set(PNG_INCLUDE_DIRS ${PNG_INSTALL}/include)
    # CMake INTERFACE_INCLUDE_DIRECTORIES requires the directory to exists at configure time
    # This is quite unhelpful because those directories are only generated at build time
    file(MAKE_DIRECTORY ${PNG_INCLUDE_DIRS}) # Workaround
    set_target_properties(PNG_EXTERNAL PROPERTIES
        IMPORTED_LOCATION_RELEASE "${PNG_LIBRARY_RELEASE}"
        IMPORTED_LOCATION_RELWITHDEBINFO "${PNG_LIBRARY_RELWITHDEBINFO}"
        IMPORTED_LOCATION_DEBUG "${PNG_LIBRARY_DEBUG}"
        INTERFACE_INCLUDE_DIRECTORIES ${PNG_INCLUDE_DIRS})
endif()


<|start_filename|>src/math/haar_transform.h<|end_filename|>
#pragma once
#include <cstddef>
#include <vector>

namespace Image_Function
{
    void HaarDirectTransform ( const std::vector< double > & input, std::vector< double > & output, size_t width, size_t height );
    void HaarInverseTransform( const std::vector< double > & input, std::vector< double > & output, size_t width, size_t height );

    void HaarDirectTransform ( const std::vector< float > & input, std::vector< float > & output, size_t width, size_t height );
    void HaarInverseTransform( const std::vector< float > & input, std::vector< float > & output, size_t width, size_t height );
}


<|start_filename|>src/math/hough_transform.h<|end_filename|>
#pragma once

#include <vector>
#include "math_base.h"

namespace Image_Function
{
    bool HoughTransform( const std::vector< PointBase2D<double> > & input, double initialAngle, double angleTolerance, double angleStep,
                         double lineTolerance, std::vector< PointBase2D<double> > & outOnLine, std::vector< PointBase2D<double> > & outOffLine );

    bool HoughTransform( const std::vector< PointBase2D<float> > & input, float initialAngle, float angleTolerance, float angleStep,
                         float lineTolerance, std::vector< PointBase2D<float> > & outOnLine, std::vector< PointBase2D<float> > & outOffLine );
}


<|start_filename|>src/ui/x11/x11_ui.h<|end_filename|>
#pragma once

#ifndef _WIN32 // Not for Windows

#include <vector>
#include <utility>
#include <X11/Xlib.h>
#include "../ui.h"

class UiWindowX11 : public UiWindow
{
public:
    explicit UiWindowX11( const penguinV::Image & image = penguinV::Image(), const std::string & title = std::string() );
    virtual ~UiWindowX11();

    virtual void drawPoint( const Point2d & point, const PaintColor & color );
protected:
    virtual void _display();
private:
    std::vector<char> _data;
    Display * _uiDisplay;
    int _screen;
    Window _window;
    XImage * _image;
    Atom _deleteWindowEvent;
    uint32_t _width;
    uint32_t _height;

    std::vector< std::pair<Point2d, uint32_t> > _point;

    void _setupImage( const penguinV::Image & image );
};

#endif


<|start_filename|>src/cuda/cuda_memory.cuh<|end_filename|>
#pragma once

#include <cuda_runtime.h>
#include <map>
#include "../memory/memory_allocator.h"

namespace multiCuda
{
    // Class for memory allocation on devices with CUDA support
    class MemoryAllocator : public BaseMemoryAllocator
    {
    public:
        explicit MemoryAllocator( size_t availableSpace )
            : _data         ( nullptr )
            , _availableSize( availableSpace )
        {
            if ( _availableSize == 0 )
                throw std::logic_error( "Available size cannot be 0" );
        }

        virtual ~MemoryAllocator()
        {
            _free();
        }

        // Returns a pointer to an allocated memory. If memory size of allocated memory chuck of memory is enough for requested size
        // so assign a pointer to preallocated memory, otherwise allocate a new chuck of memory just for the pointer
        template <typename _DataType = uint8_t>
        _DataType* allocate( size_t size = 1 )
        {
            size = size * sizeof( _DataType );

            if ( _data != nullptr && size < _size ) {
                const uint8_t level = _getAllocationLevel( size );

                if ( _split( level ) ) {
                    _DataType* address = reinterpret_cast<_DataType*>(static_cast<uint8_t*>(_data) + *_freeChunk[level].begin());
                    _allocatedChunk.insert( std::pair<size_t, uint8_t >( *_freeChunk[level].begin(), level ) );
                    _freeChunk[level].erase( _freeChunk[level].begin() );
                    return address;
                }
            }

            // if no space in preallocated memory just allocate as usual memory
            _DataType* address = nullptr;
            cudaError_t error = cudaMalloc( &address, size );
            if ( error != cudaSuccess )
                throw std::logic_error( "Cannot allocate a memory for CUDA device" );

            return address;
        }

        // deallocates a memory by input address
        // if a pointer points on allocated chuck of memory inside the allocator then
        // the allocator just removes a reference to such area without any cost
        // otherwise CUDA specific function will be called
        void free( void * address )
        {
            if ( _data != nullptr && address >= _data ) {
                std::map <size_t, uint8_t>::iterator pos =
                    _allocatedChunk.find( static_cast<uint8_t*>(address) - static_cast<uint8_t*>(_data) );

                if ( pos != _allocatedChunk.end() ) {
                    _freeChunk[pos->second].insert( pos->first );
                    _merge( pos->first, pos->second );
                    _allocatedChunk.erase( pos );
                    return;
                }
            }

            cudaError_t error = cudaFree( address );
            if ( error != cudaSuccess )
                throw std::logic_error( "Cannot deallocate memory for CUDA device" );
        }

        // returns maximum available space which could be allocated by allocator
        size_t availableSize() const
        {
            return _availableSize;
        }
    private:
        void * _data; // a pointer to memory allocated chunk
        const size_t _availableSize; // maximum available memory size

        // a map which holds an information about allocated memory in preallocated memory chunk
        // first parameter is an offset from preallocated memory, second parameter is a power of 2 (level)
        std::map <size_t, uint8_t> _allocatedChunk;

        // true memory allocation on devices with CUDA support
        virtual void _allocate( size_t size )
        {
            if ( size > _availableSize )
                throw std::logic_error( "Memory size to be allocated is bigger than available size on device" );

            if ( _size != size && size > 0 ) {
                if ( !_allocatedChunk.empty() )
                    throw std::logic_error( "Cannot free a memory on device with CUDA support. Not all objects were previously deallocated from allocator." );

                _free();

                cudaError_t error = cudaMalloc( &_data, size );
                if ( error != cudaSuccess )
                    throw std::logic_error( "Cannot allocate a memory for CUDA device" );

                _size = size;
            }
        }

        // true memory deallocation on devices with CUDA support
        virtual void _deallocate()
        {
            if ( _data != nullptr ) {
                cudaError_t error = cudaFree( _data );
                if ( error != cudaSuccess )
                    throw std::logic_error( "Cannot deallocate memory for CUDA device" );
                _data = nullptr;
            }

            _allocatedChunk.clear();
        }

        MemoryAllocator( const MemoryAllocator & )
            : _availableSize( 0 )
        {
        }

        MemoryAllocator & operator=( const MemoryAllocator & ) { return (*this); }
    };
}


<|start_filename|>src/opencl/opencl_device.h<|end_filename|>
#pragma once

#define CL_USE_DEPRECATED_OPENCL_1_2_APIS

#if defined(__APPLE__) || defined(__MACOSX)
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif

#include <list>
#include <string>
#include <vector>
#include "opencl_memory.h"

namespace multiCL
{
    class OpenCLDeviceManager;

    // This is a shortcut (facade) namespace to access memory allocator for devices
    namespace MemoryManager
    {
        // Returns memory allocator for current thread
        // By default it will return an allocator for device with ID = 0 otherwise an ID what is actual for current thread
        MemoryAllocator & memory();

        // Returns memory allocator for specified device ID
        MemoryAllocator & memory( uint32_t deviceId );

        void memorySet( cl_mem data, const void * pattern, size_t patternSize, size_t offset, size_t size );
    }

    class OpenCLContext
    {
    public:
        explicit OpenCLContext( cl_device_id deviceId );
        explicit OpenCLContext( cl_context context );
        ~OpenCLContext();

        cl_context operator()() const;

    private:
        cl_context _context;

        OpenCLContext( const OpenCLContext& );
        OpenCLContext& operator= ( const OpenCLContext& );
    };

    class OpenCLProgram
    {
    public:
        OpenCLProgram( const OpenCLContext& context, const char * program );
        explicit OpenCLProgram( cl_program program );
        OpenCLProgram( OpenCLProgram && program );
        ~OpenCLProgram();

        cl_program operator()() const;

    private:
        cl_program _program;

        OpenCLProgram( const OpenCLProgram& );
        OpenCLProgram& operator=( const OpenCLProgram& );
    };

    class OpenCLKernel
    {
    public:
        OpenCLKernel( const OpenCLProgram& program, const std::string& name );
        explicit OpenCLKernel( cl_kernel kernel );
        ~OpenCLKernel();

        cl_kernel operator()() const;

        template <typename T>
        void setArgument( T value )
        {
            _setArgument( sizeof( T ), &value );
        }

        template <typename T, typename... Args>
        void setArgument( T value, Args... args )
        {
            setArgument( value );
            setArgument( args... );
        }

        void reset();

    private:
        cl_kernel _kernel;
        cl_uint _parameterId;

        OpenCLKernel( const OpenCLKernel& );
        OpenCLKernel& operator=( const OpenCLKernel& );

        void _setArgument( size_t size, const void * data );
    };

    class OpenCLQueue
    {
    public:
        OpenCLQueue( const OpenCLContext& context, cl_device_id deviceId );
        explicit OpenCLQueue( cl_command_queue queue );
        ~OpenCLQueue();

        cl_command_queue operator()() const;

        void synchronize();

    private:
        cl_command_queue _commandQueue;

        OpenCLQueue( const OpenCLQueue& );
        OpenCLQueue& operator=( const OpenCLQueue& );
    };

    class OpenCLDevice
    {
    public:
        friend class OpenCLDeviceManager;

        ~OpenCLDevice();

        // Device information
        cl_device_id deviceId() const;

        size_t threadsPerBlock( const OpenCLKernel& kernel ) const; // maximum available number of threads per block

        uint64_t totalMemorySize() const; // total available memory in bytes
        std::string name() const;
        std::string computeCapability() const;

        // Device manipulation
        void synchronize(); // synchronize all operations on device with CPU

        OpenCLContext & context();
        const OpenCLContext & context() const;

        size_t currentQueueId() const; // current queue ID which is used as a default value in queue() function
        void setCurrentQueueId( size_t queueId );

        OpenCLQueue & queue(); // a reference to current queue
        const OpenCLQueue & queue() const;

        OpenCLQueue & queue( size_t queueId ); // a reference to queue with specified ID
        const OpenCLQueue & queue( size_t queueId ) const;

        size_t queueCount() const; // total number of queues
        void setQueueCount( size_t queueCount );

        MemoryAllocator & allocator(); // memory allocator associated with device
        const MemoryAllocator & allocator() const;

    private:
        cl_device_id _deviceId;
        OpenCLContext _context;

        size_t _currentQueueId;
        std::vector< OpenCLQueue * > _queue; // array of queues within the device

        MemoryAllocator * _allocator; // memory allocator on current device

        explicit OpenCLDevice( cl_device_id deviceId );
        OpenCLDevice( const OpenCLDevice& );
        OpenCLDevice& operator= ( const OpenCLDevice& );
    };

    class OpenCLDeviceManager
    {
    public:
        static OpenCLDeviceManager & instance();

        void initializeDevices(); // initializes all devices available in system
        void initializeDevice( uint32_t deviceId ); // initializes a device with specified ID
        void closeDevice( uint32_t deviceId ); // closes initialized device with specified ID
        void closeDevices(); // closes all devices initialized by manager

        uint32_t deviceCount() const; // initialized devices via manager
        uint32_t supportedDeviceCount() const; // maximum available devices in the system

        OpenCLDevice & device(); // returns device within current thread
        const OpenCLDevice & device() const; // returns device within current thread

        OpenCLDevice & device( uint32_t deviceId ); // returns device with specified ID
        const OpenCLDevice & device( uint32_t deviceId ) const; // returns device with specified ID

        void setActiveDevice( uint32_t deviceId ); // set device with specified ID as a active device in current thread

        void resetSupportedDevice();

    private:
        OpenCLDeviceManager();
        ~OpenCLDeviceManager();

        std::vector < cl_device_id > _supportedDeviceId;
        std::list<OpenCLDevice *> _device; // a list of initialized devices
    };
}


<|start_filename|>cmake/find_jpeg.cmake<|end_filename|>
include(ExternalProject)
option(PENGUINV_ENABLE_JPEG_SUPPORT "Enable support of libjpeg" ON)
option(PENGUINV_USE_EXTERNAL_JPEG "Download libjpeg and build from source" OFF)
option(PENGUINV_INSTALL_YASM "Download yasm and build from source" ON)
option(PENGUINV_INSTALL_JPEG "Download jpeg and build from source" ON)

if(PENGUINV_ENABLE_JPEG_SUPPORT)
    find_package(JPEG)
    if(NOT JPEG_FOUND)
        set(PENGUINV_USE_EXTERNAL_JPEG ON CACHE BOOL "" FORCE)
        message(STATUS "libjpeg has not been found in the system and will be downloaded")
    endif()
endif()

if(PENGUINV_USE_EXTERNAL_JPEG)
    set(DOWNLOAD_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/downloads"
    CACHE PATH "Location where external projects will be downloaded.")
    mark_as_advanced(DOWNLOAD_LOCATION)

    set(YASM_INSTALL ${CMAKE_BINARY_DIR}/yasm)
    set(YASM_INCLUDE_DIR ${YASM_INSTALL}/include)
    set(YASM_LIBRARIES ${YASM_INSTALL}/lib/libyasm.a)

    if(WIN32)
        set(YASM_BINARY ${YASM_INSTALL}/bin/yasm.exe)
    else()
        set(YASM_BINARY ${YASM_INSTALL}/bin/yasm)
    endif()

    if(DEFINED ENV{APPVEYOR})
        if(EXISTS ${YASM_BINARY})
            set(PENGUINV_INSTALL_YASM OFF CACHE BOOL "" FORCE)
        endif()
    endif()

    set(JPEG_INSTALL ${CMAKE_BINARY_DIR}/jpeg)
    set(JPEG_BUILD_DIR ${CMAKE_BINARY_DIR}/jpeg/build)
    set(JPEG_LIB_DIR ${JPEG_INSTALL}/lib)
    set(JPEG_INCLUDE_DIR ${JPEG_INSTALL}/include)

    if(DEFINED ENV{APPVEYOR})
        if(EXISTS ${JPEG_INSTALL})
            set(PENGUINV_INSTALL_JPEG OFF CACHE BOOL "" FORCE)
        endif()
    endif()

    if(WIN32)
        if(MSVC)
            set(JPEG_STATIC_LIBRARIES
                debug ${JPEG_LIB_DIR}/jpeg-staticd.lib
                optimized ${JPEG_LIB_DIR}/jpeg-static.lib)
        else()
            if(CMAKE_BUILD_TYPE EQUAL Debug)
                set(JPEG_STATIC_LIBRARIES ${JPEG_LIB_DIR}/jpeg-staticd.lib)
            else()
                set(JPEG_STATIC_LIBRARIES ${JPEG_LIB_DIR}/jpeg-static.lib)
            endif()
        endif()
    else()
        set(JPEG_STATIC_LIBRARIES ${JPEG_LIB_DIR}/libjpeg.a)
    endif()

    if(PENGUINV_INSTALL_YASM)
        # Download yasm to compile jpeg
        ExternalProject_Add(yasm
            PREFIX ${CMAKE_CURRENT_BINARY_DIR}/yasm
            URL http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
            CMAKE_CACHE_ARGS
                -DBUILD_SHARED_LIBS:BOOL=OFF
                -DCMAKE_BUILD_TYPE:STRING=RELEASE
                -DCMAKE_INSTALL_PREFIX:STRING=${YASM_INSTALL})

        if(PENGUINV_INSTALL_JPEG)
            ExternalProject_Add(jpeg
                PREFIX ${CMAKE_CURRENT_BINARY_DIR}/jpeg
                DEPENDS yasm
                URL https://sourceforge.net/projects/libjpeg-turbo/files/2.0.1/libjpeg-turbo-2.0.1.tar.gz
                URL_MD5 1b05a66aa9b006fd04ed29f408e68f46
                INSTALL_DIR ${JPEG_INSTALL}
                CMAKE_ARGS
                    -DWITH_SIMD=TRUE
                    -DENABLE_SHARED=TRUE
                    -DENABLE_STATIC=TRUE
                    -DWITH_TURBOJPEG=TRUE
                    -DWITH_JPEG8=TRUE
                    -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE
                    -DCMAKE_BUILD_TYPE=Release
                    -DCMAKE_CONFIGURATION_TYPES=Release
                    -DCMAKE_INSTALL_PREFIX=${JPEG_INSTALL}
                    -DCMAKE_ASM_NASM_COMPILER=${YASM_BINARY})
        endif()
    else()
        if(PENGUINV_INSTALL_JPEG)
            ExternalProject_Add(jpeg
                PREFIX ${CMAKE_CURRENT_BINARY_DIR}/jpeg
                URL https://sourceforge.net/projects/libjpeg-turbo/files/2.0.1/libjpeg-turbo-2.0.1.tar.gz
                URL_MD5 1b05a66aa9b006fd04ed29f408e68f46
                INSTALL_DIR ${JPEG_INSTALL}
                CMAKE_ARGS
                    -DWITH_SIMD=TRUE
                    -DENABLE_SHARED=TRUE
                    -DENABLE_STATIC=TRUE
                    -DWITH_TURBOJPEG=TRUE
                    -DWITH_JPEG8=TRUE
                    -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE
                    -DCMAKE_BUILD_TYPE=Release
                    -DCMAKE_CONFIGURATION_TYPES=Release
                    -DCMAKE_INSTALL_PREFIX=${JPEG_INSTALL}
                    -DCMAKE_ASM_NASM_COMPILER=${YASM_BINARY})
        endif()
    endif()

    add_library(JPEG_EXTERNAL STATIC IMPORTED)
    set(JPEG_LIBRARY_RELEASE ${JPEG_INSTALL}/lib/jpeg-static.lib)
    set(JPEG_LIBRARY_RELWITHDEBINFO ${JPEG_INSTALL}/lib/jpeg-static.lib)
    set(JPEG_LIBRARY_DEBUG ${JPEG_INSTALL}/lib/jpeg-staticd.lib)
    set(JPEG_INCLUDE_DIRS ${JPEG_INSTALL}/include)
    # CMake INTERFACE_INCLUDE_DIRECTORIES requires the directory to exists at configure time
    # This is quite unhelpful because those directories are only generated at build time
    file(MAKE_DIRECTORY ${JPEG_INCLUDE_DIRS}) # Workaround
    set_target_properties(JPEG_EXTERNAL PROPERTIES
        IMPORTED_LOCATION_RELEASE "${JPEG_LIBRARY_RELEASE}"
        IMPORTED_LOCATION_RELWITHDEBINFO "${JPEG_LIBRARY_RELWITHDEBINFO}"
        IMPORTED_LOCATION_DEBUG "${JPEG_LIBRARY_DEBUG}"
        INTERFACE_INCLUDE_DIRECTORIES ${JPEG_INCLUDE_DIRS})
endif()


<|start_filename|>test/performance_tests/performance_tests.cpp<|end_filename|>
#include <iostream>
#include "performance_test_blob_detection.h"
#include "performance_test_edge_detection.h"
#include "performance_test_filtering.h"
#include "performance_test_framework.h"
#include "performance_test_helper.h"
#include "performance_test_image_function.h"

int main( int argc, char* argv[] )
{
    Performance_Test::setRunCount( argc, argv, 128 );

    cpu_Memory::MemoryAllocator::instance().reserve( 32 * 1024 * 1024 );

    PerformanceTestFramework framework;
    addTests_Blob_Detection     ( framework );
    addTests_Edge_Detection     ( framework );
    addTests_Filtering          ( framework );
    addTests_Image_Function     ( framework );
    framework.run();

    return 0;
}


<|start_filename|>src/file/jpeg_image.h<|end_filename|>
#pragma once
#include "../image_buffer.h"

namespace Jpeg_Operation
{
    penguinV::Image Load( const std::string & path );
    void            Load( const std::string & path, penguinV::Image & image );

    void Save( const std::string & path, const penguinV::Image & image );
    void Save( const std::string & path, const penguinV::Image & image, uint32_t startX, uint32_t startY, uint32_t width, uint32_t height );

    void SetImageQuality( int quality ); // quality is in % from 1 to 100
    int GetImageQuality(); // in %
}


<|start_filename|>src/penguinv/cpu_id_windows.h<|end_filename|>
#pragma once

#include <intrin.h>

struct CpuInformation
{
    static bool isSseSupported()
    {
        int info[4];
        __cpuidex( info, 0, 0 );
        const int id = info[0];

        if( id >= 0x00000001 ) {
            __cpuidex( info, 0x00000001, 0 );
            return (info[3] & ((int)1 << 26)) != 0;
        }

        return false;
    }

    static bool isAvxSupported()
    {
        int info[4];
        __cpuidex( info, 0, 0 );
        const int id = info[0];

        if( id >= 0x00000007 ) {
            __cpuidex( info, 0x00000007, 0 );
            return (info[1] & ((int)1 << 5)) != 0;
        }

        return false;
    }

    static bool isAvx512SKLSupported()
    {
        int info[4];
        __cpuidex( info, 0, 0 );
        const int id = info[0];

        if ( id >= 0x00000007 ) {
            __cpuidex( info, 0x00000007, 0 );
            return (info[1] & (((int)1 << 31) | ((int)1 << 30) | ((int)1 << 28) | ((int)1 << 17) | ((int)1 << 16))) != 0;
        }

        return false;
    }

    static bool isNeonSupported()
    {
#ifdef _M_ARM
        return true;
#else
        return false;
#endif
    }
};


<|start_filename|>src/memory/cpu_memory.h<|end_filename|>
#pragma once

#include <map>
#include <mutex>
#include "memory_allocator.h"

namespace cpu_Memory
{
    // Class for memory allocation on CPU
    class MemoryAllocator : public BaseMemoryAllocator
    {
    public:
        MemoryAllocator()
            : _data( nullptr )
            , _alignedData( nullptr)
        {
        }

        static MemoryAllocator & instance()
        {
            static MemoryAllocator allocator;
            return allocator;
        }

        virtual ~MemoryAllocator()
        {
            _lock.lock();
            _free();
            _lock.unlock();
        }

        // Returns a pointer to an allocated memory. If memory size of allocated memory chuck is enough for requested size
        // then return a point from preallocated memory, otherwise allocate heap memory
        template <typename _DataType = uint8_t>
        _DataType* allocate( size_t size = 1 )
        {
            _lock.lock();
            if ( _data != nullptr ) {
                const size_t overallSize = size * sizeof( _DataType );

                if ( overallSize < _size ) {
                    const uint8_t level = _getAllocationLevel( overallSize );

                    if ( _split( level ) ) {
                        std::set < size_t >::iterator chunk = _freeChunk[level].begin();
                        _DataType* address = reinterpret_cast<_DataType*>( _alignedData + *chunk );
                        _allocatedChunk.insert( std::pair<size_t, uint8_t >( *chunk, level ) );
                        _freeChunk[level].erase( chunk );
                        _lock.unlock();
                        return address;
                    }
                }
            }
            _lock.unlock();

            // if no space in preallocated memory, allocate as usual memory
            return new _DataType[size];
        }

        // Deallocates a memory by input address. If a pointer points on allocated chuck of memory inside the allocator then
        // the allocator just removes a reference to such area without any cost, otherwise heap allocation
        template <typename _DataType>
        void free( _DataType * address )
        {
            _lock.lock();
            if ( _data != nullptr && reinterpret_cast<uint8_t*>( address ) >= _alignedData ) {
                std::map <size_t, uint8_t>::iterator pos = _allocatedChunk.find( static_cast<size_t>( reinterpret_cast<uint8_t*>(address) - _alignedData ) );

                if ( pos != _allocatedChunk.end() ) {
                    _freeChunk[pos->second].insert( pos->first );
                    _merge( pos->first, pos->second );
                    _allocatedChunk.erase( pos );
                    _lock.unlock();
                    return;
                }
            }
            _lock.unlock();

            delete[] address;
        }
    private:
        uint8_t * _data; // a pointer to memory allocated chunk
        uint8_t * _alignedData; // aligned pointer for SIMD access
        std::mutex _lock;

        // a map which holds an information about allocated memory in preallocated memory chunk
        // first parameter is an offset from preallocated memory, second parameter is a power of 2 (level)
        std::map <size_t, uint8_t> _allocatedChunk;

        // true memory allocation on CPU
        virtual void _allocate( size_t size )
        {
            _lock.lock();
            if ( _size != size && size > 0 ) {
                if ( !_allocatedChunk.empty() )
                    throw std::logic_error( "Cannot free a memory on CPU. Not all objects were previously deallocated from allocator." );

                _free();

                const size_t alignment = 32u; // AVX alignment requirement
                _data = new uint8_t[size + alignment];
                const std::uintptr_t dataAddress = reinterpret_cast<std::uintptr_t>( _data );
                _alignedData = ( ( dataAddress % alignment ) == 0 ) ? _data : _data + ( alignment - ( dataAddress % alignment ) );

                _size = size;
            }
            _lock.unlock();
        }

        // true memory deallocation on CPU
        virtual void _deallocate()
        {
            if ( _data != nullptr ) {
                delete[] _data;
                _data = nullptr;
                _alignedData = nullptr;
            }

            _allocatedChunk.clear();
        }

        MemoryAllocator( const MemoryAllocator & ) {}
        MemoryAllocator & operator=( const MemoryAllocator & ) { return (*this); }
    };
}


<|start_filename|>test/unit_tests/unit_tests.cpp<|end_filename|>
#include "unit_test_blob_detection.h"
#include "unit_test_edge_detection.h"
#include "unit_test_file.h"
#include "unit_test_fft.h"
#include "unit_test_framework.h"
#include "unit_test_helper.h"
#include "unit_test_image_buffer.h"
#include "unit_test_image_function.h"
#include "unit_test_math.h"

int main( int argc, char * argv[] )
{
    Unit_Test::setRunCount( argc, argv, 100 );

    cpu_Memory::MemoryAllocator::instance().reserve( 32 * 1024 * 1024 ); // reserve preallocated memory

    UnitTestFramework framework;
    addTests_Blob_Detection ( framework );
    addTests_Edge_Detection ( framework );
    addTests_File           ( framework );
    addTests_FFT            ( framework );
    addTests_Image_Buffer   ( framework );
    addTests_Image_Function ( framework );
    addTests_Math           ( framework );

    return framework.run();
}


<|start_filename|>test/performance_tests/cuda/performance_test_helper_cuda.cu<|end_filename|>
#include "performance_test_helper_cuda.cuh"
#include "../../../src/cuda/cuda_helper.cuh"

namespace
{
    void setCudaThreadCount( uint32_t threadCount )
    {
        multiCuda::CudaDeviceManager::instance().device().setThreadsPerBlock( threadCount );
    }

    uint32_t getMaximumCudaThreadCount()
    {
        return multiCuda::CudaDeviceManager::instance().device().maximumThreadsPerBlock();
    }
}

namespace Performance_Test
{
    namespace Cuda_Helper
    {
        TimerContainerCuda::TimerContainerCuda()
        {
            multiCuda::cudaCheck( cudaEventCreate( &_startEvent ) );
            multiCuda::cudaCheck( cudaEventCreate( &_stopEvent  ) );
        }

        TimerContainerCuda::~TimerContainerCuda()
        {
            multiCuda::cudaCheck( cudaEventDestroy( _startEvent ) );
            multiCuda::cudaCheck( cudaEventDestroy( _stopEvent  ) );
        }

        void TimerContainerCuda::start()
        {
            multiCuda::cudaCheck( cudaEventRecord( _startEvent, multiCuda::getCudaStream() ) );
        }

        void TimerContainerCuda::stop()
        {
            multiCuda::cudaCheck( cudaEventRecord( _stopEvent, multiCuda::getCudaStream() ) );
            multiCuda::cudaCheck( cudaEventSynchronize( _stopEvent ) );

            float time = 0.0f;

            multiCuda::cudaCheck( cudaEventElapsedTime( &time, _startEvent, _stopEvent ) );

            push( time );
        }

        std::pair < double, double > runPerformanceTestCuda( performanceFunctionCuda function, uint32_t size, uint32_t threadCountDivider )
        {
            setCudaThreadCount( getMaximumCudaThreadCount() / threadCountDivider );
            TimerContainerCuda timer;
            function(timer, size);
            return timer.mean();
        }

        penguinV::Image uniformImage( uint32_t width, uint32_t height )
        {
            return uniformImage( width, height, randomValue<uint8_t>( 256 ) );
        }

        penguinV::Image uniformImage( uint32_t width, uint32_t height, uint8_t value )
        {
            penguinV::ImageCuda image( width, height );

            image.fill( value );

            penguinV::Image imageOut;
            imageOut.swap( image );

            return imageOut;
        }

        std::vector<penguinV::Image> uniformImages( uint32_t count, uint32_t width, uint32_t height )
        {
            std::vector<penguinV::Image> image( count );

            for ( std::vector<penguinV::Image>::iterator im = image.begin(); im != image.end(); ++im )
                *im = uniformImage( width, height );

            return image;
        }
    }
}


<|start_filename|>src/filtering.h<|end_filename|>
#pragma once

#include <vector>
#include "image_buffer.h"

namespace Image_Function
{
    using namespace penguinV;

    Image Median( const Image & in, uint32_t kernelSize );
    void  Median( const Image & in, Image & out, uint32_t kernelSize );
    Image Median( const Image & in, uint32_t startXIn, uint32_t startYIn, uint32_t width, uint32_t height, uint32_t kernelSize );
    void  Median( const Image & in, uint32_t startXIn, uint32_t startYIn, Image & out, uint32_t startXOut, uint32_t startYOut,
                  uint32_t width, uint32_t height, uint32_t kernelSize );

    // This filter returns image based on gradient magnitude in both X and Y directions
    Image Prewitt( const Image & in );
    void  Prewitt( const Image & in, Image & out );
    Image Prewitt( const Image & in, uint32_t startXIn, uint32_t startYIn, uint32_t width, uint32_t height );
    void  Prewitt( const Image & in, uint32_t startXIn, uint32_t startYIn, Image & out, uint32_t startXOut, uint32_t startYOut,
                   uint32_t width, uint32_t height );

    // This filter returns image based on gradient magnitude in both X and Y directions
    Image Sobel( const Image & in );
    void  Sobel( const Image & in, Image & out );
    Image Sobel( const Image & in, uint32_t startXIn, uint32_t startYIn, uint32_t width, uint32_t height );
    void  Sobel( const Image & in, uint32_t startXIn, uint32_t startYIn, Image & out, uint32_t startXOut, uint32_t startYOut,
                 uint32_t width, uint32_t height );

    void GetGaussianKernel( std::vector<float> & filter, uint32_t width, uint32_t height, uint32_t kernelSize, float sigma );
}


<|start_filename|>src/opencl/opencl_memory.h<|end_filename|>
#pragma once

#if defined(__APPLE__) || defined(__MACOSX)
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif

#include <map>
#include "../memory/memory_allocator.h"

namespace multiCL
{
    // Class for memory allocation on OpenCL devices
    class MemoryAllocator : public BaseMemoryAllocator
    {
    public:
        MemoryAllocator( cl_context context, cl_device_id deviceId, size_t availableSpace )
            : _context          ( context )
            , _minimumSizeChunk ( 1 )
            , _data             ( NULL )
            , _availableSize    ( availableSpace ) 
        {
            const cl_int error = clGetDeviceInfo( deviceId, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(cl_uint), &_minimumSizeChunk, NULL );
            if ( error != CL_SUCCESS )
                throw std::logic_error( "Cannot get an information about minimum allocation size on OpenCL device" );
        }

        virtual ~MemoryAllocator()
        {
            _free();
        }

        // Returns a memory structure pointer to an allocated memory. If memory size of allocated memory chuck is enough for requested size
        // then assign a pointer to preallocated memory, otherwise allocate a new chuck of memory just for this pointer
        template <typename _DataType>
        cl_mem allocate( size_t size = 1 )
        {
            size = size * sizeof( _DataType );

            if ( _data != NULL && size < _size ) {
                const uint8_t level = _getAllocationLevel( size < _minimumSizeChunk ? _minimumSizeChunk : size );

                if ( _split( level ) ) {
                    cl_buffer_region region;
                    region.origin = *(_freeChunk[level].begin());
                    region.size = size;

                    cl_int error;
                    cl_mem memory = clCreateSubBuffer( _data, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, &region, &error );
                    if ( error != CL_SUCCESS )
                        throw std::logic_error( "Cannot allocate a subbuffer memory for OpenCL device" );

                    _allocatedChunk.insert( std::pair< cl_mem, std::pair < size_t, uint8_t > >( memory,  std::pair < size_t, uint8_t >(*(_freeChunk[level].begin()), level) ) );
                    _freeChunk[level].erase( _freeChunk[level].begin() );
                    return memory;
                }
            }

            // if no space is in preallocated memory just allocate as usual memory
            cl_int error;
            cl_mem memory = clCreateBuffer( _context, CL_MEM_READ_WRITE, size, NULL, &error);
            if ( error != CL_SUCCESS )
                throw std::logic_error( "Cannot allocate a memory for OpenCL device" );

            return memory;
        }

        // deallocates a memory by given memory structure pointer
        // if a pointer points on allocated chuck of memory inside the allocator then
        // the allocator just removes a reference to such area without any cost
        // otherwise OpenCL specific function will be called
        void free( cl_mem memory )
        {
            if ( _data != NULL ) {
                std::map < cl_mem, std::pair < size_t, uint8_t > >::iterator pos = _allocatedChunk.find( memory );

                if ( pos != _allocatedChunk.end() ) {
                    _freeChunk[pos->second.second].insert( pos->second.first );
                    _merge( pos->second.first, pos->second.second );
                    _allocatedChunk.erase( pos );
                }
            }

            if ( clReleaseMemObject( memory ) != CL_SUCCESS )
                throw std::logic_error( "Cannot deallocate a memory for OpenCL device" );
        }

        // returns maximum available space which could be allocated by allocator
        size_t availableSize() const
        {
            return _availableSize;
        }
    private:
        cl_context _context;
        cl_uint _minimumSizeChunk;
        cl_mem _data; // a pointer to memory allocated chunk
        const size_t _availableSize; // maximum available memory size

        // a map which holds an information about allocated memory in preallocated memory chunk
        // first paramter is a pointer to allocated memory in OpenCL terms
        // second parameter is an offset from preallocated memory
        // third parameter is a power of 2 (level)
        std::map < cl_mem, std::pair < size_t, uint8_t > > _allocatedChunk;

        // true memory allocation on OpenCL devices
        virtual void _allocate( size_t size )
        {
            if ( size > _availableSize )
                throw std::logic_error( "Memory size to be allocated is bigger than available size on device" );

            if ( _size != size && size > 0 ) {
                if ( !_allocatedChunk.empty() )
                    throw std::logic_error( "Cannot free a memory on OpenCL device. Not all objects were previously deallocated from allocator." );

                _free();

                cl_int error;
                _data = clCreateBuffer( _context, CL_MEM_READ_WRITE, size, NULL, &error);
                if ( error != CL_SUCCESS )
                    throw std::logic_error( "Cannot allocate a memory for OpenCL device" );

                _size = size;
            }
        }

        // true memory deallocation on OpenCL device
        virtual void _deallocate()
        {
            if ( _data != NULL ) {
                cl_int error = clReleaseMemObject( _data );
                if ( error != CL_SUCCESS )
                    throw std::logic_error( "Cannot deallocate a memory for OpenCL device" );
                _data = NULL;
            }

            _allocatedChunk.clear();
        }

        MemoryAllocator( const MemoryAllocator & allocator )
            : BaseMemoryAllocator( allocator )
            , _availableSize( 0 )
        {
        }
        MemoryAllocator & operator=( const MemoryAllocator & ) { return (*this); }
    };
}


<|start_filename|>test/performance_tests/cuda/Makefile<|end_filename|>
PWD := $(shell pwd)
LIB_DIR := $(PWD)/../../../src
PERFORMANCE_TEST_DIR := $(PWD)/..
TEST_DIR := $(PWD)/../..
SRCSCU :=  \
	$(LIB_DIR)/cuda/cuda_device.cu \
	$(LIB_DIR)/cuda/cuda_helper.cu \
	$(LIB_DIR)/cuda/image_function_cuda.cu \
	performance_test_helper_cuda.cu
SRCSCPP :=  \
	${LIB_DIR}/image_function_helper.cpp \
	${PERFORMANCE_TEST_DIR}/performance_test_framework.cpp \
	${PERFORMANCE_TEST_DIR}/performance_test_helper.cpp \
	${TEST_DIR}/test_helper.cpp \
	performance_tests_cuda.cpp \
	performance_test_image_function_cuda.cpp
TARGET := perfomance_tests_cuda

CXX := nvcc
LINKER := nvcc
INCDIRS := -I$(PWD) -I$(LIB_DIR) -I$(PERFORMANCE_TEST_DIR) -I$(TEST_DIR)
CXXFLAGS := -std=c++11 -O2 -Wno-deprecated-gpu-targets
BUILD_DIR=build
BIN := $(BUILD_DIR)/bin
OBJSCU := $(patsubst %.cu,%.o,$(SRCSCU))
OBJSCPP := $(patsubst %.cpp,%.o,$(SRCSCPP))
OBJFILES := $(addprefix $(BIN)/, $(foreach obj, $(OBJSCU), $(shell basename $(obj))))
OBJFILES += $(addprefix $(BIN)/, $(foreach obj, $(OBJSCPP), $(shell basename $(obj))))

all: $(BIN) $(TARGET)

$(BIN):
	@mkdir -p $(BIN)

$(TARGET): $(OBJFILES)
	$(LINKER) $^ -o $@

$(BIN)/%.o: $(LIB_DIR)/%.cu
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: $(LIB_DIR)/**/%.cu
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: $(PERFORMANCE_TEST_DIR)/%.cpp
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: $(TEST_DIR)/%.cpp
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@
	
$(BIN)/%.o: $(PERFORMANCE_TEST_DIR)/**/%.cpp
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: ./%.cu
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: ./**/%.cu
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: $(LIB_DIR)/%.cpp
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: $(LIB_DIR)/**/%.cpp
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: ./%.cpp
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

$(BIN)/%.o: ./**/%.cpp
	$(CXX) $(CXXFLAGS) $(INCDIRS) -c $< -o $@

run: $(TARGET)
	@echo "Running CUDA performance tests ..."
	@./$(TARGET)
clean:
	@rm -rf $(BUILD_DIR)


<|start_filename|>src/cuda/cuda_device.cuh<|end_filename|>
#pragma once

#include <list>
#include <string>
#include <vector>
#include "cuda_memory.cuh"

namespace multiCuda
{
    class CudaDeviceManager;
    class CudaStream;

    // This is a shortcut (facade) namespace to access memory allocator for CUDA devices
    namespace MemoryManager
    {
        // Returns memory allocator for current thread
        // By default it will return an allocator for device with ID = 0 otherwise an ID what is actual for current thread
        MemoryAllocator & memory();

        // Returns memory allocator for specified device ID
        MemoryAllocator & memory( int deviceId );
    }

    // This class represents a single CUDA device (videocard) in a system
    // An object of the class can only be contructed by CudaDeviceManager
    class CudaDevice
    {
    public:
        friend class CudaDeviceManager;

        ~CudaDevice();

        // Device information
        int deviceId() const;
        std::string name() const;
        size_t totalMemorySize() const; // total available memory in bytes
        std::string computeCapability() const; // compute capability or version of supported computations
        size_t sharedMemoryPerBlock() const; // maximum supported shared memory in bytes per block
        uint32_t threadsPerBlock() const; // current number of threads per block
        uint32_t maximumThreadsPerBlock() const; // maximum available number of threads per block
        dim3 blockDimension() const; // maximum number of threads per block
        dim3 dimensionSize() const; // maximum supported dimension size of block's grid
        int dmaEngineCount() const; // supported DMA engines count to execute copy operations concurrently with kernel execution

        // User defined settings
        void setThreadsPerBlock( uint32_t threadCount ); // limit number of threads per block. The value cannot be bigger than device's supported and it must be a miltiplier of 32

        // Device manipulation
        void synchronize(); // synchronize all operations on device with CPU

        size_t currentStreamId() const; // current stream ID which is used as a default value in stream() function
        void setCurrentStreamId( size_t streamId );

        CudaStream & stream(); // a reference to current stream
        const CudaStream & stream() const;

        CudaStream & stream( size_t streamId ); // a reference to stream with specified ID
        const CudaStream & stream( size_t streamId ) const;

        size_t streamCount() const; // total number of streams
        void setStreamCount( size_t streamCount );

        MemoryAllocator & allocator(); // memory allocator associated with device
        const MemoryAllocator & allocator() const;
    private:
        int _deviceId; // associated device ID
        cudaDeviceProp _deviceProperty; // full device properties taken from CUDA
        cudaDeviceProp _backupDeviceProperty; // backup version of device properties

        size_t _currentStreamId;
        std::vector< CudaStream * > _stream; // array of streams within the device

        MemoryAllocator * _allocator; // memory allocator on current device

        CudaDevice( int deviceId_ );
        CudaDevice( const CudaDevice & );
        CudaDevice & operator=( const CudaDevice & );

        void setActive(); // set device active for currect thread
    };

    // Manager class for all CUDA devices which are in the system
    class CudaDeviceManager
    {
    public:
        static CudaDeviceManager & instance();

        void initializeDevices(); // initializes all CUDA devices available in system
        void initializeDevice( int deviceId ); // initializes a CUDA device with specified ID
        void closeDevice( int deviceId ); // closes initialized CUDA device with specified ID
        void closeDevices(); // closes all CUDA devices initialized by manager

        int deviceCount() const; // initialized CUDA devices via manager
        int supportedDeviceCount() const; // maximum available CUDA devices in the system

        CudaDevice & device(); // returns CUDA device within current thread
        const CudaDevice & device() const; // returns CUDA device within current thread

        CudaDevice & device( int deviceId ); // returns CUDA device with specified ID
        const CudaDevice & device( int deviceId ) const; // returns CUDA device with specified ID

        void setActiveDevice( int deviceId ); // set CUDA device with specified ID as a active device in current thread

    private:
        CudaDeviceManager();
        ~CudaDeviceManager();

        int _supportedDeviceCount; // maximum available CUDA devices in the system
        std::list<CudaDevice *> _device; // a list of initialized CUDA devices
    };

    // A wrapper class for CUDA stream
    class CudaStream
    {
    public:
        CudaStream();
        ~CudaStream();

        void synchronize(); // synchronize CPU and this stream
        bool isFree(); // returns true if no operation is currently executed within the stream

        cudaStream_t id() const; // returns an ID used in kernel executions or memory operations

        void setCallback( cudaStreamCallback_t callbackFunction, void * data ); // sets callback function for stream

    private:
        cudaStream_t _id;
    };
}


<|start_filename|>test/test_helper.h<|end_filename|>
#pragma once

#include <cstdlib>
#include "../src/image_buffer.h"

namespace Test_Helper
{
    // Functions to generate images
    penguinV::Image uniformImage( uint32_t width = 0, uint32_t height = 0, const penguinV::Image & reference = penguinV::Image() );
    penguinV::Image uniformImage( uint8_t value, uint32_t width = 0, uint32_t height = 0, const penguinV::Image & reference = penguinV::Image() );
    penguinV::Image16Bit uniformImage16Bit( uint16_t value, uint32_t width = 0, uint32_t height = 0, const penguinV::Image16Bit & reference = penguinV::Image16Bit() );
    penguinV::Image uniformRGBImage( uint32_t width, uint32_t height );
    penguinV::Image uniformRGBImage( uint32_t width, uint32_t height, uint8_t value );
    penguinV::Image uniformRGBImage( const penguinV::Image & reference = penguinV::Image() );
    penguinV::Image uniformRGBImage( uint8_t value, const penguinV::Image & reference = penguinV::Image() );
    penguinV::Image uniformRGBAImage( uint32_t width, uint32_t height );
    penguinV::Image uniformRGBAImage( uint32_t width, uint32_t height, uint8_t value );
    penguinV::Image uniformRGBAImage( const penguinV::Image & reference = penguinV::Image() );
    penguinV::Image uniformRGBAImage( uint8_t value, const penguinV::Image & reference = penguinV::Image() );
    std::vector<penguinV::Image> uniformImages( uint32_t count, uint32_t width, uint32_t height );
    std::vector<penguinV::Image> uniformRGBImages( uint32_t count, uint32_t width, uint32_t height );
    std::vector<penguinV::Image> uniformImages( uint32_t images, const penguinV::Image & reference = penguinV::Image() );
    std::vector<penguinV::Image> uniformImages( const std::vector<uint8_t> & intensityValue, const penguinV::Image & reference = penguinV::Image() );
    penguinV::Image randomImage( uint32_t width = 0, uint32_t height = 0 );
    penguinV::Image randomRGBImage( const penguinV::Image & reference = penguinV::Image() );
    penguinV::Image randomImage( const std::vector<uint8_t> & value );

    // Iteration count for tests
    uint32_t runCount(); // fixed value for all test loops
    void setRunCount( int argc, char* argv[], uint32_t count );

    // Return random value for specific range or variable type
    template <typename data>
    data randomValue( uint32_t maximum )
    {
        if( maximum == 0 )
            return 0;
        else
            return static_cast<data>(static_cast<uint32_t>(rand()) % maximum);
    }

    template <typename data>
    data randomValue( data minimum, uint32_t maximum )
    {
        if( maximum == 0 ) {
            return 0;
        }
        else {
            data value = static_cast<data>(static_cast<uint32_t>(rand()) % maximum);

            if( value < minimum )
                value = minimum;

            return value;
        }
    }
}


<|start_filename|>test/performance_tests/opencl/performance_tests_opencl.cpp<|end_filename|>
#include <iostream>
#include "performance_test_image_function_opencl.h"
#include "../performance_test_framework.h"
#include "../performance_test_helper.h"
#include "../../../src/opencl/opencl_device.h"
#include "../../../src/opencl/opencl_helper.h"

int main( int argc, char * argv[] )
{
    if( !multiCL::isOpenCLSupported() ) {
        std::cout << "No GPU devices in the system" << std::endl;
        return 0;
    }

    Performance_Test::setRunCount( argc, argv, 128 );

    multiCL::OpenCLDeviceManager & deviceManager = multiCL::OpenCLDeviceManager::instance();
    deviceManager.initializeDevices();

    for ( uint32_t deviceId = 0; deviceId < deviceManager.deviceCount(); ++deviceId ) {
        deviceManager.setActiveDevice( deviceId );

        const multiCL::OpenCLDevice & device = deviceManager.device();
        std::cout << device.name() << ": " << device.computeCapability() << std::endl;

        multiCL::MemoryManager::memory().reserve( 32 * 1024 * 1024 ); // preallocate memory (32 MB)

        PerformanceTestFramework framework;
        addTests_Image_Function_OpenCL( framework );

        framework.run();
    }

    return 0;
}


<|start_filename|>src/ui/qt/qt_ui.cpp<|end_filename|>
#include "qt_ui.h"
#include <QImage>
#include <QPainter>
#include <QString>

UiWindowQt::UiWindowQt( const penguinV::Image & image, const std::string & title )
    : UiWindow( image, title )
{
    const QImage imageQt( _image.data(), static_cast<int>( _image.width() ), static_cast<int>( _image.height() ),
                          static_cast<int>( _image.rowSize() ), (_image.colorCount() == 1u) ? QImage::Format_Grayscale8 : QImage::Format_RGB888 );
    _pixmap = QPixmap::fromImage( imageQt );
    _window.setPixmap( _pixmap );
    _window.window()->setWindowTitle( QString::fromStdString( _title ) );
}

UiWindowQt::~UiWindowQt()
{
}

void UiWindowQt::_display()
{
    if ( !_shown ) // we don't need to display anything
        return;

    _window.show();
}

void UiWindowQt::drawPoint( const Point2d & point, const PaintColor & color )
{
    QPainter paint( &_pixmap );
    paint.setPen( QColor( color.red, color.green, color.blue, color.alpha ) );
    paint.drawPoint( static_cast<int>(point.x), static_cast<int>(point.y) );

    _window.setPixmap( _pixmap );
    _display();
}

void UiWindowQt::drawLine( const Point2d & start, const Point2d & end, const PaintColor & color )
{
    QPainter paint( &_pixmap );
    paint.setPen( QColor( color.red, color.green, color.blue, color.alpha ) );
    paint.drawLine( static_cast<int>(start.x), static_cast<int>(start.y), static_cast<int>(end.x), static_cast<int>(end.y) );

    _window.setPixmap( _pixmap );
    _display();
}

void UiWindowQt::drawEllipse( const Point2d & center, double xRadius, double yRadius, const PaintColor & color )
{
    QPainter paint( &_pixmap );
    paint.setPen( QColor( color.red, color.green, color.blue, color.alpha ) );
    paint.drawEllipse( QPointF(center.x, center.y), xRadius, yRadius );
    _window.setPixmap( _pixmap );
    _display();
}

void UiWindowQt::drawRectangle( const Point2d & topLeftCorner, double width, double height, const PaintColor & color )
{
    QPainter paint( &_pixmap );
    paint.setPen( QColor( color.red, color.green, color.blue, color.alpha ) );
    paint.drawRect( static_cast<int>(topLeftCorner.x), static_cast<int>(topLeftCorner.y),
                    static_cast<int>(width), static_cast<int>(height) );

    _window.setPixmap( _pixmap );
    _display();
}


<|start_filename|>src/ui/ui.cpp<|end_filename|>
#include "ui.h"

UiWindow::UiWindow( const penguinV::Image & image, const std::string & title )
    : _image( image )
    , _title( title )
    , _shown( false )
{
}

UiWindow::~UiWindow()
{
}

void UiWindow::show()
{
    _shown = true;
    _display();
}

void UiWindow::setImage( const penguinV::Image & image )
{
    _image = image;
    _display();
}

void UiWindow::drawPoint( const Point2d &, const PaintColor & )
{
    _display();
}

void UiWindow::drawLine( const Point2d &, const Point2d &, const PaintColor & )
{
    _display();
}

void UiWindow::drawEllipse( const Point2d &, double, double, const PaintColor & )
{
    _display();
}

void UiWindow::drawRectangle( const Point2d &, double, double, const PaintColor & )
{
    _display();
}

void UiWindow::_display()
{
}


<|start_filename|>examples/image_function/example_image_function.cpp<|end_filename|>
// Example application of library utilization
#include <iostream>
#include "../../src/image_buffer.h"
#include "../../src/image_function.h"

void example1( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut );
void example2( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut );
void example3( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut );
void example4( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut );

int main()
{
    // This example is to show how you can perform bitwise operations on gray-scale images
    //
    // Conditions:
    // We are in the middle of very serious image processing algorithm development
    //
    // We have 2 input images and 1 output image with known sizes:
    // - first input image is 1024 x 1024 pixels
    // - second input image is 2048 x 2048 pixels
    // - output image (where we would like to store results) is 512 x 512 pixel
    //
    // We have to make bitwise OR on 2 input images and store result in output image
    // We know that the area in first input image has coordinates { [10, 10], [138, 138] },
    // second input image - { [650, 768], [778, 896] },
    // and we need to put result into area { [0, 0], [128, 128] } in output image
    //
    // So let's do it!

    try // <---- do not forget to put your code into try.. catch block!
    {
        // create image objects with certain sizes

        penguinV::Image imageIn1( 1024, 1024 );
        penguinV::Image imageIn2( 2048, 2048 );
        penguinV::Image imageOut( 512, 512 );

        // set any data because initially images contain some uninitialized garbage
        // (we assume that this step you do not need to do during real development of image processing algorithms)
        imageIn1.fill( 255 );
        imageIn2.fill( 128 );
        imageOut.fill( 0 );

        // Now we need to make bitwise operation OR
        // First way to do
        example1( imageIn1, imageIn2, imageOut );

        // Second way to do
        example2( imageIn1, imageIn2, imageOut );

        // Third way to do
        example3( imageIn1, imageIn2, imageOut );

        // Forth way to do
        example4( imageIn1, imageIn2, imageOut );
    }
    catch( const std::exception & ex ) { // uh-oh, something went wrong!
        std::cout << "Exception " << ex.what() << " raised. Closing the application..." << std::endl;
        return 1;
    }
    catch( ... ) { // uh-oh, something terrible happen!
        std::cout << "Generic exception raised. Closing the application..." << std::endl;
        return 2;
    }

    std::cout << "Application ended correctly." << std::endl;
    return 0;
}


void example1( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut )
{
    // We allocate another images with size 128 x 128
    penguinV::Image croppedIn1( 128, 128 );
    penguinV::Image croppedIn2( 128, 128 );
    penguinV::Image croppedOut( 128, 128 );

    // Copy information from input images to cropped images

    // It is not a good style of programming but it is easy to explain all parameters!
    Image_Function::Copy( imageIn1,   // first input image
                          10,         // X coordinate where we get information from first input image
                          10,         // Y coordinate where we get information from first input image
                          croppedIn1, // first cropped image
                          0,          // X coordinate where we put information to first cropped image
                          0,          // Y coordinate where we put information to first cropped image
                          128,        // width of copying area
                          128         // height of copying area
    );

    Image_Function::Copy( imageIn2,   // second input image
                          650,        // X coordinate where we get information from second input image
                          768,        // Y coordinate where we get information from second input image
                          croppedIn1, // second cropped image
                          0,          // X coordinate where we put information to second cropped image
                          0,          // Y coordinate where we put information to second cropped image
                          128,        // width of copying area
                          128         // height of copying area
    );

    // Do Bitwise OR
    Image_Function::BitwiseOr( croppedIn1, croppedIn2, croppedOut );

    // Copy the result into output image
    Image_Function::Copy( croppedOut, // cropped output image
                          0,          // X coordinate where we get information from cropped output image
                          0,          // Y coordinate where we get information from cropped output image
                          imageOut,   // output image
                          0,          // X coordinate where we put information to output image
                          0,          // Y coordinate where we put information to output image
                          128,        // width of copying area
                          128         // height of copying area
    );
}

void example2( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut )
{
    // We allocate another images with size 128 x 128
    penguinV::Image croppedIn1( 128, 128 );
    penguinV::Image croppedIn2( 128, 128 );

    // Copy information from input images to cropped images

    Image_Function::Copy( imageIn1,   // first input image
                          10,         // X coordinate where we get information from first input image
                          10,         // Y coordinate where we get information from first input image
                          croppedIn1, // first cropped image
                          0,          // X coordinate where we put information to first cropped image
                          0,          // Y coordinate where we put information to first cropped image
                          128,        // width of copying area
                          128         // height of copying area
    );

    Image_Function::Copy( imageIn2,   // second input image
                          650,        // X coordinate where we get information from second input image
                          768,        // Y coordinate where we get information from second input image
                          croppedIn1, // second cropped image
                          0,          // X coordinate where we put information to second cropped image
                          0,          // Y coordinate where we put information to second cropped image
                          128,        // width of copying area
                          128         // height of copying area
    );

    // Do Bitwise OR and store result in cropped output image (move operator)
    penguinV::Image croppedOut = Image_Function::BitwiseOr( croppedIn1, croppedIn2 );

    // Copy the result into output image
    Image_Function::Copy( croppedOut, // cropped output image
                          0,          // X coordinate where we get information from cropped output image
                          0,          // Y coordinate where we get information from cropped output image
                          imageOut,   // output image
                          0,          // X coordinate where we put information to output image
                          0,          // Y coordinate where we put information to output image
                          128,        // width of copying area
                          128         // height of copying area
    );
}

void example3( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut )
{
    // Do Bitwise OR and store result in cropped output image (move operator)
    penguinV::Image croppedOut = Image_Function::BitwiseOr( imageIn1, // first input image
                                                            10,       // X coordinate of first input image area
                                                            10,       // Y coordinate of first input image area
                                                            imageIn2, // second input image
                                                            650,      // X coordinate of second input image area
                                                            768,      // Y coordinate of second input image area
                                                            128,      // width of the area
                                                            128       // height of the area
    );

    // Copy the result into output image
    Image_Function::Copy( croppedOut, // cropped output image
                          0,          // X coordinate where we get information from cropped output image
                          0,          // Y coordinate where we get information from cropped output image
                          imageOut,   // output image
                          0,          // X coordinate where we put information to output image
                          0,          // Y coordinate where we put information to output image
                          128,        // width of copying area
                          128         // height of copying area
    );
}

void example4( const penguinV::Image & imageIn1, const penguinV::Image & imageIn2, penguinV::Image & imageOut )
{
    Image_Function::BitwiseOr( imageIn1, // first input image
                               10,       // X coordinate of first input image area
                               10,       // Y coordinate of first input image area
                               imageIn2, // second input image
                               650,      // X coordinate of second input image area
                               768,      // Y coordinate of second input image area
                               imageOut, // output image
                               0,        // X coordinate of output image area
                               0,        // Y coordinate of output image area
                               128,      // width of the area
                               128       // height of the area
    );
    // And that's all
}


<|start_filename|>src/ui/qt/qt_ui.h<|end_filename|>
#pragma once
#include "../ui.h"

#include <QLabel>
#include <QPixmap>

class UiWindowQt : public UiWindow
{
public:
    explicit UiWindowQt( const penguinV::Image & image = penguinV::Image(), const std::string & title = std::string() );
    virtual ~UiWindowQt();

    virtual void drawPoint( const Point2d & point, const PaintColor & color );
    virtual void drawLine( const Point2d & start, const Point2d & end, const PaintColor & color );
    virtual void drawEllipse( const Point2d & center, double xRadius, double yRadius, const PaintColor & color );
    virtual void drawRectangle( const Point2d & topLeftCorner, double width, double height, const PaintColor & color );
protected:
    virtual void _display();
private:
    QPixmap _pixmap;
    QLabel _window;
};


<|start_filename|>src/tool/light_correction.h<|end_filename|>
#pragma once

#include <vector>
#include "../image_buffer.h"
#include "../math/math_base.h"

// Input image for analysis should not contain pixel intensity values 0 or 255
// If an image contains pixels with such values they would be ignored during correction
class LightCorrection
{
public:
    void analyze( const penguinV::Image & image );
    void correct( penguinV::Image & image ) const;
    void correct( penguinV::Image & image, uint32_t x, uint32_t y, uint32_t width, uint32_t height ) const;

    // Returns an array of pixel coordinates on which pixel intensity equal to 0 or 255
    std::vector< PointBase2D< uint32_t > > findIncorrectPixels( const penguinV::Image & image ) const;

private:
    std::vector< uint32_t > _data;
    uint32_t _width;
    uint32_t _height;
};
